Merge
This commit is contained in:
commit
bf0670e111
@ -183,10 +183,22 @@ JAVA_JAVA_java = \
|
||||
java/util/MissingFormatWidthException.java \
|
||||
java/util/UnknownFormatConversionException.java \
|
||||
java/util/UnknownFormatFlagsException.java \
|
||||
java/util/IllformedLocaleException.java \
|
||||
java/util/FormatterClosedException.java \
|
||||
java/util/ListResourceBundle.java \
|
||||
sun/util/EmptyListResourceBundle.java \
|
||||
java/util/Locale.java \
|
||||
sun/util/locale/AsciiUtil.java \
|
||||
sun/util/locale/BaseLocale.java \
|
||||
sun/util/locale/Extension.java \
|
||||
sun/util/locale/InternalLocaleBuilder.java \
|
||||
sun/util/locale/LanguageTag.java \
|
||||
sun/util/locale/LocaleExtensions.java \
|
||||
sun/util/locale/LocaleObjectCache.java \
|
||||
sun/util/locale/LocaleSyntaxException.java \
|
||||
sun/util/locale/ParseStatus.java \
|
||||
sun/util/locale/StringTokenIterator.java \
|
||||
sun/util/locale/UnicodeLocaleExtension.java \
|
||||
java/util/LocaleISOData.java \
|
||||
sun/util/LocaleServiceProviderPool.java \
|
||||
sun/util/LocaleDataMetaInfo.java \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2010, 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
|
||||
@ -31,13 +31,14 @@ import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.applet.Applet;
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Window;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.RepaintManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* A collection of utility methods for Swing.
|
||||
@ -91,7 +92,7 @@ public class SwingUtilities3 {
|
||||
*/
|
||||
public static void setVsyncRequested(Container rootContainer,
|
||||
boolean isRequested) {
|
||||
assert SwingUtilities.getRoot(rootContainer) == rootContainer;
|
||||
assert (rootContainer instanceof Applet) || (rootContainer instanceof Window);
|
||||
if (isRequested) {
|
||||
vsyncedMap.put(rootContainer, Boolean.TRUE);
|
||||
} else {
|
||||
@ -106,7 +107,7 @@ public class SwingUtilities3 {
|
||||
* @return {@code true} if vsync painting is requested for {@code rootContainer}
|
||||
*/
|
||||
public static boolean isVsyncRequested(Container rootContainer) {
|
||||
assert SwingUtilities.getRoot(rootContainer) == rootContainer;
|
||||
assert (rootContainer instanceof Applet) || (rootContainer instanceof Window);
|
||||
return Boolean.TRUE == vsyncedMap.get(rootContainer);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2010, 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
|
||||
@ -399,7 +399,7 @@ class GTKPainter extends SynthPainter {
|
||||
}
|
||||
|
||||
String detail = "arrow";
|
||||
if (name == "ScrollBar.button") {
|
||||
if ((name == "ScrollBar.button") || (name == "TabbedPane.button")) {
|
||||
if (arrowType == ArrowType.UP || arrowType == ArrowType.DOWN) {
|
||||
detail = "vscrollbar";
|
||||
} else {
|
||||
@ -409,7 +409,7 @@ class GTKPainter extends SynthPainter {
|
||||
name == "Spinner.previousButton") {
|
||||
detail = "spinbutton";
|
||||
} else if (name != "ComboBox.arrowButton") {
|
||||
assert false;
|
||||
assert false : "unexpected name: " + name;
|
||||
}
|
||||
|
||||
int gtkState = GTKLookAndFeel.synthStateToGTKState(
|
||||
@ -436,7 +436,7 @@ class GTKPainter extends SynthPainter {
|
||||
String name = button.getName();
|
||||
String detail = "button";
|
||||
int direction = SwingConstants.CENTER;
|
||||
if (name == "ScrollBar.button") {
|
||||
if ((name == "ScrollBar.button") || (name == "TabbedPane.button")) {
|
||||
Integer prop = (Integer)
|
||||
button.getClientProperty("__arrow_direction__");
|
||||
direction = (prop != null) ?
|
||||
@ -457,7 +457,7 @@ class GTKPainter extends SynthPainter {
|
||||
} else if (name == "Spinner.nextButton") {
|
||||
detail = "spinbutton_up";
|
||||
} else if (name != "ComboBox.arrowButton") {
|
||||
assert false;
|
||||
assert false : "unexpected name: " + name;
|
||||
}
|
||||
|
||||
int state = context.getComponentState();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2010, 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
|
||||
@ -40,8 +40,6 @@ import javax.sound.sampled.AudioFormat.Encoding;
|
||||
*/
|
||||
public abstract class AudioFloatConverter {
|
||||
|
||||
public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* LSB Filter, used filter least significant byte in samples arrays.
|
||||
@ -982,7 +980,7 @@ public abstract class AudioFloatConverter {
|
||||
format.getSampleSizeInBits() + 7) / 8) - 4);
|
||||
}
|
||||
}
|
||||
} else if (format.getEncoding().equals(PCM_FLOAT)) {
|
||||
} else if (format.getEncoding().equals(Encoding.PCM_FLOAT)) {
|
||||
if (format.getSampleSizeInBits() == 32) {
|
||||
if (format.isBigEndian())
|
||||
conv = new AudioFloatConversion32B();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2010, 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
|
||||
@ -175,7 +175,6 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
for (int c = 0; c < targetChannels; c++) {
|
||||
for (int i = 0, ix = off + c; i < len2; i++, ix += cs) {
|
||||
b[ix] = conversion_buffer[i];
|
||||
;
|
||||
}
|
||||
}
|
||||
} else if (targetChannels == 1) {
|
||||
@ -186,7 +185,6 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
for (int c = 1; c < sourceChannels; c++) {
|
||||
for (int i = c, ix = off; i < len2; i += cs, ix++) {
|
||||
b[ix] += conversion_buffer[i];
|
||||
;
|
||||
}
|
||||
}
|
||||
float vol = 1f / ((float) sourceChannels);
|
||||
@ -390,6 +388,7 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
return -1;
|
||||
if (len < 0)
|
||||
return 0;
|
||||
int offlen = off + len;
|
||||
int remain = len / nrofchannels;
|
||||
int destPos = 0;
|
||||
int in_end = ibuffer_len;
|
||||
@ -423,7 +422,7 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
for (int c = 0; c < nrofchannels; c++) {
|
||||
int ix = 0;
|
||||
float[] buff = cbuffer[c];
|
||||
for (int i = c; i < b.length; i += nrofchannels) {
|
||||
for (int i = c + off; i < offlen; i += nrofchannels) {
|
||||
b[i] = buff[ix++];
|
||||
}
|
||||
}
|
||||
@ -447,7 +446,7 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
}
|
||||
|
||||
public long skip(long len) throws IOException {
|
||||
if (len > 0)
|
||||
if (len < 0)
|
||||
return 0;
|
||||
if (skipbuffer == null)
|
||||
skipbuffer = new float[1024 * targetFormat.getFrameSize()];
|
||||
@ -470,7 +469,7 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
}
|
||||
|
||||
private Encoding[] formats = { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
|
||||
AudioFloatConverter.PCM_FLOAT };
|
||||
Encoding.PCM_FLOAT };
|
||||
|
||||
public AudioInputStream getAudioInputStream(Encoding targetEncoding,
|
||||
AudioInputStream sourceStream) {
|
||||
@ -482,7 +481,7 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
float samplerate = format.getSampleRate();
|
||||
int bits = format.getSampleSizeInBits();
|
||||
boolean bigendian = format.isBigEndian();
|
||||
if (targetEncoding.equals(AudioFloatConverter.PCM_FLOAT))
|
||||
if (targetEncoding.equals(Encoding.PCM_FLOAT))
|
||||
bits = 32;
|
||||
AudioFormat targetFormat = new AudioFormat(encoding, samplerate, bits,
|
||||
channels, channels * bits / 8, samplerate, bigendian);
|
||||
@ -521,19 +520,19 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
|
||||
public Encoding[] getSourceEncodings() {
|
||||
return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
|
||||
AudioFloatConverter.PCM_FLOAT };
|
||||
Encoding.PCM_FLOAT };
|
||||
}
|
||||
|
||||
public Encoding[] getTargetEncodings() {
|
||||
return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
|
||||
AudioFloatConverter.PCM_FLOAT };
|
||||
Encoding.PCM_FLOAT };
|
||||
}
|
||||
|
||||
public Encoding[] getTargetEncodings(AudioFormat sourceFormat) {
|
||||
if (AudioFloatConverter.getConverter(sourceFormat) == null)
|
||||
return new Encoding[0];
|
||||
return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
|
||||
AudioFloatConverter.PCM_FLOAT };
|
||||
Encoding.PCM_FLOAT };
|
||||
}
|
||||
|
||||
public AudioFormat[] getTargetFormats(Encoding targetEncoding,
|
||||
@ -572,17 +571,17 @@ public class AudioFloatFormatConverter extends FormatConversionProvider {
|
||||
}
|
||||
}
|
||||
|
||||
if (targetEncoding.equals(AudioFloatConverter.PCM_FLOAT)) {
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
if (targetEncoding.equals(Encoding.PCM_FLOAT)) {
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
|
||||
AudioSystem.NOT_SPECIFIED, false));
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
|
||||
AudioSystem.NOT_SPECIFIED, true));
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
|
||||
AudioSystem.NOT_SPECIFIED, false));
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
|
||||
AudioSystem.NOT_SPECIFIED, true));
|
||||
}
|
||||
|
@ -42,11 +42,14 @@ public class AudioSynthesizerPropertyInfo {
|
||||
*/
|
||||
public AudioSynthesizerPropertyInfo(String name, Object value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
if (value instanceof Class)
|
||||
valueClass = (Class)value;
|
||||
else if (value != null)
|
||||
valueClass = value.getClass();
|
||||
else
|
||||
{
|
||||
this.value = value;
|
||||
if (value != null)
|
||||
valueClass = value.getClass();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The name of the property.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2010, 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
|
||||
@ -781,7 +781,7 @@ public class DLSSoundbank implements Soundbank {
|
||||
}
|
||||
if (sampleformat == 3) {
|
||||
audioformat = new AudioFormat(
|
||||
AudioFloatConverter.PCM_FLOAT, samplerate, bits,
|
||||
Encoding.PCM_FLOAT, samplerate, bits,
|
||||
channels, framesize, samplerate, false);
|
||||
}
|
||||
|
||||
@ -965,7 +965,7 @@ public class DLSSoundbank implements Soundbank {
|
||||
sampleformat = 1;
|
||||
else if (audioformat.getEncoding().equals(Encoding.PCM_SIGNED))
|
||||
sampleformat = 1;
|
||||
else if (audioformat.getEncoding().equals(AudioFloatConverter.PCM_FLOAT))
|
||||
else if (audioformat.getEncoding().equals(Encoding.PCM_FLOAT))
|
||||
sampleformat = 3;
|
||||
|
||||
fmt_chunk.writeUnsignedShort(sampleformat);
|
||||
|
@ -205,7 +205,8 @@ public class ModelByteBufferWavetable implements ModelWavetable {
|
||||
}
|
||||
if (buffer.array() == null) {
|
||||
return AudioFloatInputStream.getInputStream(new AudioInputStream(
|
||||
buffer.getInputStream(), format, buffer.capacity()));
|
||||
buffer.getInputStream(), format,
|
||||
buffer.capacity() / format.getFrameSize()));
|
||||
}
|
||||
if (buffer8 != null) {
|
||||
if (format.getEncoding().equals(Encoding.PCM_SIGNED)
|
||||
|
@ -56,7 +56,7 @@ public abstract class ModelInstrument extends Instrument {
|
||||
|
||||
public ModelDirector getDirector(ModelPerformer[] performers,
|
||||
MidiChannel channel, ModelDirectedPlayer player) {
|
||||
return new ModelStandardDirector(performers, player);
|
||||
return new ModelStandardIndexedDirector(performers, player);
|
||||
}
|
||||
|
||||
public ModelPerformer[] getPerformers() {
|
||||
|
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.sun.media.sound;
|
||||
|
||||
/**
|
||||
* A standard indexed director who chooses performers
|
||||
* by there keyfrom,keyto,velfrom,velto properties.
|
||||
*
|
||||
* @author Karl Helgason
|
||||
*/
|
||||
public class ModelStandardIndexedDirector implements ModelDirector {
|
||||
|
||||
ModelPerformer[] performers;
|
||||
ModelDirectedPlayer player;
|
||||
boolean noteOnUsed = false;
|
||||
boolean noteOffUsed = false;
|
||||
|
||||
// Variables needed for index
|
||||
byte[][] trantables;
|
||||
int[] counters;
|
||||
int[][] mat;
|
||||
|
||||
public ModelStandardIndexedDirector(ModelPerformer[] performers,
|
||||
ModelDirectedPlayer player) {
|
||||
this.performers = performers;
|
||||
this.player = player;
|
||||
for (int i = 0; i < performers.length; i++) {
|
||||
ModelPerformer p = performers[i];
|
||||
if (p.isReleaseTriggered()) {
|
||||
noteOffUsed = true;
|
||||
} else {
|
||||
noteOnUsed = true;
|
||||
}
|
||||
}
|
||||
buildindex();
|
||||
}
|
||||
|
||||
private int[] lookupIndex(int x, int y) {
|
||||
if ((x >= 0) && (x < 128) && (y >= 0) && (y < 128)) {
|
||||
int xt = trantables[0][x];
|
||||
int yt = trantables[1][y];
|
||||
if (xt != -1 && yt != -1) {
|
||||
return mat[xt + yt * counters[0]];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int restrict(int value) {
|
||||
if(value < 0) return 0;
|
||||
if(value > 127) return 127;
|
||||
return value;
|
||||
}
|
||||
|
||||
private void buildindex() {
|
||||
trantables = new byte[2][129];
|
||||
counters = new int[trantables.length];
|
||||
for (ModelPerformer performer : performers) {
|
||||
int keyFrom = performer.getKeyFrom();
|
||||
int keyTo = performer.getKeyTo();
|
||||
int velFrom = performer.getVelFrom();
|
||||
int velTo = performer.getVelTo();
|
||||
if (keyFrom > keyTo) continue;
|
||||
if (velFrom > velTo) continue;
|
||||
keyFrom = restrict(keyFrom);
|
||||
keyTo = restrict(keyTo);
|
||||
velFrom = restrict(velFrom);
|
||||
velTo = restrict(velTo);
|
||||
trantables[0][keyFrom] = 1;
|
||||
trantables[0][keyTo + 1] = 1;
|
||||
trantables[1][velFrom] = 1;
|
||||
trantables[1][velTo + 1] = 1;
|
||||
}
|
||||
for (int d = 0; d < trantables.length; d++) {
|
||||
byte[] trantable = trantables[d];
|
||||
int transize = trantable.length;
|
||||
for (int i = transize - 1; i >= 0; i--) {
|
||||
if (trantable[i] == 1) {
|
||||
trantable[i] = -1;
|
||||
break;
|
||||
}
|
||||
trantable[i] = -1;
|
||||
}
|
||||
int counter = -1;
|
||||
for (int i = 0; i < transize; i++) {
|
||||
if (trantable[i] != 0) {
|
||||
counter++;
|
||||
if (trantable[i] == -1)
|
||||
break;
|
||||
}
|
||||
trantable[i] = (byte) counter;
|
||||
}
|
||||
counters[d] = counter;
|
||||
}
|
||||
mat = new int[counters[0] * counters[1]][];
|
||||
int ix = 0;
|
||||
for (ModelPerformer performer : performers) {
|
||||
int keyFrom = performer.getKeyFrom();
|
||||
int keyTo = performer.getKeyTo();
|
||||
int velFrom = performer.getVelFrom();
|
||||
int velTo = performer.getVelTo();
|
||||
if (keyFrom > keyTo) continue;
|
||||
if (velFrom > velTo) continue;
|
||||
keyFrom = restrict(keyFrom);
|
||||
keyTo = restrict(keyTo);
|
||||
velFrom = restrict(velFrom);
|
||||
velTo = restrict(velTo);
|
||||
int x_from = trantables[0][keyFrom];
|
||||
int x_to = trantables[0][keyTo + 1];
|
||||
int y_from = trantables[1][velFrom];
|
||||
int y_to = trantables[1][velTo + 1];
|
||||
if (x_to == -1)
|
||||
x_to = counters[0];
|
||||
if (y_to == -1)
|
||||
y_to = counters[1];
|
||||
for (int y = y_from; y < y_to; y++) {
|
||||
int i = x_from + y * counters[0];
|
||||
for (int x = x_from; x < x_to; x++) {
|
||||
int[] mprev = mat[i];
|
||||
if (mprev == null) {
|
||||
mat[i] = new int[] { ix };
|
||||
} else {
|
||||
int[] mnew = new int[mprev.length + 1];
|
||||
mnew[mnew.length - 1] = ix;
|
||||
for (int k = 0; k < mprev.length; k++)
|
||||
mnew[k] = mprev[k];
|
||||
mat[i] = mnew;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
public void noteOff(int noteNumber, int velocity) {
|
||||
if (!noteOffUsed)
|
||||
return;
|
||||
int[] plist = lookupIndex(noteNumber, velocity);
|
||||
if(plist == null) return;
|
||||
for (int i : plist) {
|
||||
ModelPerformer p = performers[i];
|
||||
if (p.isReleaseTriggered()) {
|
||||
player.play(i, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void noteOn(int noteNumber, int velocity) {
|
||||
if (!noteOnUsed)
|
||||
return;
|
||||
int[] plist = lookupIndex(noteNumber, velocity);
|
||||
if(plist == null) return;
|
||||
for (int i : plist) {
|
||||
ModelPerformer p = performers[i];
|
||||
if (!p.isReleaseTriggered()) {
|
||||
player.play(i, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2010, 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
|
||||
@ -116,7 +116,7 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
|
||||
protected int tuning_program = 0;
|
||||
protected SoftInstrument current_instrument = null;
|
||||
protected ModelChannelMixer current_mixer = null;
|
||||
private ModelDirector current_director = null;
|
||||
protected ModelDirector current_director = null;
|
||||
|
||||
// Controller Destination Settings
|
||||
protected int cds_control_number = -1;
|
||||
@ -1264,13 +1264,16 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
|
||||
}
|
||||
|
||||
public void programChange(int bank, int program) {
|
||||
bank = restrict7Bit(bank);
|
||||
bank = restrict14Bit(bank);
|
||||
program = restrict7Bit(program);
|
||||
synchronized (control_mutex) {
|
||||
mainmixer.activity();
|
||||
this.bank = bank;
|
||||
this.program = program;
|
||||
current_instrument = null;
|
||||
if(this.bank != bank || this.program != program)
|
||||
{
|
||||
this.bank = bank;
|
||||
this.program = program;
|
||||
current_instrument = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2010, 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
|
||||
@ -118,16 +118,16 @@ public class SoftMixingMixer implements Mixer {
|
||||
AudioSystem.NOT_SPECIFIED, bits, channels, channels
|
||||
* bits / 8, AudioSystem.NOT_SPECIFIED, true));
|
||||
}
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
|
||||
AudioSystem.NOT_SPECIFIED, false));
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
|
||||
AudioSystem.NOT_SPECIFIED, true));
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
|
||||
AudioSystem.NOT_SPECIFIED, false));
|
||||
formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
formats.add(new AudioFormat(Encoding.PCM_FLOAT,
|
||||
AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
|
||||
AudioSystem.NOT_SPECIFIED, true));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2010, 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,16 +25,25 @@
|
||||
|
||||
package com.sun.media.sound;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.security.AccessControlException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import javax.sound.midi.Instrument;
|
||||
import javax.sound.midi.MidiChannel;
|
||||
@ -182,6 +191,7 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
// 1: DLS Voice Allocation
|
||||
protected int voice_allocation_mode = 0;
|
||||
|
||||
protected boolean load_default_soundbank = false;
|
||||
protected boolean reverb_light = true;
|
||||
protected boolean reverb_on = true;
|
||||
protected boolean chorus_on = true;
|
||||
@ -226,8 +236,6 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
= new HashMap<String, SoftTuning>();
|
||||
private Map<String, SoftInstrument> inslist
|
||||
= new HashMap<String, SoftInstrument>();
|
||||
private Map<String, ModelInstrument> availlist
|
||||
= new HashMap<String, ModelInstrument>();
|
||||
private Map<String, ModelInstrument> loadedlist
|
||||
= new HashMap<String, ModelInstrument>();
|
||||
|
||||
@ -275,10 +283,12 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
synchronized (control_mutex) {
|
||||
if (channels != null)
|
||||
for (SoftChannel c : channels)
|
||||
{
|
||||
c.current_instrument = null;
|
||||
c.current_director = null;
|
||||
}
|
||||
for (Instrument instrument : instruments) {
|
||||
String pat = patchToString(instrument.getPatch());
|
||||
availlist.remove(pat);
|
||||
SoftInstrument softins
|
||||
= new SoftInstrument((ModelInstrument) instrument);
|
||||
inslist.put(pat, softins);
|
||||
@ -341,6 +351,7 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
number_of_midi_channels = (Integer)items[10].value;
|
||||
jitter_correction = (Boolean)items[11].value;
|
||||
reverb_light = (Boolean)items[12].value;
|
||||
load_default_soundbank = (Boolean)items[13].value;
|
||||
}
|
||||
|
||||
private String patchToString(Patch patch) {
|
||||
@ -578,7 +589,9 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
c.current_instrument = null;
|
||||
inslist.remove(pat);
|
||||
loadedlist.remove(pat);
|
||||
availlist.remove(pat);
|
||||
for (int i = 0; i < channels.length; i++) {
|
||||
channels[i].allSoundOff();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,7 +613,7 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
return false;
|
||||
|
||||
synchronized (control_mutex) {
|
||||
if (!loadedlist.containsValue(to) && !availlist.containsValue(to))
|
||||
if (!loadedlist.containsValue(to))
|
||||
throw new IllegalArgumentException("Instrument to is not loaded.");
|
||||
unloadInstrument(from);
|
||||
ModelMappedInstrument mfrom = new ModelMappedInstrument(
|
||||
@ -609,118 +622,155 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Soundbank getDefaultSoundbank() {
|
||||
if (defaultSoundBank == null) {
|
||||
try {
|
||||
File javahome = new File(System.getProperties().getProperty(
|
||||
"java.home"));
|
||||
File libaudio = new File(new File(javahome, "lib"), "audio");
|
||||
public Soundbank getDefaultSoundbank() {
|
||||
synchronized (SoftSynthesizer.class) {
|
||||
if (defaultSoundBank != null)
|
||||
return defaultSoundBank;
|
||||
|
||||
if (libaudio.exists()) {
|
||||
File foundfile = null;
|
||||
File[] files = libaudio.listFiles();
|
||||
if (files != null) {
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File file = files[i];
|
||||
if (file.isFile()) {
|
||||
String lname = file.getName().toLowerCase();
|
||||
if (lname.endsWith(".sf2") ||
|
||||
lname.endsWith(".dls")) {
|
||||
if (foundfile == null || (file.length() >
|
||||
foundfile.length())) {
|
||||
foundfile = file;
|
||||
List<PrivilegedAction<InputStream>> actions =
|
||||
new ArrayList<PrivilegedAction<InputStream>>();
|
||||
|
||||
actions.add(new PrivilegedAction<InputStream>() {
|
||||
public InputStream run() {
|
||||
File javahome = new File(System.getProperties()
|
||||
.getProperty("java.home"));
|
||||
File libaudio = new File(new File(javahome, "lib"), "audio");
|
||||
if (libaudio.exists()) {
|
||||
File foundfile = null;
|
||||
File[] files = libaudio.listFiles();
|
||||
if (files != null) {
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File file = files[i];
|
||||
if (file.isFile()) {
|
||||
String lname = file.getName().toLowerCase();
|
||||
if (lname.endsWith(".sf2")
|
||||
|| lname.endsWith(".dls")) {
|
||||
if (foundfile == null
|
||||
|| (file.length() > foundfile
|
||||
.length())) {
|
||||
foundfile = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (foundfile != null) {
|
||||
try {
|
||||
Soundbank sbk = MidiSystem.getSoundbank(foundfile);
|
||||
defaultSoundBank = sbk;
|
||||
return defaultSoundBank;
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
if (foundfile != null) {
|
||||
try {
|
||||
return new FileInputStream(foundfile);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if (System.getProperties().getProperty("os.name")
|
||||
.startsWith("Windows")) {
|
||||
File gm_dls = new File(System.getenv("SystemRoot")
|
||||
+ "\\system32\\drivers\\gm.dls");
|
||||
if (gm_dls.exists()) {
|
||||
try {
|
||||
Soundbank sbk = MidiSystem.getSoundbank(gm_dls);
|
||||
defaultSoundBank = sbk;
|
||||
return defaultSoundBank;
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
actions.add(new PrivilegedAction<InputStream>() {
|
||||
public InputStream run() {
|
||||
if (System.getProperties().getProperty("os.name")
|
||||
.startsWith("Windows")) {
|
||||
File gm_dls = new File(System.getenv("SystemRoot")
|
||||
+ "\\system32\\drivers\\gm.dls");
|
||||
if (gm_dls.exists()) {
|
||||
try {
|
||||
return new FileInputStream(gm_dls);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} catch (AccessControlException e) {
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
File userhome = null;
|
||||
File emg_soundbank_file = null;
|
||||
actions.add(new PrivilegedAction<InputStream>() {
|
||||
public InputStream run() {
|
||||
/*
|
||||
* Try to load saved generated soundbank
|
||||
*/
|
||||
File userhome = new File(System.getProperty("user.home"),
|
||||
".gervill");
|
||||
File emg_soundbank_file = new File(userhome,
|
||||
"soundbank-emg.sf2");
|
||||
if (emg_soundbank_file.exists()) {
|
||||
try {
|
||||
return new FileInputStream(emg_soundbank_file);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Try to load saved generated soundbank
|
||||
*/
|
||||
try {
|
||||
userhome = new File(System.getProperty("user.home"),
|
||||
".gervill");
|
||||
emg_soundbank_file = new File(userhome, "soundbank-emg.sf2");
|
||||
Soundbank sbk = MidiSystem.getSoundbank(emg_soundbank_file);
|
||||
defaultSoundBank = sbk;
|
||||
return defaultSoundBank;
|
||||
} catch (AccessControlException e) {
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
for (PrivilegedAction<InputStream> action : actions) {
|
||||
try {
|
||||
InputStream is = AccessController.doPrivileged(action);
|
||||
if(is == null) continue;
|
||||
Soundbank sbk;
|
||||
try {
|
||||
sbk = MidiSystem.getSoundbank(new BufferedInputStream(is));
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
if (sbk != null) {
|
||||
defaultSoundBank = sbk;
|
||||
return defaultSoundBank;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Generate emergency soundbank
|
||||
* Generate emergency soundbank
|
||||
*/
|
||||
defaultSoundBank = EmergencySoundbank.createSoundbank();
|
||||
|
||||
/*
|
||||
* Save generated soundbank to disk for faster future use.
|
||||
*/
|
||||
if(defaultSoundBank != null)
|
||||
{
|
||||
if(!userhome.exists()) userhome.mkdirs();
|
||||
if(!emg_soundbank_file.exists())
|
||||
((SF2Soundbank)defaultSoundBank).save(emg_soundbank_file);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
if (defaultSoundBank != null) {
|
||||
/*
|
||||
* Save generated soundbank to disk for faster future use.
|
||||
*/
|
||||
OutputStream out = AccessController
|
||||
.doPrivileged(new PrivilegedAction<OutputStream>() {
|
||||
public OutputStream run() {
|
||||
try {
|
||||
File userhome = new File(System
|
||||
.getProperty("user.home"),
|
||||
".gervill");
|
||||
if (!userhome.exists())
|
||||
userhome.mkdirs();
|
||||
File emg_soundbank_file = new File(
|
||||
userhome, "soundbank-emg.sf2");
|
||||
if (emg_soundbank_file.exists())
|
||||
return null;
|
||||
return new FileOutputStream(
|
||||
emg_soundbank_file);
|
||||
} catch (IOException e) {
|
||||
} catch (SecurityException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
if (out != null) {
|
||||
try {
|
||||
((SF2Soundbank) defaultSoundBank).save(out);
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultSoundBank;
|
||||
}
|
||||
|
||||
public Instrument[] getAvailableInstruments() {
|
||||
if (!isOpen()) {
|
||||
Soundbank defsbk = getDefaultSoundbank();
|
||||
if (defsbk == null)
|
||||
return new Instrument[0];
|
||||
return defsbk.getInstruments();
|
||||
}
|
||||
|
||||
synchronized (control_mutex) {
|
||||
ModelInstrument[] inslist_array =
|
||||
new ModelInstrument[availlist.values().size()];
|
||||
availlist.values().toArray(inslist_array);
|
||||
Arrays.sort(inslist_array, new ModelInstrumentComparator());
|
||||
return inslist_array;
|
||||
}
|
||||
Soundbank defsbk = getDefaultSoundbank();
|
||||
if (defsbk == null)
|
||||
return new Instrument[0];
|
||||
Instrument[] inslist_array = defsbk.getInstruments();
|
||||
Arrays.sort(inslist_array, new ModelInstrumentComparator());
|
||||
return inslist_array;
|
||||
}
|
||||
|
||||
public Instrument[] getLoadedInstruments() {
|
||||
@ -794,6 +844,31 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
return info;
|
||||
}
|
||||
|
||||
private Properties getStoredProperties() {
|
||||
return AccessController
|
||||
.doPrivileged(new PrivilegedAction<Properties>() {
|
||||
public Properties run() {
|
||||
Properties p = new Properties();
|
||||
String notePath = "/com/sun/media/sound/softsynthesizer";
|
||||
try {
|
||||
Preferences prefroot = Preferences.userRoot();
|
||||
if (prefroot.nodeExists(notePath)) {
|
||||
Preferences prefs = prefroot.node(notePath);
|
||||
String[] prefs_keys = prefs.keys();
|
||||
for (String prefs_key : prefs_keys) {
|
||||
String val = prefs.get(prefs_key, null);
|
||||
if (val != null)
|
||||
p.setProperty(prefs_key, val);
|
||||
}
|
||||
}
|
||||
} catch (BackingStoreException e) {
|
||||
} catch (SecurityException e) {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map<String, Object> info) {
|
||||
List<AudioSynthesizerPropertyInfo> list =
|
||||
new ArrayList<AudioSynthesizerPropertyInfo>();
|
||||
@ -861,17 +936,92 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
item.description = "Turn light reverb mode on or off";
|
||||
list.add(item);
|
||||
|
||||
item = new AudioSynthesizerPropertyInfo("load default soundbank", o?load_default_soundbank:true);
|
||||
item.description = "Enabled/disable loading default soundbank";
|
||||
list.add(item);
|
||||
|
||||
AudioSynthesizerPropertyInfo[] items;
|
||||
items = list.toArray(new AudioSynthesizerPropertyInfo[list.size()]);
|
||||
|
||||
if (info != null)
|
||||
for (AudioSynthesizerPropertyInfo item2: items) {
|
||||
Object v = info.get(item2.name);
|
||||
Properties storedProperties = getStoredProperties();
|
||||
|
||||
for (AudioSynthesizerPropertyInfo item2 : items) {
|
||||
Object v = (info == null) ? null : info.get(item2.name);
|
||||
v = (v != null) ? v : storedProperties.getProperty(item2.name);
|
||||
if (v != null) {
|
||||
Class c = (item2.valueClass);
|
||||
if (v != null)
|
||||
if (c.isInstance(v))
|
||||
item2.value = v;
|
||||
if (c.isInstance(v))
|
||||
item2.value = v;
|
||||
else if (v instanceof String) {
|
||||
String s = (String) v;
|
||||
if (c == Boolean.class) {
|
||||
if (s.equalsIgnoreCase("true"))
|
||||
item2.value = Boolean.TRUE;
|
||||
if (s.equalsIgnoreCase("false"))
|
||||
item2.value = Boolean.FALSE;
|
||||
} else if (c == AudioFormat.class) {
|
||||
int channels = 2;
|
||||
boolean signed = true;
|
||||
boolean bigendian = false;
|
||||
int bits = 16;
|
||||
float sampleRate = 44100f;
|
||||
try {
|
||||
StringTokenizer st = new StringTokenizer(s, ", ");
|
||||
String prevToken = "";
|
||||
while (st.hasMoreTokens()) {
|
||||
String token = st.nextToken().toLowerCase();
|
||||
if (token.equals("mono"))
|
||||
channels = 1;
|
||||
if (token.startsWith("channel"))
|
||||
channels = Integer.parseInt(prevToken);
|
||||
if (token.contains("unsigned"))
|
||||
signed = false;
|
||||
if (token.equals("big-endian"))
|
||||
bigendian = true;
|
||||
if (token.equals("bit"))
|
||||
bits = Integer.parseInt(prevToken);
|
||||
if (token.equals("hz"))
|
||||
sampleRate = Float.parseFloat(prevToken);
|
||||
prevToken = token;
|
||||
}
|
||||
item2.value = new AudioFormat(sampleRate, bits,
|
||||
channels, signed, bigendian);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
|
||||
} else
|
||||
try {
|
||||
if (c == Byte.class)
|
||||
item2.value = Byte.valueOf(s);
|
||||
else if (c == Short.class)
|
||||
item2.value = Short.valueOf(s);
|
||||
else if (c == Integer.class)
|
||||
item2.value = Integer.valueOf(s);
|
||||
else if (c == Long.class)
|
||||
item2.value = Long.valueOf(s);
|
||||
else if (c == Float.class)
|
||||
item2.value = Float.valueOf(s);
|
||||
else if (c == Double.class)
|
||||
item2.value = Double.valueOf(s);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
} else if (v instanceof Number) {
|
||||
Number n = (Number) v;
|
||||
if (c == Byte.class)
|
||||
item2.value = Byte.valueOf(n.byteValue());
|
||||
if (c == Short.class)
|
||||
item2.value = Short.valueOf(n.shortValue());
|
||||
if (c == Integer.class)
|
||||
item2.value = Integer.valueOf(n.intValue());
|
||||
if (c == Long.class)
|
||||
item2.value = Long.valueOf(n.longValue());
|
||||
if (c == Float.class)
|
||||
item2.value = Float.valueOf(n.floatValue());
|
||||
if (c == Double.class)
|
||||
item2.value = Double.valueOf(n.doubleValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
@ -1007,11 +1157,12 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
if (targetFormat != null)
|
||||
setFormat(targetFormat);
|
||||
|
||||
Soundbank defbank = getDefaultSoundbank();
|
||||
if (defbank != null) {
|
||||
loadAllInstruments(defbank);
|
||||
availlist.putAll(loadedlist);
|
||||
loadedlist.clear();
|
||||
if (load_default_soundbank)
|
||||
{
|
||||
Soundbank defbank = getDefaultSoundbank();
|
||||
if (defbank != null) {
|
||||
loadAllInstruments(defbank);
|
||||
}
|
||||
}
|
||||
|
||||
voices = new SoftVoice[maxpoly];
|
||||
@ -1117,7 +1268,6 @@ public class SoftSynthesizer implements AudioSynthesizer,
|
||||
}
|
||||
|
||||
inslist.clear();
|
||||
availlist.clear();
|
||||
loadedlist.clear();
|
||||
tunings.clear();
|
||||
|
||||
|
@ -279,9 +279,12 @@ public class SoftVoice extends VoiceStatus {
|
||||
}
|
||||
|
||||
protected void updateTuning(SoftTuning newtuning) {
|
||||
tuning = newtuning;
|
||||
tunedKey = tuning.getTuning(note) / 100.0;
|
||||
if (!portamento) {
|
||||
co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_connections[4];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -433,6 +436,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
}
|
||||
|
||||
protected void setPolyPressure(int pressure) {
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_connections[2];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -441,6 +446,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
}
|
||||
|
||||
protected void setChannelPressure(int pressure) {
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_connections[1];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -449,6 +456,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
}
|
||||
|
||||
protected void controlChange(int controller, int value) {
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_ctrl_connections[controller];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -457,6 +466,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
}
|
||||
|
||||
protected void nrpnChange(int controller, int value) {
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_nrpn_connections.get(controller);
|
||||
if (c == null)
|
||||
return;
|
||||
@ -465,6 +476,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
}
|
||||
|
||||
protected void rpnChange(int controller, int value) {
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_rpn_connections.get(controller);
|
||||
if (c == null)
|
||||
return;
|
||||
@ -473,6 +486,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
}
|
||||
|
||||
protected void setPitchBend(int bend) {
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_connections[0];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -499,6 +514,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
|
||||
co_noteon_on[0] = -1;
|
||||
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_connections[3];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -527,6 +544,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
|
||||
co_noteon_on[0] = 0;
|
||||
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_connections[3];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -543,6 +562,8 @@ public class SoftVoice extends VoiceStatus {
|
||||
sustain = true;
|
||||
co_noteon_on[0] = 1;
|
||||
|
||||
if(performer == null)
|
||||
return;
|
||||
int[] c = performer.midi_connections[3];
|
||||
if (c == null)
|
||||
return;
|
||||
@ -555,6 +576,11 @@ public class SoftVoice extends VoiceStatus {
|
||||
active = false;
|
||||
stopping = false;
|
||||
audiostarted = false;
|
||||
instrument = null;
|
||||
performer = null;
|
||||
connections = null;
|
||||
extendedConnectionBlocks = null;
|
||||
channelmixer = null;
|
||||
if (osc_stream != null)
|
||||
try {
|
||||
osc_stream.close();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2010, 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
|
||||
@ -271,7 +271,7 @@ public class WaveExtensibleFileReader extends AudioFileReader {
|
||||
bits, channels, framesize, samplerate, false, p);
|
||||
}
|
||||
} else if (subFormat.equals(SUBTYPE_IEEE_FLOAT)) {
|
||||
audioformat = new AudioFormat(AudioFloatConverter.PCM_FLOAT,
|
||||
audioformat = new AudioFormat(Encoding.PCM_FLOAT,
|
||||
samplerate, bits, channels, framesize, samplerate, false, p);
|
||||
} else
|
||||
throw new UnsupportedAudioFileException();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2010, 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
|
||||
@ -33,6 +33,7 @@ import java.net.URL;
|
||||
|
||||
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;
|
||||
@ -102,7 +103,7 @@ public class WaveFloatFileReader extends AudioFileReader {
|
||||
throw new UnsupportedAudioFileException();
|
||||
|
||||
AudioFormat audioformat = new AudioFormat(
|
||||
AudioFloatConverter.PCM_FLOAT, samplerate, bits, channels,
|
||||
Encoding.PCM_FLOAT, samplerate, bits, channels,
|
||||
framesize, samplerate, false);
|
||||
AudioFileFormat fileformat = new AudioFileFormat(
|
||||
AudioFileFormat.Type.WAVE, audioformat,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2010, 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
|
||||
@ -30,6 +30,7 @@ import java.io.OutputStream;
|
||||
|
||||
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.AudioFileFormat.Type;
|
||||
@ -48,8 +49,7 @@ public class WaveFloatFileWriter extends AudioFileWriter {
|
||||
|
||||
public Type[] getAudioFileTypes(AudioInputStream stream) {
|
||||
|
||||
if (!stream.getFormat().getEncoding().equals(
|
||||
AudioFloatConverter.PCM_FLOAT))
|
||||
if (!stream.getFormat().getEncoding().equals(Encoding.PCM_FLOAT))
|
||||
return new Type[0];
|
||||
return new Type[] { Type.WAVE };
|
||||
}
|
||||
@ -58,8 +58,7 @@ public class WaveFloatFileWriter extends AudioFileWriter {
|
||||
if (!Type.WAVE.equals(type))
|
||||
throw new IllegalArgumentException("File type " + type
|
||||
+ " not supported.");
|
||||
if (!stream.getFormat().getEncoding().equals(
|
||||
AudioFloatConverter.PCM_FLOAT))
|
||||
if (!stream.getFormat().getEncoding().equals(Encoding.PCM_FLOAT))
|
||||
throw new IllegalArgumentException("File format "
|
||||
+ stream.getFormat() + " not supported.");
|
||||
}
|
||||
|
@ -595,7 +595,6 @@ class Character implements java.io.Serializable, Comparable<Character> {
|
||||
/**
|
||||
* Constructs a new <code>Subset</code> instance.
|
||||
*
|
||||
* @exception NullPointerException if name is <code>null</code>
|
||||
* @param name The name of this subset
|
||||
* @exception NullPointerException if name is <code>null</code>
|
||||
*/
|
||||
|
@ -226,7 +226,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
* Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
|
||||
* All locales use the same these unlocalized pattern characters.
|
||||
*/
|
||||
static final String patternChars = "GyMdkHmsSEDFwWahKzZYu";
|
||||
static final String patternChars = "GyMdkHmsSEDFwWahKzZYuX";
|
||||
|
||||
static final int PATTERN_ERA = 0; // G
|
||||
static final int PATTERN_YEAR = 1; // y
|
||||
@ -249,6 +249,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
static final int PATTERN_ZONE_VALUE = 18; // Z
|
||||
static final int PATTERN_WEEK_YEAR = 19; // Y
|
||||
static final int PATTERN_ISO_DAY_OF_WEEK = 20; // u
|
||||
static final int PATTERN_ISO_ZONE = 21; // X
|
||||
|
||||
/**
|
||||
* Localized date-time pattern characters. For example, a locale may
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2010, 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
|
||||
@ -43,10 +43,10 @@ import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.util.Currency;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import sun.util.LocaleServiceProviderPool;
|
||||
import sun.util.resources.LocaleData;
|
||||
|
||||
@ -527,10 +527,17 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
||||
|
||||
// get resource bundle data - try the cache first
|
||||
boolean needCacheUpdate = false;
|
||||
Object[] data = (Object[]) cachedLocaleData.get(locale);
|
||||
Object[] data = cachedLocaleData.get(locale);
|
||||
if (data == null) { /* cache miss */
|
||||
// When numbering system is thai (Locale's extension contains u-nu-thai),
|
||||
// we read the data from th_TH_TH.
|
||||
Locale lookupLocale = locale;
|
||||
String numberType = locale.getUnicodeLocaleType("nu");
|
||||
if (numberType != null && numberType.equals("thai")) {
|
||||
lookupLocale = new Locale("th", "TH", "TH");
|
||||
}
|
||||
data = new Object[3];
|
||||
ResourceBundle rb = LocaleData.getNumberFormatData(locale);
|
||||
ResourceBundle rb = LocaleData.getNumberFormatData(lookupLocale);
|
||||
data[0] = rb.getStringArray("NumberElements");
|
||||
needCacheUpdate = true;
|
||||
}
|
||||
@ -586,7 +593,7 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
||||
monetarySeparator = decimalSeparator;
|
||||
|
||||
if (needCacheUpdate) {
|
||||
cachedLocaleData.put(locale, data);
|
||||
cachedLocaleData.putIfAbsent(locale, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -806,7 +813,7 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
||||
* cache to hold the NumberElements and the Currency
|
||||
* of a Locale.
|
||||
*/
|
||||
private static final Hashtable cachedLocaleData = new Hashtable(3);
|
||||
private static final ConcurrentHashMap<Locale, Object[]> cachedLocaleData = new ConcurrentHashMap<Locale, Object[]>(3);
|
||||
|
||||
/**
|
||||
* Obtains a DecimalFormatSymbols instance from a DecimalFormatSymbolsProvider
|
||||
|
@ -204,6 +204,11 @@ import static java.text.DateFormatSymbols.*;
|
||||
* <td>Time zone
|
||||
* <td><a href="#rfc822timezone">RFC 822 time zone</a>
|
||||
* <td><code>-0800</code>
|
||||
* <tr bgcolor="#eeeeff">
|
||||
* <td><code>X</code>
|
||||
* <td>Time zone
|
||||
* <td><a href="#iso8601timezone">ISO 8601 time zone</a>
|
||||
* <td><code>-08</code>; <code>-0800</code>; <code>-08:00</code>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
* Pattern letters are usually repeated, as their number determines the
|
||||
@ -288,6 +293,7 @@ import static java.text.DateFormatSymbols.*;
|
||||
* accepted.<br><br></li>
|
||||
* <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
|
||||
* For formatting, the RFC 822 4-digit time zone format is used:
|
||||
*
|
||||
* <pre>
|
||||
* <i>RFC822TimeZone:</i>
|
||||
* <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
|
||||
@ -295,8 +301,41 @@ import static java.text.DateFormatSymbols.*;
|
||||
* <i>Digit Digit</i></pre>
|
||||
* <i>TwoDigitHours</i> must be between 00 and 23. Other definitions
|
||||
* are as for <a href="#timezone">general time zones</a>.
|
||||
*
|
||||
* <p>For parsing, <a href="#timezone">general time zones</a> are also
|
||||
* accepted.
|
||||
* <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong>
|
||||
* The number of pattern letters designates the format for both formatting
|
||||
* and parsing as follows:
|
||||
* <pre>
|
||||
* <i>ISO8601TimeZone:</i>
|
||||
* <i>OneLetterISO8601TimeZone</i>
|
||||
* <i>TwoLetterISO8601TimeZone</i>
|
||||
* <i>ThreeLetterISO8601TimeZone</i>
|
||||
* <i>OneLetterISO8601TimeZone:</i>
|
||||
* <i>Sign</i> <i>TwoDigitHours</i>
|
||||
* {@code Z}
|
||||
* <i>TwoLetterISO8601TimeZone:</i>
|
||||
* <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
|
||||
* {@code Z}
|
||||
* <i>ThreeLetterISO8601TimeZone:</i>
|
||||
* <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i>
|
||||
* {@code Z}</pre>
|
||||
* Other definitions are as for <a href="#timezone">general time zones</a> or
|
||||
* <a href="#rfc822timezone">RFC 822 time zones</a>.
|
||||
*
|
||||
* <p>For formatting, if the offset value from GMT is 0, {@code "Z"} is
|
||||
* produced. If the number of pattern letters is 1, any fraction of an hour
|
||||
* is ignored. For example, if the pattern is {@code "X"} and the time zone is
|
||||
* {@code "GMT+05:30"}, {@code "+05"} is produced.
|
||||
*
|
||||
* <p>For parsing, {@code "Z"} is parsed as the UTC time zone designator.
|
||||
* <a href="#timezone">General time zones</a> are <em>not</em> accepted.
|
||||
*
|
||||
* <p>If the number of pattern letters is 4 or more, {@link
|
||||
* IllegalArgumentException} is thrown when constructing a {@code
|
||||
* SimpleDateFormat} or {@linkplain #applyPattern(String) applying a
|
||||
* pattern}.
|
||||
* </ul>
|
||||
* <code>SimpleDateFormat</code> also supports <em>localized date and time
|
||||
* pattern</em> strings. In these strings, the pattern letters described above
|
||||
@ -343,6 +382,9 @@ import static java.text.DateFormatSymbols.*;
|
||||
* <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
|
||||
* <td><code>2001-07-04T12:08:56.235-0700</code>
|
||||
* <tr bgcolor="#eeeeff">
|
||||
* <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
|
||||
* <td><code>2001-07-04T12:08:56.235-07:00</code>
|
||||
* <tr>
|
||||
* <td><code>"YYYY-'W'ww-u"</code>
|
||||
* <td><code>2001-W27-3</code>
|
||||
* </table>
|
||||
@ -839,6 +881,9 @@ public class SimpleDateFormat extends DateFormat {
|
||||
* Encodes the given tag and length and puts encoded char(s) into buffer.
|
||||
*/
|
||||
private static final void encode(int tag, int length, StringBuilder buffer) {
|
||||
if (tag == PATTERN_ISO_ZONE && length >= 4) {
|
||||
throw new IllegalArgumentException("invalid ISO 8601 format: length=" + length);
|
||||
}
|
||||
if (length < 255) {
|
||||
buffer.append((char)(tag << 8 | length));
|
||||
} else {
|
||||
@ -995,7 +1040,8 @@ public class SimpleDateFormat extends DateFormat {
|
||||
Calendar.ZONE_OFFSET,
|
||||
// Pseudo Calendar fields
|
||||
CalendarBuilder.WEEK_YEAR,
|
||||
CalendarBuilder.ISO_DAY_OF_WEEK
|
||||
CalendarBuilder.ISO_DAY_OF_WEEK,
|
||||
Calendar.ZONE_OFFSET
|
||||
};
|
||||
|
||||
// Map index into pattern character string to DateFormat field number
|
||||
@ -1009,7 +1055,8 @@ public class SimpleDateFormat extends DateFormat {
|
||||
DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.AM_PM_FIELD,
|
||||
DateFormat.HOUR1_FIELD, DateFormat.HOUR0_FIELD,
|
||||
DateFormat.TIMEZONE_FIELD, DateFormat.TIMEZONE_FIELD,
|
||||
DateFormat.YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD
|
||||
DateFormat.YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD,
|
||||
DateFormat.TIMEZONE_FIELD
|
||||
};
|
||||
|
||||
// Maps from DecimalFormatSymbols index to Field constant
|
||||
@ -1021,7 +1068,8 @@ public class SimpleDateFormat extends DateFormat {
|
||||
Field.WEEK_OF_YEAR, Field.WEEK_OF_MONTH,
|
||||
Field.AM_PM, Field.HOUR1, Field.HOUR0, Field.TIME_ZONE,
|
||||
Field.TIME_ZONE,
|
||||
Field.YEAR, Field.DAY_OF_WEEK
|
||||
Field.YEAR, Field.DAY_OF_WEEK,
|
||||
Field.TIME_ZONE
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1189,6 +1237,34 @@ public class SimpleDateFormat extends DateFormat {
|
||||
CalendarUtils.sprintf0d(buffer, num, width);
|
||||
break;
|
||||
|
||||
case PATTERN_ISO_ZONE: // 'X'
|
||||
value = calendar.get(Calendar.ZONE_OFFSET)
|
||||
+ calendar.get(Calendar.DST_OFFSET);
|
||||
|
||||
if (value == 0) {
|
||||
buffer.append('Z');
|
||||
break;
|
||||
}
|
||||
|
||||
value /= 60000;
|
||||
if (value >= 0) {
|
||||
buffer.append('+');
|
||||
} else {
|
||||
buffer.append('-');
|
||||
value = -value;
|
||||
}
|
||||
|
||||
CalendarUtils.sprintf0d(buffer, value / 60, 2);
|
||||
if (count == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (count == 3) {
|
||||
buffer.append(':');
|
||||
}
|
||||
CalendarUtils.sprintf0d(buffer, value % 60, 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
// case PATTERN_DAY_OF_MONTH: // 'd'
|
||||
// case PATTERN_HOUR_OF_DAY0: // 'H' 0-based. eg, 23:59 + 1 hour =>> 00:59
|
||||
@ -1973,6 +2049,94 @@ public class SimpleDateFormat extends DateFormat {
|
||||
}
|
||||
break parsing;
|
||||
|
||||
case PATTERN_ISO_ZONE: // 'X'
|
||||
{
|
||||
int sign = 0;
|
||||
int offset = 0;
|
||||
|
||||
iso8601: {
|
||||
try {
|
||||
char c = text.charAt(pos.index);
|
||||
if (c == 'Z') {
|
||||
calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0);
|
||||
return ++pos.index;
|
||||
}
|
||||
|
||||
// parse text as "+/-hh[[:]mm]" based on count
|
||||
if (c == '+') {
|
||||
sign = 1;
|
||||
} else if (c == '-') {
|
||||
sign = -1;
|
||||
}
|
||||
// Look for hh.
|
||||
int hours = 0;
|
||||
c = text.charAt(++pos.index);
|
||||
if (c < '0' || c > '9') { /* must be from '0' to '9'. */
|
||||
break parsing;
|
||||
}
|
||||
hours = c - '0';
|
||||
c = text.charAt(++pos.index);
|
||||
if (c < '0' || c > '9') { /* must be from '0' to '9'. */
|
||||
break parsing;
|
||||
}
|
||||
hours *= 10;
|
||||
hours += c - '0';
|
||||
if (hours > 23) {
|
||||
break parsing;
|
||||
}
|
||||
|
||||
if (count == 1) { // "X"
|
||||
offset = hours * 60;
|
||||
break iso8601;
|
||||
}
|
||||
|
||||
c = text.charAt(++pos.index);
|
||||
// Skip ':' if "XXX"
|
||||
if (c == ':') {
|
||||
if (count == 2) {
|
||||
break parsing;
|
||||
}
|
||||
c = text.charAt(++pos.index);
|
||||
} else {
|
||||
if (count == 3) {
|
||||
// missing ':'
|
||||
break parsing;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for mm.
|
||||
int minutes = 0;
|
||||
if (c < '0' || c > '9') { /* must be from '0' to '9'. */
|
||||
break parsing;
|
||||
}
|
||||
minutes = c - '0';
|
||||
c = text.charAt(++pos.index);
|
||||
if (c < '0' || c > '9') { /* must be from '0' to '9'. */
|
||||
break parsing;
|
||||
}
|
||||
minutes *= 10;
|
||||
minutes += c - '0';
|
||||
|
||||
if (minutes > 59) {
|
||||
break parsing;
|
||||
}
|
||||
|
||||
offset = hours * 60 + minutes;
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
break parsing;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the final processing for both of the above cases. We only
|
||||
// arrive here if the form GMT+/-... or an RFC 822 form was seen.
|
||||
if (sign != 0) {
|
||||
offset *= MILLIS_PER_MINUTE * sign;
|
||||
calb.set(Calendar.ZONE_OFFSET, offset).set(Calendar.DST_OFFSET, 0);
|
||||
return ++pos.index;
|
||||
}
|
||||
}
|
||||
break parsing;
|
||||
|
||||
default:
|
||||
// case PATTERN_DAY_OF_MONTH: // 'd'
|
||||
// case PATTERN_HOUR_OF_DAY0: // 'H' 0-based. eg, 23:59 + 1 hour =>> 00:59
|
||||
@ -2102,7 +2266,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
* @exception NullPointerException if the given pattern is null
|
||||
* @exception IllegalArgumentException if the given pattern is invalid
|
||||
*/
|
||||
public void applyPattern (String pattern)
|
||||
public void applyPattern(String pattern)
|
||||
{
|
||||
compiledPattern = compile(pattern);
|
||||
this.pattern = pattern;
|
||||
|
@ -1013,19 +1013,30 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
||||
private static Calendar createCalendar(TimeZone zone,
|
||||
Locale aLocale)
|
||||
{
|
||||
// If the specified locale is a Thai locale, returns a BuddhistCalendar
|
||||
// instance.
|
||||
if ("th".equals(aLocale.getLanguage())
|
||||
&& ("TH".equals(aLocale.getCountry()))) {
|
||||
return new sun.util.BuddhistCalendar(zone, aLocale);
|
||||
} else if ("JP".equals(aLocale.getVariant())
|
||||
&& "JP".equals(aLocale.getCountry())
|
||||
&& "ja".equals(aLocale.getLanguage())) {
|
||||
return new JapaneseImperialCalendar(zone, aLocale);
|
||||
Calendar cal = null;
|
||||
|
||||
String caltype = aLocale.getUnicodeLocaleType("ca");
|
||||
if (caltype == null) {
|
||||
// Calendar type is not specified.
|
||||
// If the specified locale is a Thai locale,
|
||||
// returns a BuddhistCalendar instance.
|
||||
if ("th".equals(aLocale.getLanguage())
|
||||
&& ("TH".equals(aLocale.getCountry()))) {
|
||||
cal = new BuddhistCalendar(zone, aLocale);
|
||||
} else {
|
||||
cal = new GregorianCalendar(zone, aLocale);
|
||||
}
|
||||
} else if (caltype.equals("japanese")) {
|
||||
cal = new JapaneseImperialCalendar(zone, aLocale);
|
||||
} else if (caltype.equals("buddhist")) {
|
||||
cal = new BuddhistCalendar(zone, aLocale);
|
||||
} else {
|
||||
// Unsupported calendar type.
|
||||
// Use Gregorian calendar as a fallback.
|
||||
cal = new GregorianCalendar(zone, aLocale);
|
||||
}
|
||||
|
||||
// else create the default calendar
|
||||
return new GregorianCalendar(zone, aLocale);
|
||||
return cal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2160,20 +2160,22 @@ public class GregorianCalendar extends Calendar {
|
||||
gc.complete();
|
||||
}
|
||||
|
||||
if (!isLenient() &&
|
||||
(gc.getWeekYear() != weekYear
|
||||
|| gc.internalGet(WEEK_OF_YEAR) != weekOfYear
|
||||
|| gc.internalGet(DAY_OF_WEEK) != dayOfWeek)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
set(ERA, gc.internalGet(ERA));
|
||||
set(YEAR, gc.internalGet(YEAR));
|
||||
set(MONTH, gc.internalGet(MONTH));
|
||||
set(DAY_OF_MONTH, gc.internalGet(DAY_OF_MONTH));
|
||||
|
||||
// to avoid throwing an IllegalArgumentException in
|
||||
// non-lenient, set WEEK_OF_YEAR and DAY_OF_WEEK internally
|
||||
// non-lenient, set WEEK_OF_YEAR internally
|
||||
internalSet(WEEK_OF_YEAR, weekOfYear);
|
||||
internalSet(DAY_OF_WEEK, dayOfWeek);
|
||||
complete();
|
||||
|
||||
assert getWeekYear() == weekYear;
|
||||
assert get(WEEK_OF_YEAR) == weekOfYear;
|
||||
assert get(DAY_OF_WEEK) == dayOfWeek;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* Thrown by methods in {@link Locale} and {@link Locale.Builder} to
|
||||
* indicate that an argument is not a well-formed BCP 47 tag.
|
||||
*
|
||||
* @see Locale
|
||||
* @since 1.7
|
||||
*/
|
||||
public class IllformedLocaleException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -5245986824925681401L;
|
||||
|
||||
private int _errIdx = -1;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>IllformedLocaleException</code> with no
|
||||
* detail message and -1 as the error index.
|
||||
*/
|
||||
public IllformedLocaleException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>IllformedLocaleException</code> with the
|
||||
* given message and -1 as the error index.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public IllformedLocaleException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>IllformedLocaleException</code> with the
|
||||
* given message and the error index. The error index is the approximate
|
||||
* offset from the start of the ill-formed value to the point where the
|
||||
* parse first detected an error. A negative error index value indicates
|
||||
* either the error index is not applicable or unknown.
|
||||
*
|
||||
* @param message the message
|
||||
* @param errorIndex the index
|
||||
*/
|
||||
public IllformedLocaleException(String message, int errorIndex) {
|
||||
super(message + ((errorIndex < 0) ? "" : " [at index " + errorIndex + "]"));
|
||||
_errIdx = errorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index where the error was found. A negative value indicates
|
||||
* either the error index is not applicable or unknown.
|
||||
*
|
||||
* @return the error index
|
||||
*/
|
||||
public int getErrorIndex() {
|
||||
return _errIdx;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2010, 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
|
||||
@ -56,16 +56,18 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import sun.util.locale.BaseLocale;
|
||||
import sun.util.locale.LocaleExtensions;
|
||||
import sun.util.locale.LocaleObjectCache;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Resource bundles contain locale-specific objects.
|
||||
* When your program needs a locale-specific resource,
|
||||
* a <code>String</code> for example, your program can load it
|
||||
* from the resource bundle that is appropriate for the
|
||||
* current user's locale. In this way, you can write
|
||||
* program code that is largely independent of the user's
|
||||
* locale isolating most, if not all, of the locale-specific
|
||||
* Resource bundles contain locale-specific objects. When your program needs a
|
||||
* locale-specific resource, a <code>String</code> for example, your program can
|
||||
* load it from the resource bundle that is appropriate for the current user's
|
||||
* locale. In this way, you can write program code that is largely independent
|
||||
* of the user's locale isolating most, if not all, of the locale-specific
|
||||
* information in resource bundles.
|
||||
*
|
||||
* <p>
|
||||
@ -854,87 +856,140 @@ public abstract class ResourceBundle {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a resource bundle using the specified base name, locale, and class loader.
|
||||
* Gets a resource bundle using the specified base name, locale, and class
|
||||
* loader.
|
||||
*
|
||||
* <p><a name="default_behavior"/>
|
||||
* Conceptually, <code>getBundle</code> uses the following strategy for locating and instantiating
|
||||
* resource bundles:
|
||||
* <p>
|
||||
* <code>getBundle</code> uses the base name, the specified locale, and the default
|
||||
* locale (obtained from {@link java.util.Locale#getDefault() Locale.getDefault})
|
||||
* to generate a sequence of <a name="candidates"><em>candidate bundle names</em></a>.
|
||||
* If the specified locale's language, country, and variant are all empty
|
||||
* strings, then the base name is the only candidate bundle name.
|
||||
* Otherwise, the following sequence is generated from the attribute
|
||||
* values of the specified locale (language1, country1, and variant1)
|
||||
* and of the default locale (language2, country2, and variant2):
|
||||
* <ul>
|
||||
* <li> baseName + "_" + language1 + "_" + country1 + "_" + variant1
|
||||
* <li> baseName + "_" + language1 + "_" + country1
|
||||
* <li> baseName + "_" + language1
|
||||
* <li> baseName + "_" + language2 + "_" + country2 + "_" + variant2
|
||||
* <li> baseName + "_" + language2 + "_" + country2
|
||||
* <li> baseName + "_" + language2
|
||||
* <li> baseName
|
||||
* </ul>
|
||||
* <p>
|
||||
* Candidate bundle names where the final component is an empty string are omitted.
|
||||
* For example, if country1 is an empty string, the second candidate bundle name is omitted.
|
||||
* <p><a name="default_behavior"/>This method behaves the same as calling
|
||||
* {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
|
||||
* default instance of {@link Control}. The following describes this behavior.
|
||||
*
|
||||
* <p>
|
||||
* <code>getBundle</code> then iterates over the candidate bundle names to find the first
|
||||
* one for which it can <em>instantiate</em> an actual resource bundle. For each candidate
|
||||
* bundle name, it attempts to create a resource bundle:
|
||||
* <ul>
|
||||
* <li>
|
||||
* First, it attempts to load a class using the candidate bundle name.
|
||||
* If such a class can be found and loaded using the specified class loader, is assignment
|
||||
* compatible with ResourceBundle, is accessible from ResourceBundle, and can be instantiated,
|
||||
* <code>getBundle</code> creates a new instance of this class and uses it as the <em>result
|
||||
* resource bundle</em>.
|
||||
* <li>
|
||||
* Otherwise, <code>getBundle</code> attempts to locate a property resource file.
|
||||
* It generates a path name from the candidate bundle name by replacing all "." characters
|
||||
* with "/" and appending the string ".properties".
|
||||
* It attempts to find a "resource" with this name using
|
||||
* {@link java.lang.ClassLoader#getResource(java.lang.String) ClassLoader.getResource}.
|
||||
* (Note that a "resource" in the sense of <code>getResource</code> has nothing to do with
|
||||
* the contents of a resource bundle, it is just a container of data, such as a file.)
|
||||
* If it finds a "resource", it attempts to create a new
|
||||
* {@link PropertyResourceBundle} instance from its contents.
|
||||
* If successful, this instance becomes the <em>result resource bundle</em>.
|
||||
* </ul>
|
||||
* <p><code>getBundle</code> uses the base name, the specified locale, and
|
||||
* the default locale (obtained from {@link java.util.Locale#getDefault()
|
||||
* Locale.getDefault}) to generate a sequence of <a
|
||||
* name="candidates"><em>candidate bundle names</em></a>. If the specified
|
||||
* locale's language, script, country, and variant are all empty strings,
|
||||
* then the base name is the only candidate bundle name. Otherwise, a list
|
||||
* of candidate locales is generated from the attribute values of the
|
||||
* specified locale (language, script, country and variant) and appended to
|
||||
* the base name. Typically, this will look like the following:
|
||||
*
|
||||
* <p>
|
||||
* If no result resource bundle has been found, a <code>MissingResourceException</code>
|
||||
* is thrown.
|
||||
* <pre>
|
||||
* baseName + "_" + language + "_" + script + "_" + country + "_" + variant
|
||||
* baseName + "_" + language + "_" + script + "_" + country
|
||||
* baseName + "_" + language + "_" + script
|
||||
* baseName + "_" + language + "_" + country + "_" + variant
|
||||
* baseName + "_" + language + "_" + country
|
||||
* baseName + "_" + language
|
||||
* </pre>
|
||||
*
|
||||
* <p><a name="parent_chain"/>
|
||||
* Once a result resource bundle has been found, its <em>parent chain</em> is instantiated.
|
||||
* <code>getBundle</code> iterates over the candidate bundle names that can be
|
||||
* obtained by successively removing variant, country, and language
|
||||
* (each time with the preceding "_") from the bundle name of the result resource bundle.
|
||||
* As above, candidate bundle names where the final component is an empty string are omitted.
|
||||
* With each of the candidate bundle names it attempts to instantiate a resource bundle, as
|
||||
* described above.
|
||||
* Whenever it succeeds, it calls the previously instantiated resource
|
||||
* <p>Candidate bundle names where the final component is an empty string
|
||||
* are omitted, along with the underscore. For example, if country is an
|
||||
* empty string, the second and the fifth candidate bundle names above
|
||||
* would be omitted. Also, if script is an empty string, the candidate names
|
||||
* including script are omitted. For example, a locale with language "de"
|
||||
* and variant "JAVA" will produce candidate names with base name
|
||||
* "MyResource" below.
|
||||
*
|
||||
* <pre>
|
||||
* MyResource_de__JAVA
|
||||
* MyResource_de
|
||||
* </pre>
|
||||
*
|
||||
* In the case that the variant contains one or more underscores ('_'), a
|
||||
* sequence of bundle names generated by truncating the last underscore and
|
||||
* the part following it is inserted after a candidate bundle name with the
|
||||
* original variant. For example, for a locale with language "en", script
|
||||
* "Latn, country "US" and variant "WINDOWS_VISTA", and bundle base name
|
||||
* "MyResource", the list of candidate bundle names below is generated:
|
||||
*
|
||||
* <pre>
|
||||
* MyResource_en_Latn_US_WINDOWS_VISTA
|
||||
* MyResource_en_Latn_US_WINDOWS
|
||||
* MyResource_en_Latn_US
|
||||
* MyResource_en_Latn
|
||||
* MyResource_en_US_WINDOWS_VISTA
|
||||
* MyResource_en_US_WINDOWS
|
||||
* MyResource_en_US
|
||||
* MyResource_en
|
||||
* </pre>
|
||||
*
|
||||
* <blockquote><b>Note:</b> For some <code>Locale</code>s, the list of
|
||||
* candidate bundle names contains extra names, or the order of bundle names
|
||||
* is slightly modified. See the description of the default implementation
|
||||
* of {@link Control#getCandidateLocales(String, Locale)
|
||||
* getCandidateLocales} for details.</blockquote>
|
||||
*
|
||||
* <p><code>getBundle</code> then iterates over the candidate bundle names
|
||||
* to find the first one for which it can <em>instantiate</em> an actual
|
||||
* resource bundle. It uses the default controls' {@link Control#getFormats
|
||||
* getFormats} method, which generates two bundle names for each generated
|
||||
* name, the first a class name and the second a properties file name. For
|
||||
* each candidate bundle name, it attempts to create a resource bundle:
|
||||
*
|
||||
* <ul><li>First, it attempts to load a class using the generated class name.
|
||||
* If such a class can be found and loaded using the specified class
|
||||
* loader, is assignment compatible with ResourceBundle, is accessible from
|
||||
* ResourceBundle, and can be instantiated, <code>getBundle</code> creates a
|
||||
* new instance of this class and uses it as the <em>result resource
|
||||
* bundle</em>.
|
||||
*
|
||||
* <li>Otherwise, <code>getBundle</code> attempts to locate a property
|
||||
* resource file using the generated properties file name. It generates a
|
||||
* path name from the candidate bundle name by replacing all "." characters
|
||||
* with "/" and appending the string ".properties". It attempts to find a
|
||||
* "resource" with this name using {@link
|
||||
* java.lang.ClassLoader#getResource(java.lang.String)
|
||||
* ClassLoader.getResource}. (Note that a "resource" in the sense of
|
||||
* <code>getResource</code> has nothing to do with the contents of a
|
||||
* resource bundle, it is just a container of data, such as a file.) If it
|
||||
* finds a "resource", it attempts to create a new {@link
|
||||
* PropertyResourceBundle} instance from its contents. If successful, this
|
||||
* instance becomes the <em>result resource bundle</em>. </ul>
|
||||
*
|
||||
* <p>This continues until a result resource bundle is instantiated or the
|
||||
* list of candidate bundle names is exhausted. If no matching resource
|
||||
* bundle is found, the default control's {@link Control#getFallbackLocale
|
||||
* getFallbackLocale} method is called, which returns the current default
|
||||
* locale. A new sequence of candidate locale names is generated using this
|
||||
* locale and and searched again, as above.
|
||||
*
|
||||
* <p>If still no result bundle is found, the base name alone is looked up. If
|
||||
* this still fails, a <code>MissingResourceException</code> is thrown.
|
||||
*
|
||||
* <p><a name="parent_chain"/> Once a result resource bundle has been found,
|
||||
* its <em>parent chain</em> is instantiated. If the result bundle already
|
||||
* has a parent (perhaps because it was returned from a cache) the chain is
|
||||
* complete.
|
||||
*
|
||||
* <p>Otherwise, <code>getBundle</code> examines the remainder of the
|
||||
* candidate locale list that was used during the pass that generated the
|
||||
* result resource bundle. (As before, candidate bundle names where the
|
||||
* final component is an empty string are omitted.) When it comes to the
|
||||
* end of the candidate list, it tries the plain bundle name. With each of the
|
||||
* candidate bundle names it attempts to instantiate a resource bundle (first
|
||||
* looking for a class and then a properties file, as described above).
|
||||
*
|
||||
* <p>Whenever it succeeds, it calls the previously instantiated resource
|
||||
* bundle's {@link #setParent(java.util.ResourceBundle) setParent} method
|
||||
* with the new resource bundle, unless the previously instantiated resource
|
||||
* bundle already has a non-null parent.
|
||||
* with the new resource bundle. This continues until the list of names
|
||||
* is exhausted or the current bundle already has a non-null parent.
|
||||
*
|
||||
* <p>
|
||||
* <code>getBundle</code> caches instantiated resource bundles and
|
||||
* may return the same resource bundle instance multiple
|
||||
* times.
|
||||
* <p>Once the parent chain is complete, the bundle is returned.
|
||||
*
|
||||
* <p>
|
||||
* The <code>baseName</code> argument should be a fully qualified class name. However, for
|
||||
* compatibility with earlier versions, Sun's Java SE Runtime Environments do not verify this,
|
||||
* and so it is possible to access <code>PropertyResourceBundle</code>s by specifying a
|
||||
* path name (using "/") instead of a fully qualified class name (using ".").
|
||||
* <p><b>Note:</b> <code>getBundle</code> caches instantiated resource
|
||||
* bundles and might return the same resource bundle instance multiple times.
|
||||
*
|
||||
* <p><b>Note:</b>The <code>baseName</code> argument should be a fully
|
||||
* qualified class name. However, for compatibility with earlier versions,
|
||||
* Sun's Java SE Runtime Environments do not verify this, and so it is
|
||||
* possible to access <code>PropertyResourceBundle</code>s by specifying a
|
||||
* path name (using "/") instead of a fully qualified class name (using
|
||||
* ".").
|
||||
*
|
||||
* <p><a name="default_behavior_example"/>
|
||||
* <strong>Example:</strong><br>The following class and property files are provided:
|
||||
* <strong>Example:</strong>
|
||||
* <p>
|
||||
* The following class and property files are provided:
|
||||
* <pre>
|
||||
* MyResources.class
|
||||
* MyResources.properties
|
||||
@ -944,22 +999,26 @@ public abstract class ResourceBundle {
|
||||
* MyResources_en.properties
|
||||
* MyResources_es_ES.class
|
||||
* </pre>
|
||||
* The contents of all files are valid (that is, public non-abstract subclasses of <code>ResourceBundle</code> for
|
||||
* the ".class" files, syntactically correct ".properties" files).
|
||||
* The default locale is <code>Locale("en", "GB")</code>.
|
||||
* <p>
|
||||
* Calling <code>getBundle</code> with the shown locale argument values instantiates
|
||||
* resource bundles from the following sources:
|
||||
* <ul>
|
||||
* <li>Locale("fr", "CH"): result MyResources_fr_CH.class, parent MyResources_fr.properties, parent MyResources.class
|
||||
* <li>Locale("fr", "FR"): result MyResources_fr.properties, parent MyResources.class
|
||||
* <li>Locale("de", "DE"): result MyResources_en.properties, parent MyResources.class
|
||||
* <li>Locale("en", "US"): result MyResources_en.properties, parent MyResources.class
|
||||
* <li>Locale("es", "ES"): result MyResources_es_ES.class, parent MyResources.class
|
||||
* </ul>
|
||||
* <p>The file MyResources_fr_CH.properties is never used because it is hidden by
|
||||
* MyResources_fr_CH.class. Likewise, MyResources.properties is also hidden by
|
||||
* MyResources.class.
|
||||
*
|
||||
* The contents of all files are valid (that is, public non-abstract
|
||||
* subclasses of <code>ResourceBundle</code> for the ".class" files,
|
||||
* syntactically correct ".properties" files). The default locale is
|
||||
* <code>Locale("en", "GB")</code>.
|
||||
*
|
||||
* <p>Calling <code>getBundle</code> with the locale arguments below will
|
||||
* instantiate resource bundles as follows:
|
||||
*
|
||||
* <table>
|
||||
* <tr><td>Locale("fr", "CH")</td><td>MyResources_fr_CH.class, parent MyResources_fr.properties, parent MyResources.class</td></tr>
|
||||
* <tr><td>Locale("fr", "FR")</td><td>MyResources_fr.properties, parent MyResources.class</td></tr>
|
||||
* <tr><td>Locale("de", "DE")</td><td>MyResources_en.properties, parent MyResources.class</td></tr>
|
||||
* <tr><td>Locale("en", "US")</td><td>MyResources_en.properties, parent MyResources.class</td></tr>
|
||||
* <tr><td>Locale("es", "ES")</td><td>MyResources_es_ES.class, parent MyResources.class</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>The file MyResources_fr_CH.properties is never used because it is
|
||||
* hidden by the MyResources_fr_CH.class. Likewise, MyResources.properties
|
||||
* is also hidden by MyResources.class.
|
||||
*
|
||||
* @param baseName the base name of the resource bundle, a fully qualified class name
|
||||
* @param locale the locale for which a resource bundle is desired
|
||||
@ -1095,8 +1154,6 @@ public abstract class ResourceBundle {
|
||||
* href="./ResourceBundle.html#parent_chain">parent chain</a> is
|
||||
* instantiated based on the list of candidate locales from which it was
|
||||
* found. Finally, the bundle is returned to the caller.</li>
|
||||
*
|
||||
*
|
||||
* </ol>
|
||||
*
|
||||
* <p>During the resource bundle loading process above, this factory
|
||||
@ -1119,7 +1176,6 @@ public abstract class ResourceBundle {
|
||||
* {@link Control#getTimeToLive(String,Locale)
|
||||
* control.getTimeToLive} for details.
|
||||
*
|
||||
*
|
||||
* <p>The following is an example of the bundle loading process with the
|
||||
* default <code>ResourceBundle.Control</code> implementation.
|
||||
*
|
||||
@ -1131,7 +1187,6 @@ public abstract class ResourceBundle {
|
||||
* <li>Available resource bundles:
|
||||
* <code>foo/bar/Messages_fr.properties</code> and
|
||||
* <code>foo/bar/Messages.properties</code></li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>First, <code>getBundle</code> tries loading a resource bundle in
|
||||
@ -1811,8 +1866,8 @@ public abstract class ResourceBundle {
|
||||
* handleGetObject} method returns <code>null</code>. Once the
|
||||
* <code>Set</code> has been created, the value is kept in this
|
||||
* <code>ResourceBundle</code> in order to avoid producing the
|
||||
* same <code>Set</code> in the next calls. Override this method
|
||||
* in subclass implementations for faster handling.
|
||||
* same <code>Set</code> in subsequent calls. Subclasses can
|
||||
* override this method for faster handling.
|
||||
*
|
||||
* @return a <code>Set</code> of the keys contained only in this
|
||||
* <code>ResourceBundle</code>
|
||||
@ -2177,24 +2232,133 @@ public abstract class ResourceBundle {
|
||||
* <code>ResourceBundle.getBundle</code> factory method loads only
|
||||
* the base bundle as the resulting resource bundle.
|
||||
*
|
||||
* <p>It is not a requirement to return an immutable
|
||||
* (unmodifiable) <code>List</code>. However, the returned
|
||||
* <code>List</code> must not be mutated after it has been
|
||||
* returned by <code>getCandidateLocales</code>.
|
||||
* <p>It is not a requirement to return an immutable (unmodifiable)
|
||||
* <code>List</code>. However, the returned <code>List</code> must not
|
||||
* be mutated after it has been returned by
|
||||
* <code>getCandidateLocales</code>.
|
||||
*
|
||||
* <p>The default implementation returns a <code>List</code> containing
|
||||
* <code>Locale</code>s in the following sequence:
|
||||
* <pre>
|
||||
* Locale(language, country, variant)
|
||||
* Locale(language, country)
|
||||
* Locale(language)
|
||||
* Locale.ROOT
|
||||
* </pre>
|
||||
* where <code>language</code>, <code>country</code> and
|
||||
* <code>variant</code> are the language, country and variant values
|
||||
* of the given <code>locale</code>, respectively. Locales where the
|
||||
* <code>Locale</code>s using the rules described below. In the
|
||||
* description below, <em>L</em>, <em>S</em>, <em>C</em> and <em>V</em>
|
||||
* respectively represent non-empty language, script, country, and
|
||||
* variant. For example, [<em>L</em>, <em>C</em>] represents a
|
||||
* <code>Locale</code> that has non-empty values only for language and
|
||||
* country. The form <em>L</em>("xx") represents the (non-empty)
|
||||
* language value is "xx". For all cases, <code>Locale</code>s whose
|
||||
* final component values are empty strings are omitted.
|
||||
*
|
||||
* <ol><li>For an input <code>Locale</code> with an empty script value,
|
||||
* append candidate <code>Locale</code>s by omitting the final component
|
||||
* one by one as below:
|
||||
*
|
||||
* <ul>
|
||||
* <li> [<em>L</em>, <em>C</em>, <em>V</em>]
|
||||
* <li> [<em>L</em>, <em>C</em>]
|
||||
* <li> [<em>L</em>]
|
||||
* <li> <code>Locale.ROOT</code>
|
||||
* </ul>
|
||||
*
|
||||
* <li>For an input <code>Locale</code> with a non-empty script value,
|
||||
* append candidate <code>Locale</code>s by omitting the final component
|
||||
* up to language, then append candidates generated from the
|
||||
* <code>Locale</code> with country and variant restored:
|
||||
*
|
||||
* <ul>
|
||||
* <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V</em>]
|
||||
* <li> [<em>L</em>, <em>S</em>, <em>C</em>]
|
||||
* <li> [<em>L</em>, <em>S</em>]
|
||||
* <li> [<em>L</em>, <em>C</em>, <em>V</em>]
|
||||
* <li> [<em>L</em>, <em>C</em>]
|
||||
* <li> [<em>L</em>]
|
||||
* <li> <code>Locale.ROOT</code>
|
||||
* </ul>
|
||||
*
|
||||
* <li>For an input <code>Locale</code> with a variant value consisting
|
||||
* of multiple subtags separated by underscore, generate candidate
|
||||
* <code>Locale</code>s by omitting the variant subtags one by one, then
|
||||
* insert them after every occurence of <code> Locale</code>s with the
|
||||
* full variant value in the original list. For example, if the
|
||||
* the variant consists of two subtags <em>V1</em> and <em>V2</em>:
|
||||
*
|
||||
* <ul>
|
||||
* <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
|
||||
* <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>]
|
||||
* <li> [<em>L</em>, <em>S</em>, <em>C</em>]
|
||||
* <li> [<em>L</em>, <em>S</em>]
|
||||
* <li> [<em>L</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
|
||||
* <li> [<em>L</em>, <em>C</em>, <em>V1</em>]
|
||||
* <li> [<em>L</em>, <em>C</em>]
|
||||
* <li> [<em>L</em>]
|
||||
* <li> <code>Locale.ROOT</code>
|
||||
* </ul>
|
||||
*
|
||||
* <li>Special cases for Chinese. When an input <code>Locale</code> has the
|
||||
* language "zh" (Chinese) and an empty script value, either "Hans" (Simplified) or
|
||||
* "Hant" (Traditional) might be supplied, depending on the country.
|
||||
* When the country is "CN" (China) or "SG" (Singapore), "Hans" is supplied.
|
||||
* When the country is "HK" (Hong Kong SAR China), "MO" (Macau SAR China),
|
||||
* or "TW" (Taiwan), "Hant" is supplied. For all other countries or when the country
|
||||
* is empty, no script is supplied. For example, for <code>Locale("zh", "CN")
|
||||
* </code>, the candidate list will be:
|
||||
* <ul>
|
||||
* <li> [<em>L</em>("zh"), <em>S</em>("Hans"), <em>C</em>("CN")]
|
||||
* <li> [<em>L</em>("zh"), <em>S</em>("Hans")]
|
||||
* <li> [<em>L</em>("zh"), <em>C</em>("CN")]
|
||||
* <li> [<em>L</em>("zh")]
|
||||
* <li> <code>Locale.ROOT</code>
|
||||
* </ul>
|
||||
*
|
||||
* For <code>Locale("zh", "TW")</code>, the candidate list will be:
|
||||
* <ul>
|
||||
* <li> [<em>L</em>("zh"), <em>S</em>("Hant"), <em>C</em>("TW")]
|
||||
* <li> [<em>L</em>("zh"), <em>S</em>("Hant")]
|
||||
* <li> [<em>L</em>("zh"), <em>C</em>("TW")]
|
||||
* <li> [<em>L</em>("zh")]
|
||||
* <li> <code>Locale.ROOT</code>
|
||||
* </ul>
|
||||
*
|
||||
* <li>Special cases for Norwegian. Both <code>Locale("no", "NO",
|
||||
* "NY")</code> and <code>Locale("nn", "NO")</code> represent Norwegian
|
||||
* Nynorsk. When a locale's language is "nn", the standard candidate
|
||||
* list is generated up to [<em>L</em>("nn")], and then the following
|
||||
* candidates are added:
|
||||
*
|
||||
* <ul><li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("NY")]
|
||||
* <li> [<em>L</em>("no"), <em>C</em>("NO")]
|
||||
* <li> [<em>L</em>("no")]
|
||||
* <li> <code>Locale.ROOT</code>
|
||||
* </ul>
|
||||
*
|
||||
* If the locale is exactly <code>Locale("no", "NO", "NY")</code>, it is first
|
||||
* converted to <code>Locale("nn", "NO")</code> and then the above procedure is
|
||||
* followed.
|
||||
*
|
||||
* <p>Also, Java treats the language "no" as a synonym of Norwegian
|
||||
* Bokmål "nb". Except for the single case <code>Locale("no",
|
||||
* "NO", "NY")</code> (handled above), when an input <code>Locale</code>
|
||||
* has language "no" or "nb", candidate <code>Locale</code>s with
|
||||
* language code "no" and "nb" are interleaved, first using the
|
||||
* requested language, then using its synonym. For example,
|
||||
* <code>Locale("nb", "NO", "POSIX")</code> generates the following
|
||||
* candidate list:
|
||||
*
|
||||
* <ul>
|
||||
* <li> [<em>L</em>("nb"), <em>C</em>("NO"), <em>V</em>("POSIX")]
|
||||
* <li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("POSIX")]
|
||||
* <li> [<em>L</em>("nb"), <em>C</em>("NO")]
|
||||
* <li> [<em>L</em>("no"), <em>C</em>("NO")]
|
||||
* <li> [<em>L</em>("nb")]
|
||||
* <li> [<em>L</em>("no")]
|
||||
* <li> <code>Locale.ROOT</code>
|
||||
* </ul>
|
||||
*
|
||||
* <code>Locale("no", "NO", "POSIX")</code> would generate the same list
|
||||
* except that locales with "no" would appear before the corresponding
|
||||
* locales with "nb".</li>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>The default implementation uses an {@link ArrayList} that
|
||||
* overriding implementations may modify before returning it to the
|
||||
* caller. However, a subclass must not modify it after it has
|
||||
@ -2231,24 +2395,119 @@ public abstract class ResourceBundle {
|
||||
if (baseName == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
String language = locale.getLanguage();
|
||||
String country = locale.getCountry();
|
||||
String variant = locale.getVariant();
|
||||
return new ArrayList<Locale>(CANDIDATES_CACHE.get(locale.getBaseLocale()));
|
||||
}
|
||||
|
||||
List<Locale> locales = new ArrayList<Locale>(4);
|
||||
if (variant.length() > 0) {
|
||||
locales.add(locale);
|
||||
private static final CandidateListCache CANDIDATES_CACHE = new CandidateListCache();
|
||||
|
||||
private static class CandidateListCache extends LocaleObjectCache<BaseLocale, List<Locale>> {
|
||||
protected List<Locale> createObject(BaseLocale base) {
|
||||
String language = base.getLanguage();
|
||||
String script = base.getScript();
|
||||
String region = base.getRegion();
|
||||
String variant = base.getVariant();
|
||||
|
||||
// Special handling for Norwegian
|
||||
boolean isNorwegianBokmal = false;
|
||||
boolean isNorwegianNynorsk = false;
|
||||
if (language.equals("no")) {
|
||||
if (region.equals("NO") && variant.equals("NY")) {
|
||||
variant = "";
|
||||
isNorwegianNynorsk = true;
|
||||
} else {
|
||||
isNorwegianBokmal = true;
|
||||
}
|
||||
}
|
||||
if (language.equals("nb") || isNorwegianBokmal) {
|
||||
List<Locale> tmpList = getDefaultList("nb", script, region, variant);
|
||||
// Insert a locale replacing "nb" with "no" for every list entry
|
||||
List<Locale> bokmalList = new LinkedList<Locale>();
|
||||
for (Locale l : tmpList) {
|
||||
bokmalList.add(l);
|
||||
if (l.getLanguage().length() == 0) {
|
||||
break;
|
||||
}
|
||||
bokmalList.add(Locale.getInstance("no", l.getScript(), l.getCountry(),
|
||||
l.getVariant(), LocaleExtensions.EMPTY_EXTENSIONS));
|
||||
}
|
||||
return bokmalList;
|
||||
} else if (language.equals("nn") || isNorwegianNynorsk) {
|
||||
// Insert no_NO_NY, no_NO, no after nn
|
||||
List<Locale> nynorskList = getDefaultList("nn", script, region, variant);
|
||||
int idx = nynorskList.size() - 1;
|
||||
nynorskList.add(idx++, Locale.getInstance("no", "NO", "NY"));
|
||||
nynorskList.add(idx++, Locale.getInstance("no", "NO", ""));
|
||||
nynorskList.add(idx++, Locale.getInstance("no", "", ""));
|
||||
return nynorskList;
|
||||
}
|
||||
// Special handling for Chinese
|
||||
else if (language.equals("zh")) {
|
||||
if (script.length() == 0 && region.length() > 0) {
|
||||
// Supply script for users who want to use zh_Hans/zh_Hant
|
||||
// as bundle names (recommended for Java7+)
|
||||
if (region.equals("TW") || region.equals("HK") || region.equals("MO")) {
|
||||
script = "Hant";
|
||||
} else if (region.equals("CN") || region.equals("SG")) {
|
||||
script = "Hans";
|
||||
}
|
||||
} else if (script.length() > 0 && region.length() == 0) {
|
||||
// Supply region(country) for users who still package Chinese
|
||||
// bundles using old convension.
|
||||
if (script.equals("Hans")) {
|
||||
region = "CN";
|
||||
} else if (script.equals("Hant")) {
|
||||
region = "TW";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getDefaultList(language, script, region, variant);
|
||||
}
|
||||
if (country.length() > 0) {
|
||||
locales.add((locales.size() == 0) ?
|
||||
locale : Locale.getInstance(language, country, ""));
|
||||
|
||||
private static List<Locale> getDefaultList(String language, String script, String region, String variant) {
|
||||
List<String> variants = null;
|
||||
|
||||
if (variant.length() > 0) {
|
||||
variants = new LinkedList<String>();
|
||||
int idx = variant.length();
|
||||
while (idx != -1) {
|
||||
variants.add(variant.substring(0, idx));
|
||||
idx = variant.lastIndexOf('_', --idx);
|
||||
}
|
||||
}
|
||||
|
||||
LinkedList<Locale> list = new LinkedList<Locale>();
|
||||
|
||||
if (variants != null) {
|
||||
for (String v : variants) {
|
||||
list.add(Locale.getInstance(language, script, region, v, LocaleExtensions.EMPTY_EXTENSIONS));
|
||||
}
|
||||
}
|
||||
if (region.length() > 0) {
|
||||
list.add(Locale.getInstance(language, script, region, "", LocaleExtensions.EMPTY_EXTENSIONS));
|
||||
}
|
||||
if (script.length() > 0) {
|
||||
list.add(Locale.getInstance(language, script, "", "", LocaleExtensions.EMPTY_EXTENSIONS));
|
||||
|
||||
// With script, after truncating variant, region and script,
|
||||
// start over without script.
|
||||
if (variants != null) {
|
||||
for (String v : variants) {
|
||||
list.add(Locale.getInstance(language, "", region, v, LocaleExtensions.EMPTY_EXTENSIONS));
|
||||
}
|
||||
}
|
||||
if (region.length() > 0) {
|
||||
list.add(Locale.getInstance(language, "", region, "", LocaleExtensions.EMPTY_EXTENSIONS));
|
||||
}
|
||||
}
|
||||
if (language.length() > 0) {
|
||||
list.add(Locale.getInstance(language, "", "", "", LocaleExtensions.EMPTY_EXTENSIONS));
|
||||
}
|
||||
// Add root locale at the end
|
||||
list.add(Locale.ROOT);
|
||||
|
||||
return list;
|
||||
}
|
||||
if (language.length() > 0) {
|
||||
locales.add((locales.size() == 0) ?
|
||||
locale : Locale.getInstance(language, "", ""));
|
||||
}
|
||||
locales.add(Locale.ROOT);
|
||||
return locales;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2606,13 +2865,14 @@ public abstract class ResourceBundle {
|
||||
*
|
||||
* <p>This implementation returns the following value:
|
||||
* <pre>
|
||||
* baseName + "_" + language + "_" + country + "_" + variant
|
||||
* baseName + "_" + language + "_" + script + "_" + country + "_" + variant
|
||||
* </pre>
|
||||
* where <code>language</code>, <code>country</code> and
|
||||
* <code>variant</code> are the language, country and variant values
|
||||
* of <code>locale</code>, respectively. Final component values that
|
||||
* are empty Strings are omitted along with the preceding '_'. If
|
||||
* all of the values are empty strings, then <code>baseName</code>
|
||||
* where <code>language</code>, <code>script</code>, <code>country</code>,
|
||||
* and <code>variant</code> are the language, script, country, and variant
|
||||
* values of <code>locale</code>, respectively. Final component values that
|
||||
* are empty Strings are omitted along with the preceding '_'. When the
|
||||
* script is empty, the script value is ommitted along with the preceding '_'.
|
||||
* If all of the values are empty strings, then <code>baseName</code>
|
||||
* is returned.
|
||||
*
|
||||
* <p>For example, if <code>baseName</code> is
|
||||
@ -2643,6 +2903,7 @@ public abstract class ResourceBundle {
|
||||
}
|
||||
|
||||
String language = locale.getLanguage();
|
||||
String script = locale.getScript();
|
||||
String country = locale.getCountry();
|
||||
String variant = locale.getVariant();
|
||||
|
||||
@ -2652,12 +2913,22 @@ public abstract class ResourceBundle {
|
||||
|
||||
StringBuilder sb = new StringBuilder(baseName);
|
||||
sb.append('_');
|
||||
if (variant != "") {
|
||||
sb.append(language).append('_').append(country).append('_').append(variant);
|
||||
} else if (country != "") {
|
||||
sb.append(language).append('_').append(country);
|
||||
if (script != "") {
|
||||
if (variant != "") {
|
||||
sb.append(language).append('_').append(script).append('_').append(country).append('_').append(variant);
|
||||
} else if (country != "") {
|
||||
sb.append(language).append('_').append(script).append('_').append(country);
|
||||
} else {
|
||||
sb.append(language).append('_').append(script);
|
||||
}
|
||||
} else {
|
||||
sb.append(language);
|
||||
if (variant != "") {
|
||||
sb.append(language).append('_').append(country).append('_').append(variant);
|
||||
} else if (country != "") {
|
||||
sb.append(language).append('_').append(country);
|
||||
} else {
|
||||
sb.append(language);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2010, 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
|
||||
@ -44,22 +44,23 @@ public abstract class LocaleNameProvider extends LocaleServiceProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given ISO 639 language code and the
|
||||
* given locale that is appropriate for display to the user.
|
||||
* Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
|
||||
* IETF BCP47</a> language code and the given locale that is appropriate for
|
||||
* display to the user.
|
||||
* For example, if <code>languageCode</code> is "fr" and <code>locale</code>
|
||||
* is en_US, getDisplayLanguage() will return "French"; if <code>languageCode</code>
|
||||
* is "en" and <code>locale</code> is fr_FR, getDisplayLanguage() will return "anglais".
|
||||
* If the name returned cannot be localized according to <code>locale</code>,
|
||||
* (say, the provider does not have a Japanese name for Croatian),
|
||||
* this method returns null.
|
||||
* @param languageCode the ISO 639 language code string in the form of two
|
||||
* @param languageCode the language code string in the form of two to eight
|
||||
* lower-case letters between 'a' (U+0061) and 'z' (U+007A)
|
||||
* @param locale the desired locale
|
||||
* @return the name of the given language code for the specified locale, or null if it's not
|
||||
* available.
|
||||
* @exception NullPointerException if <code>languageCode</code> or <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>languageCode</code> is not in the form of
|
||||
* two lower-case letters, or <code>locale</code> isn't
|
||||
* two or three lower-case letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
@ -68,22 +69,52 @@ public abstract class LocaleNameProvider extends LocaleServiceProvider {
|
||||
public abstract String getDisplayLanguage(String languageCode, Locale locale);
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given ISO 3166 country code and the
|
||||
* given locale that is appropriate for display to the user.
|
||||
* Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
|
||||
* IETF BCP47</a> script code and the given locale that is appropriate for
|
||||
* display to the user.
|
||||
* For example, if <code>scriptCode</code> is "Latn" and <code>locale</code>
|
||||
* is en_US, getDisplayScript() will return "Latin"; if <code>scriptCode</code>
|
||||
* is "Cyrl" and <code>locale</code> is fr_FR, getDisplayScript() will return "cyrillique".
|
||||
* If the name returned cannot be localized according to <code>locale</code>,
|
||||
* (say, the provider does not have a Japanese name for Cyrillic),
|
||||
* this method returns null.
|
||||
* @param scriptCode the four letter script code string in the form of title-case
|
||||
* letters (the first letter is upper-case character between 'A' (U+0041) and
|
||||
* 'Z' (U+005A) followed by three lower-case character between 'a' (U+0061)
|
||||
* and 'z' (U+007A)).
|
||||
* @param locale the desired locale
|
||||
* @return the name of the given script code for the specified locale, or null if it's not
|
||||
* available.
|
||||
* @exception NullPointerException if <code>scriptCode</code> or <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>scriptCode</code> is not in the form of
|
||||
* four title case letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.util.Locale#getDisplayScript(java.util.Locale)
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract String getDisplayScript(String scriptCode, Locale locale);
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
|
||||
* IETF BCP47</a> region code (either ISO 3166 country code or UN M.49 area
|
||||
* codes) and the given locale that is appropriate for display to the user.
|
||||
* For example, if <code>countryCode</code> is "FR" and <code>locale</code>
|
||||
* is en_US, getDisplayCountry() will return "France"; if <code>countryCode</code>
|
||||
* is "US" and <code>locale</code> is fr_FR, getDisplayCountry() will return "Etats-Unis".
|
||||
* If the name returned cannot be localized according to <code>locale</code>,
|
||||
* (say, the provider does not have a Japanese name for Croatia),
|
||||
* this method returns null.
|
||||
* @param countryCode the ISO 3166 country code string in the form of two
|
||||
* upper-case letters between 'A' (U+0041) and 'Z' (U+005A)
|
||||
* @param countryCode the country(region) code string in the form of two
|
||||
* upper-case letters between 'A' (U+0041) and 'Z' (U+005A) or the UN M.49 area code
|
||||
* in the form of three digit letters between '0' (U+0030) and '9' (U+0039).
|
||||
* @param locale the desired locale
|
||||
* @return the name of the given country code for the specified locale, or null if it's not
|
||||
* available.
|
||||
* @exception NullPointerException if <code>countryCode</code> or <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>countryCode</code> is not in the form of
|
||||
* two upper-case letters, or <code>locale</code> isn't
|
||||
* two upper-case letters or three digit letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
|
@ -86,18 +86,19 @@ import java.util.Locale;
|
||||
* Otherwise, they call the <code>getAvailableLocales()</code> methods of
|
||||
* installed providers for the appropriate interface to find one that
|
||||
* supports the requested locale. If such a provider is found, its other
|
||||
* methods are called to obtain the requested object or name. If neither
|
||||
* the Java runtime environment itself nor an installed provider supports
|
||||
* the requested locale, a fallback locale is constructed by replacing the
|
||||
* first of the variant, country, or language strings of the locale that's
|
||||
* not an empty string with an empty string, and the lookup process is
|
||||
* restarted. In the case that the variant contains one or more '_'s, the
|
||||
* fallback locale is constructed by replacing the variant with a new variant
|
||||
* which eliminates the last '_' and the part following it. Even if a
|
||||
* fallback occurs, methods that return requested objects or name are
|
||||
* invoked with the original locale before the fallback.The Java runtime
|
||||
* environment must support the root locale for all locale sensitive services
|
||||
* in order to guarantee that this process terminates.
|
||||
* methods are called to obtain the requested object or name. When checking
|
||||
* whether a locale is supported, the locale's extensions are ignored.
|
||||
* If neither the Java runtime environment itself nor an installed provider
|
||||
* supports the requested locale, the methods go through a list of candidate
|
||||
* locales and repeat the availability check for each until a match is found.
|
||||
* The algorithm used for creating a list of candidate locales is same as
|
||||
* the one used by <code>ResourceBunlde</code> by default (see
|
||||
* {@link java.util.ResourceBundle.Control#getCandidateLocales getCandidateLocales}
|
||||
* for the details). Even if a locale is resolved from the candidate list,
|
||||
* methods that return requested objects or names are invoked with the original
|
||||
* requested locale including extensions. The Java runtime environment must
|
||||
* support the root locale for all locale sensitive services in order to
|
||||
* guarantee that this process terminates.
|
||||
* <p>
|
||||
* Providers of names (but not providers of other objects) are allowed to
|
||||
* return null for some name requests even for locales that they claim to
|
||||
@ -124,6 +125,11 @@ public abstract class LocaleServiceProvider {
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
* <p>
|
||||
* <b>Note:</b> Extensions in a <code>Locale</code> are ignored during
|
||||
* service provider lookup. So the array returned by this method should
|
||||
* not include two or more <code>Locale</code> objects only differing in
|
||||
* their extensions.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2010, 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
|
||||
@ -554,14 +554,14 @@ public class AudioFormat {
|
||||
* which is simply a linear (proportional) representation of the sound
|
||||
* waveform. With PCM, the number stored in each sample is proportional
|
||||
* to the instantaneous amplitude of the sound pressure at that point in
|
||||
* time. The numbers are frequently signed or unsigned integers.
|
||||
* time. The numbers may be signed or unsigned integers or floats.
|
||||
* Besides PCM, other encodings include mu-law and a-law, which are nonlinear
|
||||
* mappings of the sound amplitude that are often used for recording speech.
|
||||
* <p>
|
||||
* You can use a predefined encoding by referring to one of the static
|
||||
* objects created by this class, such as PCM_SIGNED or
|
||||
* PCM_UNSIGNED. Service providers can create new encodings, such as
|
||||
* compressed audio formats or floating-point PCM samples, and make
|
||||
* compressed audio formats, and make
|
||||
* these available through the <code>{@link AudioSystem}</code> class.
|
||||
* <p>
|
||||
* The <code>Encoding</code> class is static, so that all
|
||||
@ -591,6 +591,13 @@ public class AudioFormat {
|
||||
*/
|
||||
public static final Encoding PCM_UNSIGNED = new Encoding("PCM_UNSIGNED");
|
||||
|
||||
/**
|
||||
* Specifies floating-point PCM data.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
|
||||
|
||||
/**
|
||||
* Specifies u-law encoded data.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2010, 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
|
||||
@ -914,6 +914,7 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI
|
||||
UIResource {
|
||||
public SynthScrollableTabButton(int direction) {
|
||||
super(direction);
|
||||
setName("TabbedPane.button");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2010, 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
|
||||
@ -28,18 +28,20 @@ package sun.util;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.IllformedLocaleException;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Locale.Builder;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle.Control;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import sun.util.resources.LocaleData;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
@ -89,6 +91,16 @@ public final class LocaleServiceProviderPool {
|
||||
*/
|
||||
private Set<Locale> providerLocales = null;
|
||||
|
||||
/**
|
||||
* Special locale for ja_JP with Japanese calendar
|
||||
*/
|
||||
private static Locale locale_ja_JP_JP = new Locale("ja", "JP", "JP");
|
||||
|
||||
/**
|
||||
* Special locale for th_TH with Thai numbering system
|
||||
*/
|
||||
private static Locale locale_th_TH_TH = new Locale("th", "TH", "TH");
|
||||
|
||||
/**
|
||||
* A factory method that returns a singleton instance
|
||||
*/
|
||||
@ -153,14 +165,20 @@ public final class LocaleServiceProviderPool {
|
||||
java.util.spi.CurrencyNameProvider.class,
|
||||
java.util.spi.LocaleNameProvider.class,
|
||||
java.util.spi.TimeZoneNameProvider.class };
|
||||
Set<Locale> all = new HashSet<Locale>(Arrays.asList(
|
||||
LocaleData.getAvailableLocales())
|
||||
);
|
||||
|
||||
// Normalize locales for look up
|
||||
Locale[] allLocales = LocaleData.getAvailableLocales();
|
||||
Set<Locale> all = new HashSet<Locale>(allLocales.length);
|
||||
for (Locale locale : allLocales) {
|
||||
all.add(getLookupLocale(locale));
|
||||
}
|
||||
|
||||
for (Class providerClass : providerClasses) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(providerClass);
|
||||
all.addAll(pool.getProviderLocales());
|
||||
}
|
||||
|
||||
allAvailableLocales = all.toArray(new Locale[0]);
|
||||
}
|
||||
}
|
||||
@ -196,7 +214,8 @@ public final class LocaleServiceProviderPool {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of available locales from providers.
|
||||
* Returns an array of available locales (already normalized
|
||||
* for service lookup) from providers.
|
||||
* Note that this method does not return a defensive copy.
|
||||
*
|
||||
* @return list of the provider locales
|
||||
@ -208,7 +227,7 @@ public final class LocaleServiceProviderPool {
|
||||
for (LocaleServiceProvider lsp : providers) {
|
||||
Locale[] locales = lsp.getAvailableLocales();
|
||||
for (Locale locale: locales) {
|
||||
providerLocales.add(locale);
|
||||
providerLocales.add(getLookupLocale(locale));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -227,15 +246,19 @@ public final class LocaleServiceProviderPool {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of available locales supported by the JRE.
|
||||
* Returns an array of available locales (already normalized for
|
||||
* service lookup) supported by the JRE.
|
||||
* Note that this method does not return a defensive copy.
|
||||
*
|
||||
* @return list of the available JRE locales
|
||||
*/
|
||||
private synchronized List<Locale> getJRELocales() {
|
||||
if (availableJRELocales == null) {
|
||||
availableJRELocales =
|
||||
Arrays.asList(LocaleData.getAvailableLocales());
|
||||
Locale[] allLocales = LocaleData.getAvailableLocales();
|
||||
availableJRELocales = new ArrayList<Locale>(allLocales.length);
|
||||
for (Locale locale : allLocales) {
|
||||
availableJRELocales.add(getLookupLocale(locale));
|
||||
}
|
||||
}
|
||||
return availableJRELocales;
|
||||
}
|
||||
@ -249,7 +272,7 @@ public final class LocaleServiceProviderPool {
|
||||
*/
|
||||
private boolean isJRESupported(Locale locale) {
|
||||
List<Locale> locales = getJRELocales();
|
||||
return locales.contains(locale);
|
||||
return locales.contains(getLookupLocale(locale));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,7 +348,7 @@ public final class LocaleServiceProviderPool {
|
||||
bundleKey = key;
|
||||
}
|
||||
Locale bundleLocale = (bundle != null ? bundle.getLocale() : null);
|
||||
Locale requested = locale;
|
||||
List<Locale> lookupLocales = getLookupLocales(locale);
|
||||
P lsp;
|
||||
S providersObj = null;
|
||||
|
||||
@ -333,21 +356,30 @@ public final class LocaleServiceProviderPool {
|
||||
// to the requested locale than the bundle we've found (for
|
||||
// localized names), or Java runtime's supported locale
|
||||
// (for localized objects)
|
||||
while ((locale = findProviderLocale(locale, bundleLocale)) != null) {
|
||||
|
||||
lsp = (P)findProvider(locale);
|
||||
|
||||
if (lsp != null) {
|
||||
providersObj = getter.getObject(lsp, requested, key, params);
|
||||
if (providersObj != null) {
|
||||
return providersObj;
|
||||
} else if (isObjectProvider) {
|
||||
config(
|
||||
"A locale sensitive service provider returned null for a localized objects, which should not happen. provider: " + lsp + " locale: " + requested);
|
||||
Set<Locale> provLoc = getProviderLocales();
|
||||
for (int i = 0; i < lookupLocales.size(); i++) {
|
||||
Locale current = lookupLocales.get(i);
|
||||
if (bundleLocale != null) {
|
||||
if (current.equals(bundleLocale)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (isJRESupported(current)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (provLoc.contains(current)) {
|
||||
lsp = (P)findProvider(current);
|
||||
if (lsp != null) {
|
||||
providersObj = getter.getObject(lsp, locale, key, params);
|
||||
if (providersObj != null) {
|
||||
return providersObj;
|
||||
} else if (isObjectProvider) {
|
||||
config(
|
||||
"A locale sensitive service provider returned null for a localized objects, which should not happen. provider: " + lsp + " locale: " + locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locale = getParentLocale(locale);
|
||||
}
|
||||
|
||||
// look up the JRE bundle and its parent chain. Only
|
||||
@ -361,7 +393,7 @@ public final class LocaleServiceProviderPool {
|
||||
} else {
|
||||
lsp = (P)findProvider(bundleLocale);
|
||||
if (lsp != null) {
|
||||
providersObj = getter.getObject(lsp, requested, key, params);
|
||||
providersObj = getter.getObject(lsp, locale, key, params);
|
||||
if (providersObj != null) {
|
||||
return providersObj;
|
||||
}
|
||||
@ -399,6 +431,8 @@ public final class LocaleServiceProviderPool {
|
||||
for (LocaleServiceProvider lsp : providers) {
|
||||
Locale[] locales = lsp.getAvailableLocales();
|
||||
for (Locale available: locales) {
|
||||
// normalize
|
||||
available = getLookupLocale(available);
|
||||
if (locale.equals(available)) {
|
||||
LocaleServiceProvider providerInCache =
|
||||
providersCache.put(locale, lsp);
|
||||
@ -414,66 +448,51 @@ public final class LocaleServiceProviderPool {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provider's locale that is the most appropriate
|
||||
* within the range
|
||||
*
|
||||
* @param start the given locale that is used as the starting one
|
||||
* @param end the given locale that is used as the end one (exclusive),
|
||||
* or null if it reaching any of the JRE supported locale should
|
||||
* terminate the look up.
|
||||
* @return the most specific locale within the range, or null
|
||||
* if no provider locale found in that range.
|
||||
* Returns a list of candidate locales for service look up.
|
||||
* @param locale the input locale
|
||||
* @return the list of candiate locales for the given locale
|
||||
*/
|
||||
private Locale findProviderLocale(Locale start, Locale end) {
|
||||
Set<Locale> provLoc = getProviderLocales();
|
||||
Locale current = start;
|
||||
|
||||
while (current != null) {
|
||||
if (end != null) {
|
||||
if (current.equals(end)) {
|
||||
current = null;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (isJRESupported(current)) {
|
||||
current = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (provLoc.contains(current)) {
|
||||
break;
|
||||
}
|
||||
|
||||
current = getParentLocale(current);
|
||||
}
|
||||
|
||||
return current;
|
||||
private static List<Locale> getLookupLocales(Locale locale) {
|
||||
// Note: We currently use the default implementation of
|
||||
// ResourceBundle.Control.getCandidateLocales. The result
|
||||
// returned by getCandidateLocales are already normalized
|
||||
// (no extensions) for service look up.
|
||||
List<Locale> lookupLocales = new Control(){}.getCandidateLocales("", locale);
|
||||
return lookupLocales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent locale.
|
||||
* Returns an instance of Locale used for service look up.
|
||||
* The result Locale has no extensions except for ja_JP_JP
|
||||
* and th_TH_TH
|
||||
*
|
||||
* @param locale the locale
|
||||
* @return the parent locale
|
||||
* @return the locale used for service look up
|
||||
*/
|
||||
private static Locale getParentLocale(Locale locale) {
|
||||
String variant = locale.getVariant();
|
||||
if (variant != "") {
|
||||
int underscoreIndex = variant.lastIndexOf('_');
|
||||
if (underscoreIndex != (-1)) {
|
||||
return new Locale(locale.getLanguage(), locale.getCountry(),
|
||||
variant.substring(0, underscoreIndex));
|
||||
} else {
|
||||
return new Locale(locale.getLanguage(), locale.getCountry());
|
||||
private static Locale getLookupLocale(Locale locale) {
|
||||
Locale lookupLocale = locale;
|
||||
Set<Character> extensions = locale.getExtensionKeys();
|
||||
if (!extensions.isEmpty()
|
||||
&& !locale.equals(locale_ja_JP_JP)
|
||||
&& !locale.equals(locale_th_TH_TH)) {
|
||||
// remove extensions
|
||||
Builder locbld = new Builder();
|
||||
try {
|
||||
locbld.setLocale(locale);
|
||||
locbld.clearExtensions();
|
||||
lookupLocale = locbld.build();
|
||||
} catch (IllformedLocaleException e) {
|
||||
// A Locale with non-empty extensions
|
||||
// should have well-formed fields except
|
||||
// for ja_JP_JP and th_TH_TH. Therefore,
|
||||
// it should never enter in this catch clause.
|
||||
config("A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
|
||||
|
||||
// Fallback - script field will be lost.
|
||||
lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant());
|
||||
}
|
||||
} else if (locale.getCountry() != "") {
|
||||
return new Locale(locale.getLanguage());
|
||||
} else if (locale.getLanguage() != "") {
|
||||
return Locale.ROOT;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return lookupLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,7 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
@ -472,17 +473,18 @@ public class ZoneInfoFile {
|
||||
|
||||
private static Map<String, ZoneInfo> zoneInfoObjects = null;
|
||||
|
||||
private static final String ziDir;
|
||||
static {
|
||||
String zi = (String) AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("java.home"))
|
||||
+ File.separator + "lib" + File.separator + "zi";
|
||||
try {
|
||||
zi = new File(zi).getCanonicalPath();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
ziDir = zi;
|
||||
}
|
||||
private static final String ziDir = AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
String zi = System.getProperty("java.home") +
|
||||
File.separator + "lib" + File.separator + "zi";
|
||||
try {
|
||||
zi = FileSystems.getDefault().getPath(zi).toRealPath(true).toString();
|
||||
} catch(Exception e) {
|
||||
}
|
||||
return zi;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Converts the given time zone ID to a platform dependent path
|
||||
|
208
jdk/src/share/classes/sun/util/locale/AsciiUtil.java
Normal file
208
jdk/src/share/classes/sun/util/locale/AsciiUtil.java
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public final class AsciiUtil {
|
||||
public static boolean caseIgnoreMatch(String s1, String s2) {
|
||||
if (s1 == s2) {
|
||||
return true;
|
||||
}
|
||||
int len = s1.length();
|
||||
if (len != s2.length()) {
|
||||
return false;
|
||||
}
|
||||
int i = 0;
|
||||
while (i < len) {
|
||||
char c1 = s1.charAt(i);
|
||||
char c2 = s2.charAt(i);
|
||||
if (c1 != c2 && toLower(c1) != toLower(c2)) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return (i == len);
|
||||
}
|
||||
|
||||
public static int caseIgnoreCompare(String s1, String s2) {
|
||||
if (s1 == s2) {
|
||||
return 0;
|
||||
}
|
||||
return AsciiUtil.toLowerString(s1).compareTo(AsciiUtil.toLowerString(s2));
|
||||
}
|
||||
|
||||
|
||||
public static char toUpper(char c) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
c -= 0x20;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public static char toLower(char c) {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
c += 0x20;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public static String toLowerString(String s) {
|
||||
int idx = 0;
|
||||
for (; idx < s.length(); idx++) {
|
||||
char c = s.charAt(idx);
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == s.length()) {
|
||||
return s;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(s.substring(0, idx));
|
||||
for (; idx < s.length(); idx++) {
|
||||
buf.append(toLower(s.charAt(idx)));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String toUpperString(String s) {
|
||||
int idx = 0;
|
||||
for (; idx < s.length(); idx++) {
|
||||
char c = s.charAt(idx);
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == s.length()) {
|
||||
return s;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(s.substring(0, idx));
|
||||
for (; idx < s.length(); idx++) {
|
||||
buf.append(toUpper(s.charAt(idx)));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String toTitleString(String s) {
|
||||
if (s.length() == 0) {
|
||||
return s;
|
||||
}
|
||||
int idx = 0;
|
||||
char c = s.charAt(idx);
|
||||
if (!(c >= 'a' && c <= 'z')) {
|
||||
for (idx = 1; idx < s.length(); idx++) {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idx == s.length()) {
|
||||
return s;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(s.substring(0, idx));
|
||||
if (idx == 0) {
|
||||
buf.append(toUpper(s.charAt(idx)));
|
||||
idx++;
|
||||
}
|
||||
for (; idx < s.length(); idx++) {
|
||||
buf.append(toLower(s.charAt(idx)));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static boolean isAlpha(char c) {
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
public static boolean isAlphaString(String s) {
|
||||
boolean b = true;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (!isAlpha(s.charAt(i))) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static boolean isNumeric(char c) {
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
public static boolean isNumericString(String s) {
|
||||
boolean b = true;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (!isNumeric(s.charAt(i))) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static boolean isAlphaNumeric(char c) {
|
||||
return isAlpha(c) || isNumeric(c);
|
||||
}
|
||||
|
||||
public static boolean isAlphaNumericString(String s) {
|
||||
boolean b = true;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (!isAlphaNumeric(s.charAt(i))) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static class CaseInsensitiveKey {
|
||||
private String _key;
|
||||
private int _hash;
|
||||
|
||||
public CaseInsensitiveKey(String key) {
|
||||
_key = key;
|
||||
_hash = AsciiUtil.toLowerString(key).hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof CaseInsensitiveKey) {
|
||||
return AsciiUtil.caseIgnoreMatch(_key, ((CaseInsensitiveKey)o)._key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return _hash;
|
||||
}
|
||||
}
|
||||
}
|
253
jdk/src/share/classes/sun/util/locale/BaseLocale.java
Normal file
253
jdk/src/share/classes/sun/util/locale/BaseLocale.java
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
package sun.util.locale;
|
||||
|
||||
|
||||
public final class BaseLocale {
|
||||
|
||||
public static final String SEP = "_";
|
||||
|
||||
private static final Cache CACHE = new Cache();
|
||||
public static final BaseLocale ROOT = BaseLocale.getInstance("", "", "", "");
|
||||
|
||||
private String _language = "";
|
||||
private String _script = "";
|
||||
private String _region = "";
|
||||
private String _variant = "";
|
||||
|
||||
private transient volatile int _hash = 0;
|
||||
|
||||
private BaseLocale(String language, String script, String region, String variant) {
|
||||
if (language != null) {
|
||||
_language = AsciiUtil.toLowerString(language).intern();
|
||||
}
|
||||
if (script != null) {
|
||||
_script = AsciiUtil.toTitleString(script).intern();
|
||||
}
|
||||
if (region != null) {
|
||||
_region = AsciiUtil.toUpperString(region).intern();
|
||||
}
|
||||
if (variant != null) {
|
||||
_variant = variant.intern();
|
||||
}
|
||||
}
|
||||
|
||||
public static BaseLocale getInstance(String language, String script, String region, String variant) {
|
||||
// JDK uses deprecated ISO639.1 language codes for he, yi and id
|
||||
if (AsciiUtil.caseIgnoreMatch(language, "he")) {
|
||||
language = "iw";
|
||||
} else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
|
||||
language = "ji";
|
||||
} else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
|
||||
language = "in";
|
||||
}
|
||||
|
||||
Key key = new Key(language, script, region, variant);
|
||||
BaseLocale baseLocale = CACHE.get(key);
|
||||
return baseLocale;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return _language;
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return _script;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return _region;
|
||||
}
|
||||
|
||||
public String getVariant() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof BaseLocale)) {
|
||||
return false;
|
||||
}
|
||||
BaseLocale other = (BaseLocale)obj;
|
||||
return hashCode() == other.hashCode()
|
||||
&& _language.equals(other._language)
|
||||
&& _script.equals(other._script)
|
||||
&& _region.equals(other._region)
|
||||
&& _variant.equals(other._variant);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (_language.length() > 0) {
|
||||
buf.append("language=");
|
||||
buf.append(_language);
|
||||
}
|
||||
if (_script.length() > 0) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("script=");
|
||||
buf.append(_script);
|
||||
}
|
||||
if (_region.length() > 0) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("region=");
|
||||
buf.append(_region);
|
||||
}
|
||||
if (_variant.length() > 0) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("variant=");
|
||||
buf.append(_variant);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int h = _hash;
|
||||
if (h == 0) {
|
||||
// Generating a hash value from language, script, region and variant
|
||||
for (int i = 0; i < _language.length(); i++) {
|
||||
h = 31*h + _language.charAt(i);
|
||||
}
|
||||
for (int i = 0; i < _script.length(); i++) {
|
||||
h = 31*h + _script.charAt(i);
|
||||
}
|
||||
for (int i = 0; i < _region.length(); i++) {
|
||||
h = 31*h + _region.charAt(i);
|
||||
}
|
||||
for (int i = 0; i < _variant.length(); i++) {
|
||||
h = 31*h + _variant.charAt(i);
|
||||
}
|
||||
_hash = h;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private static class Key implements Comparable<Key> {
|
||||
private String _lang = "";
|
||||
private String _scrt = "";
|
||||
private String _regn = "";
|
||||
private String _vart = "";
|
||||
|
||||
private volatile int _hash; // Default to 0
|
||||
|
||||
public Key(String language, String script, String region, String variant) {
|
||||
if (language != null) {
|
||||
_lang = language;
|
||||
}
|
||||
if (script != null) {
|
||||
_scrt = script;
|
||||
}
|
||||
if (region != null) {
|
||||
_regn = region;
|
||||
}
|
||||
if (variant != null) {
|
||||
_vart = variant;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj) ||
|
||||
(obj instanceof Key)
|
||||
&& AsciiUtil.caseIgnoreMatch(((Key)obj)._lang, this._lang)
|
||||
&& AsciiUtil.caseIgnoreMatch(((Key)obj)._scrt, this._scrt)
|
||||
&& AsciiUtil.caseIgnoreMatch(((Key)obj)._regn, this._regn)
|
||||
&& ((Key)obj)._vart.equals(_vart); // variant is case sensitive in JDK!
|
||||
}
|
||||
|
||||
public int compareTo(Key other) {
|
||||
int res = AsciiUtil.caseIgnoreCompare(this._lang, other._lang);
|
||||
if (res == 0) {
|
||||
res = AsciiUtil.caseIgnoreCompare(this._scrt, other._scrt);
|
||||
if (res == 0) {
|
||||
res = AsciiUtil.caseIgnoreCompare(this._regn, other._regn);
|
||||
if (res == 0) {
|
||||
res = this._vart.compareTo(other._vart);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int h = _hash;
|
||||
if (h == 0) {
|
||||
// Generating a hash value from language, script, region and variant
|
||||
for (int i = 0; i < _lang.length(); i++) {
|
||||
h = 31*h + AsciiUtil.toLower(_lang.charAt(i));
|
||||
}
|
||||
for (int i = 0; i < _scrt.length(); i++) {
|
||||
h = 31*h + AsciiUtil.toLower(_scrt.charAt(i));
|
||||
}
|
||||
for (int i = 0; i < _regn.length(); i++) {
|
||||
h = 31*h + AsciiUtil.toLower(_regn.charAt(i));
|
||||
}
|
||||
for (int i = 0; i < _vart.length(); i++) {
|
||||
h = 31*h + _vart.charAt(i);
|
||||
}
|
||||
_hash = h;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public static Key normalize(Key key) {
|
||||
String lang = AsciiUtil.toLowerString(key._lang).intern();
|
||||
String scrt = AsciiUtil.toTitleString(key._scrt).intern();
|
||||
String regn = AsciiUtil.toUpperString(key._regn).intern();
|
||||
String vart = key._vart.intern(); // preserve upper/lower cases
|
||||
|
||||
return new Key(lang, scrt, regn, vart);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
|
||||
|
||||
public Cache() {
|
||||
}
|
||||
|
||||
protected Key normalizeKey(Key key) {
|
||||
return Key.normalize(key);
|
||||
}
|
||||
|
||||
protected BaseLocale createObject(Key key) {
|
||||
return new BaseLocale(key._lang, key._scrt, key._regn, key._vart);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
63
jdk/src/share/classes/sun/util/locale/Extension.java
Normal file
63
jdk/src/share/classes/sun/util/locale/Extension.java
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
|
||||
public class Extension {
|
||||
private char _key;
|
||||
protected String _value;
|
||||
|
||||
protected Extension(char key) {
|
||||
_key = key;
|
||||
}
|
||||
|
||||
Extension(char key, String value) {
|
||||
_key = key;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public char getKey() {
|
||||
return _key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return _key + LanguageTag.SEP + _value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getID();
|
||||
}
|
||||
}
|
705
jdk/src/share/classes/sun/util/locale/InternalLocaleBuilder.java
Normal file
705
jdk/src/share/classes/sun/util/locale/InternalLocaleBuilder.java
Normal file
@ -0,0 +1,705 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class InternalLocaleBuilder {
|
||||
|
||||
private String _language = "";
|
||||
private String _script = "";
|
||||
private String _region = "";
|
||||
private String _variant = "";
|
||||
|
||||
private static final CaseInsensitiveChar PRIVUSE_KEY = new CaseInsensitiveChar(LanguageTag.PRIVATEUSE.charAt(0));
|
||||
|
||||
private HashMap<CaseInsensitiveChar, String> _extensions;
|
||||
private HashSet<CaseInsensitiveString> _uattributes;
|
||||
private HashMap<CaseInsensitiveString, String> _ukeywords;
|
||||
|
||||
|
||||
public InternalLocaleBuilder() {
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
|
||||
if (language == null || language.length() == 0) {
|
||||
_language = "";
|
||||
} else {
|
||||
if (!LanguageTag.isLanguage(language)) {
|
||||
throw new LocaleSyntaxException("Ill-formed language: " + language, 0);
|
||||
}
|
||||
_language = language;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
|
||||
if (script == null || script.length() == 0) {
|
||||
_script = "";
|
||||
} else {
|
||||
if (!LanguageTag.isScript(script)) {
|
||||
throw new LocaleSyntaxException("Ill-formed script: " + script, 0);
|
||||
}
|
||||
_script = script;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
|
||||
if (region == null || region.length() == 0) {
|
||||
_region = "";
|
||||
} else {
|
||||
if (!LanguageTag.isRegion(region)) {
|
||||
throw new LocaleSyntaxException("Ill-formed region: " + region, 0);
|
||||
}
|
||||
_region = region;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
|
||||
if (variant == null || variant.length() == 0) {
|
||||
_variant = "";
|
||||
} else {
|
||||
// normalize separators to "_"
|
||||
String var = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
|
||||
int errIdx = checkVariants(var, BaseLocale.SEP);
|
||||
if (errIdx != -1) {
|
||||
throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
|
||||
}
|
||||
_variant = var;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder addUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
|
||||
if (!UnicodeLocaleExtension.isAttribute(attribute)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
|
||||
}
|
||||
// Use case insensitive string to prevent duplication
|
||||
if (_uattributes == null) {
|
||||
_uattributes = new HashSet<CaseInsensitiveString>(4);
|
||||
}
|
||||
_uattributes.add(new CaseInsensitiveString(attribute));
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder removeUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
|
||||
if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
|
||||
}
|
||||
if (_uattributes != null) {
|
||||
_uattributes.remove(new CaseInsensitiveString(attribute));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setUnicodeLocaleKeyword(String key, String type) throws LocaleSyntaxException {
|
||||
if (!UnicodeLocaleExtension.isKey(key)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale keyword key: " + key);
|
||||
}
|
||||
|
||||
CaseInsensitiveString cikey = new CaseInsensitiveString(key);
|
||||
if (type == null) {
|
||||
if (_ukeywords != null) {
|
||||
// null type is used for remove the key
|
||||
_ukeywords.remove(cikey);
|
||||
}
|
||||
} else {
|
||||
if (type.length() != 0) {
|
||||
// normalize separator to "-"
|
||||
String tp = type.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
|
||||
// validate
|
||||
StringTokenIterator itr = new StringTokenIterator(tp, LanguageTag.SEP);
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!UnicodeLocaleExtension.isTypeSubtag(s)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale keyword type: " + type, itr.currentStart());
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
}
|
||||
if (_ukeywords == null) {
|
||||
_ukeywords = new HashMap<CaseInsensitiveString, String>(4);
|
||||
}
|
||||
_ukeywords.put(cikey, type);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException {
|
||||
// validate key
|
||||
boolean isBcpPrivateuse = LanguageTag.isPrivateusePrefixChar(singleton);
|
||||
if (!isBcpPrivateuse && !LanguageTag.isExtensionSingletonChar(singleton)) {
|
||||
throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
|
||||
}
|
||||
|
||||
boolean remove = (value == null || value.length() == 0);
|
||||
CaseInsensitiveChar key = new CaseInsensitiveChar(singleton);
|
||||
|
||||
if (remove) {
|
||||
if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
|
||||
// clear entire Unicode locale extension
|
||||
if (_uattributes != null) {
|
||||
_uattributes.clear();
|
||||
}
|
||||
if (_ukeywords != null) {
|
||||
_ukeywords.clear();
|
||||
}
|
||||
} else {
|
||||
if (_extensions != null && _extensions.containsKey(key)) {
|
||||
_extensions.remove(key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// validate value
|
||||
String val = value.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
|
||||
StringTokenIterator itr = new StringTokenIterator(val, LanguageTag.SEP);
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
boolean validSubtag;
|
||||
if (isBcpPrivateuse) {
|
||||
validSubtag = LanguageTag.isPrivateuseSubtag(s);
|
||||
} else {
|
||||
validSubtag = LanguageTag.isExtensionSubtag(s);
|
||||
}
|
||||
if (!validSubtag) {
|
||||
throw new LocaleSyntaxException("Ill-formed extension value: " + s, itr.currentStart());
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
|
||||
setUnicodeLocaleExtension(val);
|
||||
} else {
|
||||
if (_extensions == null) {
|
||||
_extensions = new HashMap<CaseInsensitiveChar, String>(4);
|
||||
}
|
||||
_extensions.put(key, val);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set extension/private subtags in a single string representation
|
||||
*/
|
||||
public InternalLocaleBuilder setExtensions(String subtags) throws LocaleSyntaxException {
|
||||
if (subtags == null || subtags.length() == 0) {
|
||||
clearExtensions();
|
||||
return this;
|
||||
}
|
||||
subtags = subtags.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
|
||||
StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
|
||||
|
||||
List<String> extensions = null;
|
||||
String privateuse = null;
|
||||
|
||||
int parsed = 0;
|
||||
int start;
|
||||
|
||||
// Make a list of extension subtags
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (LanguageTag.isExtensionSingleton(s)) {
|
||||
start = itr.currentStart();
|
||||
String singleton = s;
|
||||
StringBuilder sb = new StringBuilder(singleton);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (LanguageTag.isExtensionSubtag(s)) {
|
||||
sb.append(LanguageTag.SEP).append(s);
|
||||
parsed = itr.currentEnd();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (parsed < start) {
|
||||
throw new LocaleSyntaxException("Incomplete extension '" + singleton + "'", start);
|
||||
}
|
||||
|
||||
if (extensions == null) {
|
||||
extensions = new ArrayList<String>(4);
|
||||
}
|
||||
extensions.add(sb.toString());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (LanguageTag.isPrivateusePrefix(s)) {
|
||||
start = itr.currentStart();
|
||||
StringBuilder sb = new StringBuilder(s);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (!LanguageTag.isPrivateuseSubtag(s)) {
|
||||
break;
|
||||
}
|
||||
sb.append(LanguageTag.SEP).append(s);
|
||||
parsed = itr.currentEnd();
|
||||
|
||||
itr.next();
|
||||
}
|
||||
if (parsed <= start) {
|
||||
throw new LocaleSyntaxException("Incomplete privateuse:" + subtags.substring(start), start);
|
||||
} else {
|
||||
privateuse = sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!itr.isDone()) {
|
||||
throw new LocaleSyntaxException("Ill-formed extension subtags:" + subtags.substring(itr.currentStart()), itr.currentStart());
|
||||
}
|
||||
|
||||
return setExtensions(extensions, privateuse);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a list of BCP47 extensions and private use subtags
|
||||
* BCP47 extensions are already validated and well-formed, but may contain duplicates
|
||||
*/
|
||||
private InternalLocaleBuilder setExtensions(List<String> bcpExtensions, String privateuse) {
|
||||
clearExtensions();
|
||||
|
||||
if (bcpExtensions != null && bcpExtensions.size() > 0) {
|
||||
HashSet<CaseInsensitiveChar> processedExntensions = new HashSet<CaseInsensitiveChar>(bcpExtensions.size());
|
||||
for (String bcpExt : bcpExtensions) {
|
||||
CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt.charAt(0));
|
||||
// ignore duplicates
|
||||
if (!processedExntensions.contains(key)) {
|
||||
// each extension string contains singleton, e.g. "a-abc-def"
|
||||
if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
|
||||
setUnicodeLocaleExtension(bcpExt.substring(2));
|
||||
} else {
|
||||
if (_extensions == null) {
|
||||
_extensions = new HashMap<CaseInsensitiveChar, String>(4);
|
||||
}
|
||||
_extensions.put(key, bcpExt.substring(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (privateuse != null && privateuse.length() > 0) {
|
||||
// privateuse string contains prefix, e.g. "x-abc-def"
|
||||
if (_extensions == null) {
|
||||
_extensions = new HashMap<CaseInsensitiveChar, String>(1);
|
||||
}
|
||||
_extensions.put(new CaseInsensitiveChar(privateuse.charAt(0)), privateuse.substring(2));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset Builder's internal state with the given language tag
|
||||
*/
|
||||
public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) {
|
||||
clear();
|
||||
if (langtag.getExtlangs().size() > 0) {
|
||||
_language = langtag.getExtlangs().get(0);
|
||||
} else {
|
||||
String language = langtag.getLanguage();
|
||||
if (!language.equals(LanguageTag.UNDETERMINED)) {
|
||||
_language = language;
|
||||
}
|
||||
}
|
||||
_script = langtag.getScript();
|
||||
_region = langtag.getRegion();
|
||||
|
||||
List<String> bcpVariants = langtag.getVariants();
|
||||
if (bcpVariants.size() > 0) {
|
||||
StringBuilder var = new StringBuilder(bcpVariants.get(0));
|
||||
for (int i = 1; i < bcpVariants.size(); i++) {
|
||||
var.append(BaseLocale.SEP).append(bcpVariants.get(i));
|
||||
}
|
||||
_variant = var.toString();
|
||||
}
|
||||
|
||||
setExtensions(langtag.getExtensions(), langtag.getPrivateuse());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions extensions) throws LocaleSyntaxException {
|
||||
String language = base.getLanguage();
|
||||
String script = base.getScript();
|
||||
String region = base.getRegion();
|
||||
String variant = base.getVariant();
|
||||
|
||||
// Special backward compatibility support
|
||||
|
||||
// Exception 1 - ja_JP_JP
|
||||
if (language.equals("ja") && region.equals("JP") && variant.equals("JP")) {
|
||||
// When locale ja_JP_JP is created, ca-japanese is always there.
|
||||
// The builder ignores the variant "JP"
|
||||
assert("japanese".equals(extensions.getUnicodeLocaleType("ca")));
|
||||
variant = "";
|
||||
}
|
||||
// Exception 2 - th_TH_TH
|
||||
else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) {
|
||||
// When locale th_TH_TH is created, nu-thai is always there.
|
||||
// The builder ignores the variant "TH"
|
||||
assert("thai".equals(extensions.getUnicodeLocaleType("nu")));
|
||||
variant = "";
|
||||
}
|
||||
// Exception 3 - no_NO_NY
|
||||
else if (language.equals("no") && region.equals("NO") && variant.equals("NY")) {
|
||||
// no_NO_NY is a valid locale and used by Java 6 or older versions.
|
||||
// The build ignores the variant "NY" and change the language to "nn".
|
||||
language = "nn";
|
||||
variant = "";
|
||||
}
|
||||
|
||||
// Validate base locale fields before updating internal state.
|
||||
// LocaleExtensions always store validated/canonicalized values,
|
||||
// so no checks are necessary.
|
||||
if (language.length() > 0 && !LanguageTag.isLanguage(language)) {
|
||||
throw new LocaleSyntaxException("Ill-formed language: " + language);
|
||||
}
|
||||
|
||||
if (script.length() > 0 && !LanguageTag.isScript(script)) {
|
||||
throw new LocaleSyntaxException("Ill-formed script: " + script);
|
||||
}
|
||||
|
||||
if (region.length() > 0 && !LanguageTag.isRegion(region)) {
|
||||
throw new LocaleSyntaxException("Ill-formed region: " + region);
|
||||
}
|
||||
|
||||
if (variant.length() > 0) {
|
||||
int errIdx = checkVariants(variant, BaseLocale.SEP);
|
||||
if (errIdx != -1) {
|
||||
throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
|
||||
}
|
||||
}
|
||||
|
||||
// The input locale is validated at this point.
|
||||
// Now, updating builder's internal fields.
|
||||
_language = language;
|
||||
_script = script;
|
||||
_region = region;
|
||||
_variant = variant;
|
||||
clearExtensions();
|
||||
|
||||
Set<Character> extKeys = (extensions == null) ? null : extensions.getKeys();
|
||||
if (extKeys != null) {
|
||||
// map extensions back to builder's internal format
|
||||
for (Character key : extKeys) {
|
||||
Extension e = extensions.getExtension(key);
|
||||
if (e instanceof UnicodeLocaleExtension) {
|
||||
UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e;
|
||||
for (String uatr : ue.getUnicodeLocaleAttributes()) {
|
||||
if (_uattributes == null) {
|
||||
_uattributes = new HashSet<CaseInsensitiveString>(4);
|
||||
}
|
||||
_uattributes.add(new CaseInsensitiveString(uatr));
|
||||
}
|
||||
for (String ukey : ue.getUnicodeLocaleKeys()) {
|
||||
if (_ukeywords == null) {
|
||||
_ukeywords = new HashMap<CaseInsensitiveString, String>(4);
|
||||
}
|
||||
_ukeywords.put(new CaseInsensitiveString(ukey), ue.getUnicodeLocaleType(ukey));
|
||||
}
|
||||
} else {
|
||||
if (_extensions == null) {
|
||||
_extensions = new HashMap<CaseInsensitiveChar, String>(4);
|
||||
}
|
||||
_extensions.put(new CaseInsensitiveChar(key.charValue()), e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder clear() {
|
||||
_language = "";
|
||||
_script = "";
|
||||
_region = "";
|
||||
_variant = "";
|
||||
clearExtensions();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder clearExtensions() {
|
||||
if (_extensions != null) {
|
||||
_extensions.clear();
|
||||
}
|
||||
if (_uattributes != null) {
|
||||
_uattributes.clear();
|
||||
}
|
||||
if (_ukeywords != null) {
|
||||
_ukeywords.clear();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseLocale getBaseLocale() {
|
||||
String language = _language;
|
||||
String script = _script;
|
||||
String region = _region;
|
||||
String variant = _variant;
|
||||
|
||||
// Special private use subtag sequence identified by "lvariant" will be
|
||||
// interpreted as Java variant.
|
||||
if (_extensions != null) {
|
||||
String privuse = _extensions.get(PRIVUSE_KEY);
|
||||
if (privuse != null) {
|
||||
StringTokenIterator itr = new StringTokenIterator(privuse, LanguageTag.SEP);
|
||||
boolean sawPrefix = false;
|
||||
int privVarStart = -1;
|
||||
while (!itr.isDone()) {
|
||||
if (sawPrefix) {
|
||||
privVarStart = itr.currentStart();
|
||||
break;
|
||||
}
|
||||
if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
|
||||
sawPrefix = true;
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
if (privVarStart != -1) {
|
||||
StringBuilder sb = new StringBuilder(variant);
|
||||
if (sb.length() != 0) {
|
||||
sb.append(BaseLocale.SEP);
|
||||
}
|
||||
sb.append(privuse.substring(privVarStart).replaceAll(LanguageTag.SEP, BaseLocale.SEP));
|
||||
variant = sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BaseLocale.getInstance(language, script, region, variant);
|
||||
}
|
||||
|
||||
public LocaleExtensions getLocaleExtensions() {
|
||||
if ((_extensions == null || _extensions.size() == 0)
|
||||
&& (_uattributes == null || _uattributes.size() == 0)
|
||||
&& (_ukeywords == null || _ukeywords.size() == 0)) {
|
||||
return LocaleExtensions.EMPTY_EXTENSIONS;
|
||||
}
|
||||
|
||||
return new LocaleExtensions(_extensions, _uattributes, _ukeywords);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove special private use subtag sequence identified by "lvariant"
|
||||
* and return the rest. Only used by LocaleExtensions
|
||||
*/
|
||||
static String removePrivateuseVariant(String privuseVal) {
|
||||
StringTokenIterator itr = new StringTokenIterator(privuseVal, LanguageTag.SEP);
|
||||
|
||||
// Note: privateuse value "abc-lvariant" is unchanged
|
||||
// because no subtags after "lvariant".
|
||||
|
||||
int prefixStart = -1;
|
||||
boolean sawPrivuseVar = false;
|
||||
while (!itr.isDone()) {
|
||||
if (prefixStart != -1) {
|
||||
// Note: privateuse value "abc-lvariant" is unchanged
|
||||
// because no subtags after "lvariant".
|
||||
sawPrivuseVar = true;
|
||||
break;
|
||||
}
|
||||
if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
|
||||
prefixStart = itr.currentStart();
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
if (!sawPrivuseVar) {
|
||||
return privuseVal;
|
||||
}
|
||||
|
||||
assert(prefixStart == 0 || prefixStart > 1);
|
||||
return (prefixStart == 0) ? null : privuseVal.substring(0, prefixStart -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the given variant subtags separated by the given
|
||||
* separator(s) are valid
|
||||
*/
|
||||
private int checkVariants(String variants, String sep) {
|
||||
StringTokenIterator itr = new StringTokenIterator(variants, sep);
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!LanguageTag.isVariant(s)) {
|
||||
return itr.currentStart();
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private methods parsing Unicode Locale Extension subtags.
|
||||
* Duplicated attributes/keywords will be ignored.
|
||||
* The input must be a valid extension subtags (excluding singleton).
|
||||
*/
|
||||
private void setUnicodeLocaleExtension(String subtags) {
|
||||
// wipe out existing attributes/keywords
|
||||
if (_uattributes != null) {
|
||||
_uattributes.clear();
|
||||
}
|
||||
if (_ukeywords != null) {
|
||||
_ukeywords.clear();
|
||||
}
|
||||
|
||||
StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
|
||||
|
||||
// parse attributes
|
||||
while (!itr.isDone()) {
|
||||
if (!UnicodeLocaleExtension.isAttribute(itr.current())) {
|
||||
break;
|
||||
}
|
||||
if (_uattributes == null) {
|
||||
_uattributes = new HashSet<CaseInsensitiveString>(4);
|
||||
}
|
||||
_uattributes.add(new CaseInsensitiveString(itr.current()));
|
||||
itr.next();
|
||||
}
|
||||
|
||||
// parse keywords
|
||||
CaseInsensitiveString key = null;
|
||||
String type;
|
||||
int typeStart = -1;
|
||||
int typeEnd = -1;
|
||||
while (!itr.isDone()) {
|
||||
if (key != null) {
|
||||
if (UnicodeLocaleExtension.isKey(itr.current())) {
|
||||
// next keyword - emit previous one
|
||||
assert(typeStart == -1 || typeEnd != -1);
|
||||
type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
|
||||
if (_ukeywords == null) {
|
||||
_ukeywords = new HashMap<CaseInsensitiveString, String>(4);
|
||||
}
|
||||
_ukeywords.put(key, type);
|
||||
|
||||
// reset keyword info
|
||||
CaseInsensitiveString tmpKey = new CaseInsensitiveString(itr.current());
|
||||
key = _ukeywords.containsKey(tmpKey) ? null : tmpKey;
|
||||
typeStart = typeEnd = -1;
|
||||
} else {
|
||||
if (typeStart == -1) {
|
||||
typeStart = itr.currentStart();
|
||||
}
|
||||
typeEnd = itr.currentEnd();
|
||||
}
|
||||
} else if (UnicodeLocaleExtension.isKey(itr.current())) {
|
||||
// 1. first keyword or
|
||||
// 2. next keyword, but previous one was duplicate
|
||||
key = new CaseInsensitiveString(itr.current());
|
||||
if (_ukeywords != null && _ukeywords.containsKey(key)) {
|
||||
// duplicate
|
||||
key = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!itr.hasNext()) {
|
||||
if (key != null) {
|
||||
// last keyword
|
||||
assert(typeStart == -1 || typeEnd != -1);
|
||||
type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
|
||||
if (_ukeywords == null) {
|
||||
_ukeywords = new HashMap<CaseInsensitiveString, String>(4);
|
||||
}
|
||||
_ukeywords.put(key, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
itr.next();
|
||||
}
|
||||
}
|
||||
|
||||
static class CaseInsensitiveString {
|
||||
private String _s;
|
||||
|
||||
CaseInsensitiveString(String s) {
|
||||
_s = s;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return _s;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return AsciiUtil.toLowerString(_s).hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof CaseInsensitiveString)) {
|
||||
return false;
|
||||
}
|
||||
return AsciiUtil.caseIgnoreMatch(_s, ((CaseInsensitiveString)obj).value());
|
||||
}
|
||||
}
|
||||
|
||||
static class CaseInsensitiveChar {
|
||||
private char _c;
|
||||
|
||||
CaseInsensitiveChar(char c) {
|
||||
_c = c;
|
||||
}
|
||||
|
||||
public char value() {
|
||||
return _c;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return AsciiUtil.toLower(_c);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof CaseInsensitiveChar)) {
|
||||
return false;
|
||||
}
|
||||
return _c == AsciiUtil.toLower(((CaseInsensitiveChar)obj).value());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
726
jdk/src/share/classes/sun/util/locale/LanguageTag.java
Normal file
726
jdk/src/share/classes/sun/util/locale/LanguageTag.java
Normal file
@ -0,0 +1,726 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class LanguageTag {
|
||||
//
|
||||
// static fields
|
||||
//
|
||||
public static final String SEP = "-";
|
||||
public static final String PRIVATEUSE = "x";
|
||||
public static String UNDETERMINED = "und";
|
||||
public static final String PRIVUSE_VARIANT_PREFIX = "lvariant";
|
||||
|
||||
//
|
||||
// Language subtag fields
|
||||
//
|
||||
private String _language = ""; // language subtag
|
||||
private String _script = ""; // script subtag
|
||||
private String _region = ""; // region subtag
|
||||
private String _privateuse = ""; // privateuse
|
||||
|
||||
private List<String> _extlangs = Collections.emptyList(); // extlang subtags
|
||||
private List<String> _variants = Collections.emptyList(); // variant subtags
|
||||
private List<String> _extensions = Collections.emptyList(); // extensions
|
||||
|
||||
// Map contains grandfathered tags and its preferred mappings from
|
||||
// http://www.ietf.org/rfc/rfc5646.txt
|
||||
private static final Map<AsciiUtil.CaseInsensitiveKey, String[]> GRANDFATHERED =
|
||||
new HashMap<AsciiUtil.CaseInsensitiveKey, String[]>();
|
||||
|
||||
static {
|
||||
// grandfathered = irregular ; non-redundant tags registered
|
||||
// / regular ; during the RFC 3066 era
|
||||
//
|
||||
// irregular = "en-GB-oed" ; irregular tags do not match
|
||||
// / "i-ami" ; the 'langtag' production and
|
||||
// / "i-bnn" ; would not otherwise be
|
||||
// / "i-default" ; considered 'well-formed'
|
||||
// / "i-enochian" ; These tags are all valid,
|
||||
// / "i-hak" ; but most are deprecated
|
||||
// / "i-klingon" ; in favor of more modern
|
||||
// / "i-lux" ; subtags or subtag
|
||||
// / "i-mingo" ; combination
|
||||
// / "i-navajo"
|
||||
// / "i-pwn"
|
||||
// / "i-tao"
|
||||
// / "i-tay"
|
||||
// / "i-tsu"
|
||||
// / "sgn-BE-FR"
|
||||
// / "sgn-BE-NL"
|
||||
// / "sgn-CH-DE"
|
||||
//
|
||||
// regular = "art-lojban" ; these tags match the 'langtag'
|
||||
// / "cel-gaulish" ; production, but their subtags
|
||||
// / "no-bok" ; are not extended language
|
||||
// / "no-nyn" ; or variant subtags: their meaning
|
||||
// / "zh-guoyu" ; is defined by their registration
|
||||
// / "zh-hakka" ; and all of these are deprecated
|
||||
// / "zh-min" ; in favor of a more modern
|
||||
// / "zh-min-nan" ; subtag or sequence of subtags
|
||||
// / "zh-xiang"
|
||||
|
||||
final String[][] entries = {
|
||||
//{"tag", "preferred"},
|
||||
{"art-lojban", "jbo"},
|
||||
{"cel-gaulish", "xtg-x-cel-gaulish"}, // fallback
|
||||
{"en-GB-oed", "en-GB-x-oed"}, // fallback
|
||||
{"i-ami", "ami"},
|
||||
{"i-bnn", "bnn"},
|
||||
{"i-default", "en-x-i-default"}, // fallback
|
||||
{"i-enochian", "und-x-i-enochian"}, // fallback
|
||||
{"i-hak", "hak"},
|
||||
{"i-klingon", "tlh"},
|
||||
{"i-lux", "lb"},
|
||||
{"i-mingo", "see-x-i-mingo"}, // fallback
|
||||
{"i-navajo", "nv"},
|
||||
{"i-pwn", "pwn"},
|
||||
{"i-tao", "tao"},
|
||||
{"i-tay", "tay"},
|
||||
{"i-tsu", "tsu"},
|
||||
{"no-bok", "nb"},
|
||||
{"no-nyn", "nn"},
|
||||
{"sgn-BE-FR", "sfb"},
|
||||
{"sgn-BE-NL", "vgt"},
|
||||
{"sgn-CH-DE", "sgg"},
|
||||
{"zh-guoyu", "cmn"},
|
||||
{"zh-hakka", "hak"},
|
||||
{"zh-min", "nan-x-zh-min"}, // fallback
|
||||
{"zh-min-nan", "nan"},
|
||||
{"zh-xiang", "hsn"},
|
||||
};
|
||||
for (String[] e : entries) {
|
||||
GRANDFATHERED.put(new AsciiUtil.CaseInsensitiveKey(e[0]), e);
|
||||
}
|
||||
}
|
||||
|
||||
private LanguageTag() {
|
||||
}
|
||||
|
||||
/*
|
||||
* BNF in RFC5464
|
||||
*
|
||||
* Language-Tag = langtag ; normal language tags
|
||||
* / privateuse ; private use tag
|
||||
* / grandfathered ; grandfathered tags
|
||||
*
|
||||
*
|
||||
* langtag = language
|
||||
* ["-" script]
|
||||
* ["-" region]
|
||||
* *("-" variant)
|
||||
* *("-" extension)
|
||||
* ["-" privateuse]
|
||||
*
|
||||
* language = 2*3ALPHA ; shortest ISO 639 code
|
||||
* ["-" extlang] ; sometimes followed by
|
||||
* ; extended language subtags
|
||||
* / 4ALPHA ; or reserved for future use
|
||||
* / 5*8ALPHA ; or registered language subtag
|
||||
*
|
||||
* extlang = 3ALPHA ; selected ISO 639 codes
|
||||
* *2("-" 3ALPHA) ; permanently reserved
|
||||
*
|
||||
* script = 4ALPHA ; ISO 15924 code
|
||||
*
|
||||
* region = 2ALPHA ; ISO 3166-1 code
|
||||
* / 3DIGIT ; UN M.49 code
|
||||
*
|
||||
* variant = 5*8alphanum ; registered variants
|
||||
* / (DIGIT 3alphanum)
|
||||
*
|
||||
* extension = singleton 1*("-" (2*8alphanum))
|
||||
*
|
||||
* ; Single alphanumerics
|
||||
* ; "x" reserved for private use
|
||||
* singleton = DIGIT ; 0 - 9
|
||||
* / %x41-57 ; A - W
|
||||
* / %x59-5A ; Y - Z
|
||||
* / %x61-77 ; a - w
|
||||
* / %x79-7A ; y - z
|
||||
*
|
||||
* privateuse = "x" 1*("-" (1*8alphanum))
|
||||
*
|
||||
*/
|
||||
public static LanguageTag parse(String languageTag, ParseStatus sts) {
|
||||
if (sts == null) {
|
||||
sts = new ParseStatus();
|
||||
} else {
|
||||
sts.reset();
|
||||
}
|
||||
|
||||
StringTokenIterator itr;
|
||||
|
||||
// Check if the tag is grandfathered
|
||||
String[] gfmap = GRANDFATHERED.get(new AsciiUtil.CaseInsensitiveKey(languageTag));
|
||||
if (gfmap != null) {
|
||||
// use preferred mapping
|
||||
itr = new StringTokenIterator(gfmap[1], SEP);
|
||||
} else {
|
||||
itr = new StringTokenIterator(languageTag, SEP);
|
||||
}
|
||||
|
||||
LanguageTag tag = new LanguageTag();
|
||||
|
||||
// langtag must start with either language or privateuse
|
||||
if (tag.parseLanguage(itr, sts)) {
|
||||
tag.parseExtlangs(itr, sts);
|
||||
tag.parseScript(itr, sts);
|
||||
tag.parseRegion(itr, sts);
|
||||
tag.parseVariants(itr, sts);
|
||||
tag.parseExtensions(itr, sts);
|
||||
}
|
||||
tag.parsePrivateuse(itr, sts);
|
||||
|
||||
if (!itr.isDone() && !sts.isError()) {
|
||||
String s = itr.current();
|
||||
sts._errorIndex = itr.currentStart();
|
||||
if (s.length() == 0) {
|
||||
sts._errorMsg = "Empty subtag";
|
||||
} else {
|
||||
sts._errorMsg = "Invalid subtag: " + s;
|
||||
}
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
//
|
||||
// Language subtag parsers
|
||||
//
|
||||
|
||||
private boolean parseLanguage(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isLanguage(s)) {
|
||||
found = true;
|
||||
_language = s;
|
||||
sts._parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!isExtlang(s)) {
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
if (_extlangs.isEmpty()) {
|
||||
_extlangs = new ArrayList<String>(3);
|
||||
}
|
||||
_extlangs.add(s);
|
||||
sts._parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
|
||||
if (_extlangs.size() == 3) {
|
||||
// Maximum 3 extlangs
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseScript(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isScript(s)) {
|
||||
found = true;
|
||||
_script = s;
|
||||
sts._parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseRegion(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isRegion(s)) {
|
||||
found = true;
|
||||
_region = s;
|
||||
sts._parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseVariants(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!isVariant(s)) {
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
if (_variants.isEmpty()) {
|
||||
_variants = new ArrayList<String>(3);
|
||||
}
|
||||
_variants.add(s);
|
||||
sts._parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (isExtensionSingleton(s)) {
|
||||
int start = itr.currentStart();
|
||||
String singleton = s;
|
||||
StringBuilder sb = new StringBuilder(singleton);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (isExtensionSubtag(s)) {
|
||||
sb.append(SEP).append(s);
|
||||
sts._parseLength = itr.currentEnd();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (sts._parseLength <= start) {
|
||||
sts._errorIndex = start;
|
||||
sts._errorMsg = "Incomplete extension '" + singleton + "'";
|
||||
break;
|
||||
}
|
||||
|
||||
if (_extensions.size() == 0) {
|
||||
_extensions = new ArrayList<String>(4);
|
||||
}
|
||||
_extensions.add(sb.toString());
|
||||
found = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isPrivateusePrefix(s)) {
|
||||
int start = itr.currentStart();
|
||||
StringBuilder sb = new StringBuilder(s);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (!isPrivateuseSubtag(s)) {
|
||||
break;
|
||||
}
|
||||
sb.append(SEP).append(s);
|
||||
sts._parseLength = itr.currentEnd();
|
||||
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (sts._parseLength <= start) {
|
||||
// need at least 1 private subtag
|
||||
sts._errorIndex = start;
|
||||
sts._errorMsg = "Incomplete privateuse";
|
||||
} else {
|
||||
_privateuse = sb.toString();
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
public static LanguageTag parseLocale(BaseLocale baseLocale, LocaleExtensions localeExtensions) {
|
||||
LanguageTag tag = new LanguageTag();
|
||||
|
||||
String language = baseLocale.getLanguage();
|
||||
String script = baseLocale.getScript();
|
||||
String region = baseLocale.getRegion();
|
||||
String variant = baseLocale.getVariant();
|
||||
|
||||
String privuseVar = null; // store ill-formed variant subtags
|
||||
|
||||
if (language.length() == 0 || !isLanguage(language)) {
|
||||
tag._language = UNDETERMINED;
|
||||
} else {
|
||||
// Convert a deprecated language code used by Java to
|
||||
// a new code
|
||||
if (language.equals("iw")) {
|
||||
language = "he";
|
||||
} else if (language.equals("ji")) {
|
||||
language = "yi";
|
||||
} else if (language.equals("in")) {
|
||||
language = "id";
|
||||
}
|
||||
tag._language = language;
|
||||
}
|
||||
|
||||
if (script.length() > 0 && isScript(script)) {
|
||||
tag._script = canonicalizeScript(script);
|
||||
}
|
||||
|
||||
if (region.length() > 0 && isRegion(region)) {
|
||||
tag._region = canonicalizeRegion(region);
|
||||
}
|
||||
|
||||
// Special handling for no_NO_NY - use nn_NO for language tag
|
||||
if (tag._language.equals("no") && tag._region.equals("NO") && variant.equals("NY")) {
|
||||
tag._language = "nn";
|
||||
variant = "";
|
||||
}
|
||||
|
||||
if (variant.length() > 0) {
|
||||
List<String> variants = null;
|
||||
StringTokenIterator varitr = new StringTokenIterator(variant, BaseLocale.SEP);
|
||||
while (!varitr.isDone()) {
|
||||
String var = varitr.current();
|
||||
if (!isVariant(var)) {
|
||||
break;
|
||||
}
|
||||
if (variants == null) {
|
||||
variants = new ArrayList<String>();
|
||||
}
|
||||
variants.add(var); // Do not canonicalize!
|
||||
varitr.next();
|
||||
}
|
||||
if (variants != null) {
|
||||
tag._variants = variants;
|
||||
}
|
||||
if (!varitr.isDone()) {
|
||||
// ill-formed variant subtags
|
||||
StringBuilder buf = new StringBuilder();
|
||||
while (!varitr.isDone()) {
|
||||
String prvv = varitr.current();
|
||||
if (!isPrivateuseSubtag(prvv)) {
|
||||
// cannot use private use subtag - truncated
|
||||
break;
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
buf.append(SEP);
|
||||
}
|
||||
buf.append(prvv);
|
||||
varitr.next();
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
privuseVar = buf.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<String> extensions = null;
|
||||
String privateuse = null;
|
||||
|
||||
Set<Character> locextKeys = localeExtensions.getKeys();
|
||||
for (Character locextKey : locextKeys) {
|
||||
Extension ext = localeExtensions.getExtension(locextKey);
|
||||
if (isPrivateusePrefixChar(locextKey.charValue())) {
|
||||
privateuse = ext.getValue();
|
||||
} else {
|
||||
if (extensions == null) {
|
||||
extensions = new ArrayList<String>();
|
||||
}
|
||||
extensions.add(locextKey.toString() + SEP + ext.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (extensions != null) {
|
||||
tag._extensions = extensions;
|
||||
}
|
||||
|
||||
// append ill-formed variant subtags to private use
|
||||
if (privuseVar != null) {
|
||||
if (privateuse == null) {
|
||||
privateuse = PRIVUSE_VARIANT_PREFIX + SEP + privuseVar;
|
||||
} else {
|
||||
privateuse = privateuse + SEP + PRIVUSE_VARIANT_PREFIX + SEP + privuseVar.replace(BaseLocale.SEP, SEP);
|
||||
}
|
||||
}
|
||||
|
||||
if (privateuse != null) {
|
||||
tag._privateuse = privateuse;
|
||||
} else if (tag._language.length() == 0) {
|
||||
// use "und" if neither language nor privateuse is available
|
||||
tag._language = UNDETERMINED;
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
//
|
||||
// Getter methods for language subtag fields
|
||||
//
|
||||
|
||||
public String getLanguage() {
|
||||
return _language;
|
||||
}
|
||||
|
||||
public List<String> getExtlangs() {
|
||||
return Collections.unmodifiableList(_extlangs);
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return _script;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return _region;
|
||||
}
|
||||
|
||||
public List<String> getVariants() {
|
||||
return Collections.unmodifiableList(_variants);
|
||||
}
|
||||
|
||||
public List<String> getExtensions() {
|
||||
return Collections.unmodifiableList(_extensions);
|
||||
}
|
||||
|
||||
public String getPrivateuse() {
|
||||
return _privateuse;
|
||||
}
|
||||
|
||||
//
|
||||
// Language subtag syntax checking methods
|
||||
//
|
||||
|
||||
public static boolean isLanguage(String s) {
|
||||
// language = 2*3ALPHA ; shortest ISO 639 code
|
||||
// ["-" extlang] ; sometimes followed by
|
||||
// ; extended language subtags
|
||||
// / 4ALPHA ; or reserved for future use
|
||||
// / 5*8ALPHA ; or registered language subtag
|
||||
return (s.length() >= 2) && (s.length() <= 8) && AsciiUtil.isAlphaString(s);
|
||||
}
|
||||
|
||||
public static boolean isExtlang(String s) {
|
||||
// extlang = 3ALPHA ; selected ISO 639 codes
|
||||
// *2("-" 3ALPHA) ; permanently reserved
|
||||
return (s.length() == 3) && AsciiUtil.isAlphaString(s);
|
||||
}
|
||||
|
||||
public static boolean isScript(String s) {
|
||||
// script = 4ALPHA ; ISO 15924 code
|
||||
return (s.length() == 4) && AsciiUtil.isAlphaString(s);
|
||||
}
|
||||
|
||||
public static boolean isRegion(String s) {
|
||||
// region = 2ALPHA ; ISO 3166-1 code
|
||||
// / 3DIGIT ; UN M.49 code
|
||||
return ((s.length() == 2) && AsciiUtil.isAlphaString(s))
|
||||
|| ((s.length() == 3) && AsciiUtil.isNumericString(s));
|
||||
}
|
||||
|
||||
public static boolean isVariant(String s) {
|
||||
// variant = 5*8alphanum ; registered variants
|
||||
// / (DIGIT 3alphanum)
|
||||
int len = s.length();
|
||||
if (len >= 5 && len <= 8) {
|
||||
return AsciiUtil.isAlphaNumericString(s);
|
||||
}
|
||||
if (len == 4) {
|
||||
return AsciiUtil.isNumeric(s.charAt(0))
|
||||
&& AsciiUtil.isAlphaNumeric(s.charAt(1))
|
||||
&& AsciiUtil.isAlphaNumeric(s.charAt(2))
|
||||
&& AsciiUtil.isAlphaNumeric(s.charAt(3));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isExtensionSingleton(String s) {
|
||||
// singleton = DIGIT ; 0 - 9
|
||||
// / %x41-57 ; A - W
|
||||
// / %x59-5A ; Y - Z
|
||||
// / %x61-77 ; a - w
|
||||
// / %x79-7A ; y - z
|
||||
|
||||
return (s.length() == 1)
|
||||
&& AsciiUtil.isAlphaString(s)
|
||||
&& !AsciiUtil.caseIgnoreMatch(PRIVATEUSE, s);
|
||||
}
|
||||
|
||||
public static boolean isExtensionSingletonChar(char c) {
|
||||
return isExtensionSingleton(String.valueOf(c));
|
||||
}
|
||||
|
||||
public static boolean isExtensionSubtag(String s) {
|
||||
// extension = singleton 1*("-" (2*8alphanum))
|
||||
return (s.length() >= 2) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
public static boolean isPrivateusePrefix(String s) {
|
||||
// privateuse = "x" 1*("-" (1*8alphanum))
|
||||
return (s.length() == 1)
|
||||
&& AsciiUtil.caseIgnoreMatch(PRIVATEUSE, s);
|
||||
}
|
||||
|
||||
public static boolean isPrivateusePrefixChar(char c) {
|
||||
return (AsciiUtil.caseIgnoreMatch(PRIVATEUSE, String.valueOf(c)));
|
||||
}
|
||||
|
||||
public static boolean isPrivateuseSubtag(String s) {
|
||||
// privateuse = "x" 1*("-" (1*8alphanum))
|
||||
return (s.length() >= 1) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
//
|
||||
// Language subtag canonicalization methods
|
||||
//
|
||||
|
||||
public static String canonicalizeLanguage(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtlang(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeScript(String s) {
|
||||
return AsciiUtil.toTitleString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeRegion(String s) {
|
||||
return AsciiUtil.toUpperString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeVariant(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtension(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtensionSingleton(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtensionSubtag(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizePrivateuse(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizePrivateuseSubtag(String s) {
|
||||
return AsciiUtil.toLowerString(s);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (_language.length() > 0) {
|
||||
sb.append(_language);
|
||||
|
||||
for (String extlang : _extlangs) {
|
||||
sb.append(SEP).append(extlang);
|
||||
}
|
||||
|
||||
if (_script.length() > 0) {
|
||||
sb.append(SEP).append(_script);
|
||||
}
|
||||
|
||||
if (_region.length() > 0) {
|
||||
sb.append(SEP).append(_region);
|
||||
}
|
||||
|
||||
for (String variant : _extlangs) {
|
||||
sb.append(SEP).append(variant);
|
||||
}
|
||||
|
||||
for (String extension : _extensions) {
|
||||
sb.append(SEP).append(extension);
|
||||
}
|
||||
}
|
||||
if (_privateuse.length() > 0) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(SEP);
|
||||
}
|
||||
sb.append(_privateuse);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
246
jdk/src/share/classes/sun/util/locale/LocaleExtensions.java
Normal file
246
jdk/src/share/classes/sun/util/locale/LocaleExtensions.java
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveChar;
|
||||
import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveString;
|
||||
|
||||
|
||||
public class LocaleExtensions {
|
||||
|
||||
private SortedMap<Character, Extension> _map;
|
||||
private String _id;
|
||||
|
||||
private static final SortedMap<Character, Extension> EMPTY_MAP =
|
||||
Collections.unmodifiableSortedMap(new TreeMap<Character, Extension>());
|
||||
|
||||
public static final LocaleExtensions EMPTY_EXTENSIONS;
|
||||
public static final LocaleExtensions CALENDAR_JAPANESE;
|
||||
public static final LocaleExtensions NUMBER_THAI;
|
||||
|
||||
static {
|
||||
EMPTY_EXTENSIONS = new LocaleExtensions();
|
||||
EMPTY_EXTENSIONS._id = "";
|
||||
EMPTY_EXTENSIONS._map = EMPTY_MAP;
|
||||
|
||||
CALENDAR_JAPANESE = new LocaleExtensions();
|
||||
CALENDAR_JAPANESE._id = "u-ca-japanese";
|
||||
CALENDAR_JAPANESE._map = new TreeMap<Character, Extension>();
|
||||
CALENDAR_JAPANESE._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.CA_JAPANESE);
|
||||
|
||||
NUMBER_THAI = new LocaleExtensions();
|
||||
NUMBER_THAI._id = "u-nu-thai";
|
||||
NUMBER_THAI._map = new TreeMap<Character, Extension>();
|
||||
NUMBER_THAI._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.NU_THAI);
|
||||
}
|
||||
|
||||
private LocaleExtensions() {
|
||||
}
|
||||
|
||||
/*
|
||||
* Package local constructor, only used by InternalLocaleBuilder.
|
||||
*/
|
||||
LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
|
||||
Set<CaseInsensitiveString> uattributes, Map<CaseInsensitiveString, String> ukeywords) {
|
||||
boolean hasExtension = (extensions != null && extensions.size() > 0);
|
||||
boolean hasUAttributes = (uattributes != null && uattributes.size() > 0);
|
||||
boolean hasUKeywords = (ukeywords != null && ukeywords.size() > 0);
|
||||
|
||||
if (!hasExtension && !hasUAttributes && !hasUKeywords) {
|
||||
_map = EMPTY_MAP;
|
||||
_id = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// Build extension map
|
||||
_map = new TreeMap<Character, Extension>();
|
||||
if (hasExtension) {
|
||||
for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
|
||||
char key = AsciiUtil.toLower(ext.getKey().value());
|
||||
String value = ext.getValue();
|
||||
|
||||
if (LanguageTag.isPrivateusePrefixChar(key)) {
|
||||
// we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
|
||||
value = InternalLocaleBuilder.removePrivateuseVariant(value);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Extension e = new Extension(key, AsciiUtil.toLowerString(value));
|
||||
_map.put(Character.valueOf(key), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUAttributes || hasUKeywords) {
|
||||
TreeSet<String> uaset = null;
|
||||
TreeMap<String, String> ukmap = null;
|
||||
|
||||
if (hasUAttributes) {
|
||||
uaset = new TreeSet<String>();
|
||||
for (CaseInsensitiveString cis : uattributes) {
|
||||
uaset.add(AsciiUtil.toLowerString(cis.value()));
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUKeywords) {
|
||||
ukmap = new TreeMap<String, String>();
|
||||
for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
|
||||
String key = AsciiUtil.toLowerString(kwd.getKey().value());
|
||||
String type = AsciiUtil.toLowerString(kwd.getValue());
|
||||
ukmap.put(key, type);
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
|
||||
_map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), ule);
|
||||
}
|
||||
|
||||
if (_map.size() == 0) {
|
||||
// this could happen when only privuateuse with special variant
|
||||
_map = EMPTY_MAP;
|
||||
_id = "";
|
||||
} else {
|
||||
_id = toID(_map);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Character> getKeys() {
|
||||
return Collections.unmodifiableSet(_map.keySet());
|
||||
}
|
||||
|
||||
public Extension getExtension(Character key) {
|
||||
return _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
|
||||
}
|
||||
|
||||
public String getExtensionValue(Character key) {
|
||||
Extension ext = _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
|
||||
if (ext == null) {
|
||||
return null;
|
||||
}
|
||||
return ext.getValue();
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleAttributes() {
|
||||
Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
|
||||
if (ext == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
assert (ext instanceof UnicodeLocaleExtension);
|
||||
return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleKeys() {
|
||||
Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
|
||||
if (ext == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
assert (ext instanceof UnicodeLocaleExtension);
|
||||
return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
|
||||
}
|
||||
|
||||
public String getUnicodeLocaleType(String unicodeLocaleKey) {
|
||||
Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
|
||||
if (ext == null) {
|
||||
return null;
|
||||
}
|
||||
assert (ext instanceof UnicodeLocaleExtension);
|
||||
return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(AsciiUtil.toLowerString(unicodeLocaleKey));
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return _map.isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isValidKey(char c) {
|
||||
return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
|
||||
}
|
||||
|
||||
public static boolean isValidUnicodeLocaleKey(String ukey) {
|
||||
return UnicodeLocaleExtension.isKey(ukey);
|
||||
}
|
||||
|
||||
private static String toID(SortedMap<Character, Extension> map) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
Extension privuse = null;
|
||||
for (Entry<Character, Extension> entry : map.entrySet()) {
|
||||
char singleton = entry.getKey().charValue();
|
||||
Extension extension = entry.getValue();
|
||||
if (LanguageTag.isPrivateusePrefixChar(singleton)) {
|
||||
privuse = extension;
|
||||
} else {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(LanguageTag.SEP);
|
||||
}
|
||||
buf.append(extension);
|
||||
}
|
||||
}
|
||||
if (privuse != null) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(LanguageTag.SEP);
|
||||
}
|
||||
buf.append(privuse);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return _id.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof LocaleExtensions)) {
|
||||
return false;
|
||||
}
|
||||
return this._id.equals(((LocaleExtensions)other)._id);
|
||||
}
|
||||
}
|
108
jdk/src/share/classes/sun/util/locale/LocaleObjectCache.java
Normal file
108
jdk/src/share/classes/sun/util/locale/LocaleObjectCache.java
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class LocaleObjectCache<K, V> {
|
||||
private ConcurrentHashMap<K, CacheEntry<K, V>> _map;
|
||||
private ReferenceQueue<V> _queue = new ReferenceQueue<V>();
|
||||
|
||||
public LocaleObjectCache() {
|
||||
this(16, 0.75f, 16);
|
||||
}
|
||||
|
||||
public LocaleObjectCache(int initialCapacity, float loadFactor, int concurrencyLevel) {
|
||||
_map = new ConcurrentHashMap<K, CacheEntry<K, V>>(initialCapacity, loadFactor, concurrencyLevel);
|
||||
}
|
||||
|
||||
public V get(K key) {
|
||||
V value = null;
|
||||
|
||||
cleanStaleEntries();
|
||||
CacheEntry<K, V> entry = _map.get(key);
|
||||
if (entry != null) {
|
||||
value = entry.get();
|
||||
}
|
||||
if (value == null) {
|
||||
key = normalizeKey(key);
|
||||
V newVal = createObject(key);
|
||||
if (key == null || newVal == null) {
|
||||
// subclass must return non-null key/value object
|
||||
return null;
|
||||
}
|
||||
|
||||
CacheEntry<K, V> newEntry = new CacheEntry<K, V>(key, newVal, _queue);
|
||||
|
||||
while (value == null) {
|
||||
cleanStaleEntries();
|
||||
entry = _map.putIfAbsent(key, newEntry);
|
||||
if (entry == null) {
|
||||
value = newVal;
|
||||
break;
|
||||
} else {
|
||||
value = entry.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void cleanStaleEntries() {
|
||||
CacheEntry<K, V> entry;
|
||||
while ((entry = (CacheEntry<K, V>)_queue.poll()) != null) {
|
||||
_map.remove(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract V createObject(K key);
|
||||
|
||||
protected K normalizeKey(K key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
private static class CacheEntry<K, V> extends SoftReference<V> {
|
||||
private K _key;
|
||||
|
||||
CacheEntry(K key, V value, ReferenceQueue<V> queue) {
|
||||
super(value, queue);
|
||||
_key = key;
|
||||
}
|
||||
|
||||
K getKey() {
|
||||
return _key;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public class LocaleSyntaxException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int _index = -1;
|
||||
|
||||
public LocaleSyntaxException(String msg) {
|
||||
this(msg, 0);
|
||||
}
|
||||
|
||||
public LocaleSyntaxException(String msg, int errorIndex) {
|
||||
super(msg);
|
||||
_index = errorIndex;
|
||||
}
|
||||
|
||||
public int getErrorIndex() {
|
||||
return _index;
|
||||
}
|
||||
}
|
60
jdk/src/share/classes/sun/util/locale/ParseStatus.java
Normal file
60
jdk/src/share/classes/sun/util/locale/ParseStatus.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public class ParseStatus {
|
||||
int _parseLength = 0;
|
||||
int _errorIndex = -1;
|
||||
String _errorMsg = null;
|
||||
|
||||
public void reset() {
|
||||
_parseLength = 0;
|
||||
_errorIndex = -1;
|
||||
_errorMsg = null;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return (_errorIndex >= 0);
|
||||
}
|
||||
|
||||
public int getErrorIndex() {
|
||||
return _errorIndex;
|
||||
}
|
||||
|
||||
public int getParseLength() {
|
||||
return _parseLength;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return _errorMsg;
|
||||
}
|
||||
}
|
117
jdk/src/share/classes/sun/util/locale/StringTokenIterator.java
Normal file
117
jdk/src/share/classes/sun/util/locale/StringTokenIterator.java
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public class StringTokenIterator {
|
||||
private String _text;
|
||||
private String _dlms;
|
||||
|
||||
private String _token;
|
||||
private int _start;
|
||||
private int _end;
|
||||
private boolean _done;
|
||||
|
||||
public StringTokenIterator(String text, String dlms) {
|
||||
_text = text;
|
||||
_dlms = dlms;
|
||||
setStart(0);
|
||||
}
|
||||
|
||||
public String first() {
|
||||
setStart(0);
|
||||
return _token;
|
||||
}
|
||||
|
||||
public String current() {
|
||||
return _token;
|
||||
}
|
||||
|
||||
public int currentStart() {
|
||||
return _start;
|
||||
}
|
||||
|
||||
public int currentEnd() {
|
||||
return _end;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return _done;
|
||||
}
|
||||
|
||||
public String next() {
|
||||
if (hasNext()) {
|
||||
_start = _end + 1;
|
||||
_end = nextDelimiter(_start);
|
||||
_token = _text.substring(_start, _end);
|
||||
} else {
|
||||
_start = _end;
|
||||
_token = null;
|
||||
_done = true;
|
||||
}
|
||||
return _token;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return (_end < _text.length());
|
||||
}
|
||||
|
||||
public StringTokenIterator setStart(int offset) {
|
||||
if (offset > _text.length()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
_start = offset;
|
||||
_end = nextDelimiter(_start);
|
||||
_token = _text.substring(_start, _end);
|
||||
_done = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringTokenIterator setText(String text) {
|
||||
_text = text;
|
||||
setStart(0);
|
||||
return this;
|
||||
}
|
||||
|
||||
private int nextDelimiter(int start) {
|
||||
int idx = start;
|
||||
outer: while (idx < _text.length()) {
|
||||
char c = _text.charAt(idx);
|
||||
for (int i = 0; i < _dlms.length(); i++) {
|
||||
if (c == _dlms.charAt(i)) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class UnicodeLocaleExtension extends Extension {
|
||||
public static final char SINGLETON = 'u';
|
||||
|
||||
private static final SortedSet<String> EMPTY_SORTED_SET = new TreeSet<String>();
|
||||
private static final SortedMap<String, String> EMPTY_SORTED_MAP = new TreeMap<String, String>();
|
||||
|
||||
private SortedSet<String> _attributes = EMPTY_SORTED_SET;
|
||||
private SortedMap<String, String> _keywords = EMPTY_SORTED_MAP;
|
||||
|
||||
public static final UnicodeLocaleExtension CA_JAPANESE;
|
||||
public static final UnicodeLocaleExtension NU_THAI;
|
||||
|
||||
static {
|
||||
CA_JAPANESE = new UnicodeLocaleExtension();
|
||||
CA_JAPANESE._keywords = new TreeMap<String, String>();
|
||||
CA_JAPANESE._keywords.put("ca", "japanese");
|
||||
CA_JAPANESE._value = "ca-japanese";
|
||||
|
||||
NU_THAI = new UnicodeLocaleExtension();
|
||||
NU_THAI._keywords = new TreeMap<String, String>();
|
||||
NU_THAI._keywords.put("nu", "thai");
|
||||
NU_THAI._value = "nu-thai";
|
||||
}
|
||||
|
||||
private UnicodeLocaleExtension() {
|
||||
super(SINGLETON);
|
||||
}
|
||||
|
||||
UnicodeLocaleExtension(SortedSet<String> attributes, SortedMap<String, String> keywords) {
|
||||
this();
|
||||
if (attributes != null && attributes.size() > 0) {
|
||||
_attributes = attributes;
|
||||
}
|
||||
if (keywords != null && keywords.size() > 0) {
|
||||
_keywords = keywords;
|
||||
}
|
||||
|
||||
if (_attributes.size() > 0 || _keywords.size() > 0) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String attribute : _attributes) {
|
||||
sb.append(LanguageTag.SEP).append(attribute);
|
||||
}
|
||||
for (Entry<String, String> keyword : _keywords.entrySet()) {
|
||||
String key = keyword.getKey();
|
||||
String value = keyword.getValue();
|
||||
|
||||
sb.append(LanguageTag.SEP).append(key);
|
||||
if (value.length() > 0) {
|
||||
sb.append(LanguageTag.SEP).append(value);
|
||||
}
|
||||
}
|
||||
_value = sb.substring(1); // skip leading '-'
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleAttributes() {
|
||||
return Collections.unmodifiableSet(_attributes);
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleKeys() {
|
||||
return Collections.unmodifiableSet(_keywords.keySet());
|
||||
}
|
||||
|
||||
public String getUnicodeLocaleType(String unicodeLocaleKey) {
|
||||
return _keywords.get(unicodeLocaleKey);
|
||||
}
|
||||
|
||||
public static boolean isSingletonChar(char c) {
|
||||
return (SINGLETON == AsciiUtil.toLower(c));
|
||||
}
|
||||
|
||||
public static boolean isAttribute(String s) {
|
||||
// 3*8alphanum
|
||||
return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
public static boolean isKey(String s) {
|
||||
// 2alphanum
|
||||
return (s.length() == 2) && AsciiUtil.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
public static boolean isTypeSubtag(String s) {
|
||||
// 3*8alphanum
|
||||
return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2010, 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
|
||||
@ -177,6 +177,11 @@ public class LocaleData {
|
||||
|
||||
for (Iterator<Locale> l = candidates.iterator(); l.hasNext(); ) {
|
||||
String lstr = l.next().toString();
|
||||
/* truncate extra segment introduced by Java 7 for script and extesions */
|
||||
int idx = lstr.indexOf("_#");
|
||||
if (idx >= 0) {
|
||||
lstr = lstr.substring(0, idx);
|
||||
}
|
||||
/* Every locale string in the locale string list returned from
|
||||
the above getSupportedLocaleString is enclosed
|
||||
within two white spaces so that we could check some locale
|
||||
|
@ -228,6 +228,157 @@ za=Zhuang
|
||||
zh=Chinese
|
||||
zu=Zulu
|
||||
|
||||
# script names
|
||||
# key is ISO 15924 script code
|
||||
|
||||
Arab=Arabic
|
||||
Armi=Imperial Aramaic
|
||||
Armn=Armenian
|
||||
Avst=Avestan
|
||||
Bali=Balinese
|
||||
Bamu=Bamum
|
||||
Bass=Bassa Vah
|
||||
Batk=Batak
|
||||
Beng=Bengali
|
||||
Blis=Blissymbols
|
||||
Bopo=Bopomofo
|
||||
Brah=Brahmi
|
||||
Brai=Braille
|
||||
Bugi=Buginese
|
||||
Buhd=Buhid
|
||||
Cakm=Chakma
|
||||
Cans=Unified Canadian Aboriginal Syllabics
|
||||
Cari=Carian
|
||||
Cham=Cham
|
||||
Cher=Cherokee
|
||||
Cirt=Cirth
|
||||
Copt=Coptic
|
||||
Cprt=Cypriot
|
||||
Cyrl=Cyrillic
|
||||
Cyrs=Old Church Slavonic Cyrillic
|
||||
Deva=Devanagari
|
||||
Dsrt=Deseret
|
||||
Dupl=Duployan shorthand
|
||||
Egyd=Egyptian demotic
|
||||
Egyh=Egyptian hieratic
|
||||
Egyp=Egyptian hieroglyphs
|
||||
Elba=Elbasan
|
||||
Ethi=Ethiopic
|
||||
Geok=Khutsuri
|
||||
Geor=Georgian
|
||||
Glag=Glagolitic
|
||||
Goth=Gothic
|
||||
Gran=Grantha
|
||||
Grek=Greek
|
||||
Gujr=Gujarati
|
||||
Guru=Gurmukhi
|
||||
Hang=Hangul
|
||||
Hani=Han
|
||||
Hano=Hanunoo
|
||||
Hans=Simplified Han
|
||||
Hant=Traditional Han
|
||||
Hebr=Hebrew
|
||||
Hira=Hiragana
|
||||
Hmng=Pahawh Hmong
|
||||
Hrkt=Katakana or Hiragana
|
||||
Hung=Old Hungarian
|
||||
Inds=Indus
|
||||
Ital=Old Italic
|
||||
Java=Javanese
|
||||
Jpan=Japanese
|
||||
Kali=Kayah Li
|
||||
Kana=Katakana
|
||||
Khar=Kharoshthi
|
||||
Khmr=Khmer
|
||||
Knda=Kannada
|
||||
Kore=Korean
|
||||
Kpel=Kpelle
|
||||
Kthi=Kaithi
|
||||
Lana=Tai Tham
|
||||
Laoo=Lao
|
||||
Latf=Fraktur Latin
|
||||
Latg=Gaelic Latin
|
||||
Latn=Latin
|
||||
Lepc=Lepcha
|
||||
Limb=Limbu
|
||||
Lina=Linear A
|
||||
Linb=Linear B
|
||||
Lisu=Lisu
|
||||
Loma=Loma
|
||||
Lyci=Lycian
|
||||
Lydi=Lydian
|
||||
Mand=Mandaic
|
||||
Mani=Manichaean
|
||||
Maya=Mayan hieroglyphs
|
||||
Mend=Mende
|
||||
Merc=Meroitic Cursive
|
||||
Mero=Meroitic
|
||||
Mlym=Malayalam
|
||||
Mong=Mongolian
|
||||
Moon=Moon
|
||||
Mtei=Meitei Mayek
|
||||
Mymr=Myanmar
|
||||
Narb=Old North Arabian
|
||||
Nbat=Nabataean
|
||||
Nkgb=Nakhi Geba
|
||||
Nkoo=N\u2019Ko
|
||||
Ogam=Ogham
|
||||
Olck=Ol Chiki
|
||||
Orkh=Orkhon
|
||||
Orya=Oriya
|
||||
Osma=Osmanya
|
||||
Palm=Palmyrene
|
||||
Perm=Old Permic
|
||||
Phag=Phags-pa
|
||||
Phli=Inscriptional Pahlavi
|
||||
Phlp=Psalter Pahlavi
|
||||
Phlv=Book Pahlavi
|
||||
Phnx=Phoenician
|
||||
Plrd=Miao
|
||||
Prti=Inscriptional Parthian
|
||||
Rjng=Rejang
|
||||
Roro=Rongorongo
|
||||
Runr=Runic
|
||||
Samr=Samaritan
|
||||
Sara=Sarati
|
||||
Sarb=Old South Arabian
|
||||
Saur=Saurashtra
|
||||
Sgnw=SignWriting
|
||||
Shaw=Shavian
|
||||
Sind=Sindhi
|
||||
Sinh=Sinhala
|
||||
Sund=Sundanese
|
||||
Sylo=Syloti Nagri
|
||||
Syrc=Syriac
|
||||
Syre=Estrangelo Syriac
|
||||
Syrj=Western Syriac
|
||||
Syrn=Eastern Syriac
|
||||
Tagb=Tagbanwa
|
||||
Tale=Tai Le
|
||||
Talu=New Tai Lue
|
||||
Taml=Tamil
|
||||
Tavt=Tai Viet
|
||||
Telu=Telugu
|
||||
Teng=Tengwar
|
||||
Tfng=Tifinagh
|
||||
Tglg=Tagalog
|
||||
Thaa=Thaana
|
||||
Thai=Thai
|
||||
Tibt=Tibetan
|
||||
Ugar=Ugaritic
|
||||
Vaii=Vai
|
||||
Visp=Visible Speech
|
||||
Wara=Warang Citi
|
||||
Xpeo=Old Persian
|
||||
Xsux=Sumero-Akkadian Cuneiform
|
||||
Yiii=Yi
|
||||
Zinh=Inherited script
|
||||
Zmth=Mathematical Notation
|
||||
Zsym=Symbols
|
||||
Zxxx=Unwritten
|
||||
Zyyy=Undetermined script
|
||||
Zzzz=Uncoded script
|
||||
|
||||
# country names
|
||||
# key is ISO 3166 country code
|
||||
|
||||
@ -479,6 +630,39 @@ ZA=South Africa
|
||||
ZM=Zambia
|
||||
ZW=Zimbabwe
|
||||
|
||||
# territory names
|
||||
# key is UN M.49 country and area code
|
||||
|
||||
001=World
|
||||
002=Africa
|
||||
003=North America
|
||||
005=South America
|
||||
009=Oceania
|
||||
011=Western Africa
|
||||
013=Central America
|
||||
014=Eastern Africa
|
||||
015=Northern Africa
|
||||
017=Middle Africa
|
||||
018=Southern Africa
|
||||
019=Americas
|
||||
021=Northern America
|
||||
029=Caribbean
|
||||
030=Eastern Asia
|
||||
034=Southern Asia
|
||||
035=South-Eastern Asia
|
||||
039=Southern Europe
|
||||
053=Australia and New Zealand
|
||||
054=Melanesia
|
||||
057=Micronesian Region
|
||||
061=Polynesia
|
||||
142=Asia
|
||||
143=Central Asia
|
||||
145=Western Asia
|
||||
150=Europe
|
||||
151=Eastern Europe
|
||||
154=Northern Europe
|
||||
155=Western Europe
|
||||
419=Latin America and the Caribbean
|
||||
|
||||
# variant names
|
||||
# key is %%variant
|
||||
|
@ -227,6 +227,12 @@ za=\u85cf\u6587
|
||||
zh=\u4e2d\u6587
|
||||
zu=\u7956\u9c81\u6587
|
||||
|
||||
# script names
|
||||
# key is ISO 15924 script code
|
||||
|
||||
Hans=\u7b80\u4f53\u4e2d\u6587
|
||||
Hant=\u7e41\u4f53\u4e2d\u6587
|
||||
|
||||
# country names
|
||||
# key is ISO 3166 country code
|
||||
|
||||
|
@ -227,6 +227,12 @@ za=\u58ef\u6587
|
||||
zh=\u4e2d\u6587
|
||||
zu=\u7956\u9b6f\u6587
|
||||
|
||||
# script names
|
||||
# key is ISO 15924 script code
|
||||
|
||||
Hans=\u7c21\u9ad4\u4e2d\u6587
|
||||
Hant=\u7e41\u9ad4\u4e2d\u6587
|
||||
|
||||
# country names
|
||||
# key is ISO 3166 country code
|
||||
|
||||
|
217
jdk/test/java/text/Format/DateFormat/ISO8601ZoneTest.java
Normal file
217
jdk/test/java/text/Format/DateFormat/ISO8601ZoneTest.java
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4919632
|
||||
* @summary Unit test for ISO8601 time zone format support
|
||||
*/
|
||||
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class ISO8601ZoneTest {
|
||||
static final Date TIMESTAMP = new Date(1283758039020L);
|
||||
|
||||
static final String[][] formatData = {
|
||||
// time zone name, expected output at TIMESTAMP
|
||||
{ "America/Los_Angeles", "2010-09-06T00:27:19.020-07", },
|
||||
{ "America/Los_Angeles", "2010-09-06T00:27:19.020-0700", },
|
||||
{ "America/Los_Angeles", "2010-09-06T00:27:19.020-07:00", },
|
||||
{ "Australia/Sydney", "2010-09-06T17:27:19.020+10", },
|
||||
{ "Australia/Sydney", "2010-09-06T17:27:19.020+1000", },
|
||||
{ "Australia/Sydney", "2010-09-06T17:27:19.020+10:00", },
|
||||
{ "GMT-07:00", "2010-09-06T00:27:19.020-07", },
|
||||
{ "GMT-07:00", "2010-09-06T00:27:19.020-0700", },
|
||||
{ "GMT-07:00", "2010-09-06T00:27:19.020-07:00", },
|
||||
{ "UTC", "2010-09-06T07:27:19.020Z", },
|
||||
{ "UTC", "2010-09-06T07:27:19.020Z", },
|
||||
{ "UTC", "2010-09-06T07:27:19.020Z", },
|
||||
};
|
||||
|
||||
static final String[] zones = {
|
||||
"America/Los_Angeles", "Australia/Sydney", "GMT-07:00",
|
||||
"UTC", "GMT+05:30", "GMT-01:23",
|
||||
};
|
||||
|
||||
static final String[] isoZoneFormats = {
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSX",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSXX",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
|
||||
};
|
||||
|
||||
static final String[][] badData = {
|
||||
{ "X", "1" },
|
||||
{ "X", "+1" },
|
||||
{ "X", "-2" },
|
||||
{ "X", "-24" },
|
||||
{ "X", "+24" },
|
||||
|
||||
{ "XX", "9" },
|
||||
{ "XX", "23" },
|
||||
{ "XX", "234" },
|
||||
{ "XX", "3456" },
|
||||
{ "XX", "23456" },
|
||||
{ "XX", "+1" },
|
||||
{ "XX", "-12" },
|
||||
{ "XX", "+123" },
|
||||
{ "XX", "-12:34" },
|
||||
{ "XX", "+12:34" },
|
||||
{ "XX", "-2423" },
|
||||
{ "XX", "+2423" },
|
||||
{ "XX", "-1260" },
|
||||
{ "XX", "+1260" },
|
||||
|
||||
{ "XXX", "9" },
|
||||
{ "XXX", "23" },
|
||||
{ "XXX", "234" },
|
||||
{ "XXX", "3456" },
|
||||
{ "XXX", "23456" },
|
||||
{ "XXX", "2:34" },
|
||||
{ "XXX", "12:4" },
|
||||
{ "XXX", "12:34" },
|
||||
{ "XXX", "-1" },
|
||||
{ "XXX", "+1" },
|
||||
{ "XXX", "-12" },
|
||||
{ "XXX", "+12" },
|
||||
{ "XXX", "-123" },
|
||||
{ "XXX", "+123" },
|
||||
{ "XXX", "-1234" },
|
||||
{ "XXX", "+1234" },
|
||||
{ "XXX", "+24:23" },
|
||||
{ "XXX", "+12:60" },
|
||||
{ "XXX", "+1:23" },
|
||||
{ "XXX", "+12:3" },
|
||||
};
|
||||
|
||||
static String[] badFormats = {
|
||||
"XXXX", "XXXXX", "XXXXXX",
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
|
||||
try {
|
||||
for (int i = 0; i < formatData.length; i++) {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone(formatData[i][0]));
|
||||
formatTest(isoZoneFormats[i % isoZoneFormats.length],
|
||||
formatData[i][1]);
|
||||
}
|
||||
|
||||
for (String zone : zones) {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone(zone));
|
||||
for (String fmt : isoZoneFormats) {
|
||||
roundtripTest(fmt);
|
||||
SimpleDateFormat f = new SimpleDateFormat(fmt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (String[] d : badData) {
|
||||
badDataParsing(d[0], d[1]);
|
||||
}
|
||||
|
||||
for (String fmt : badFormats) {
|
||||
badFormat(fmt);
|
||||
}
|
||||
} finally {
|
||||
TimeZone.setDefault(tz);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void formatTest(String fmt, String expected) throws Exception {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
|
||||
String s = sdf.format(TIMESTAMP);
|
||||
if (!expected.equals(s)) {
|
||||
throw new RuntimeException("formatTest: got " + s
|
||||
+ ", expected " + expected);
|
||||
}
|
||||
|
||||
Date d = sdf.parse(s);
|
||||
if (d.getTime() != TIMESTAMP.getTime()) {
|
||||
throw new RuntimeException("formatTest: parse(" + s
|
||||
+ "), got " + d.getTime()
|
||||
+ ", expected " + TIMESTAMP.getTime());
|
||||
}
|
||||
|
||||
ParsePosition pos = new ParsePosition(0);
|
||||
d = sdf.parse(s + "123", pos);
|
||||
if (d.getTime() != TIMESTAMP.getTime()) {
|
||||
throw new RuntimeException("formatTest: parse(" + s
|
||||
+ "), got " + d.getTime()
|
||||
+ ", expected " + TIMESTAMP.getTime());
|
||||
}
|
||||
if (pos.getIndex() != s.length()) {
|
||||
throw new RuntimeException("formatTest: wrong resulting parse position: "
|
||||
+ pos.getIndex() + ", expected " + s.length());
|
||||
}
|
||||
}
|
||||
|
||||
static void roundtripTest(String fmt) throws Exception {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
|
||||
Date date = new Date();
|
||||
|
||||
int fractionalHour = sdf.getTimeZone().getOffset(date.getTime());
|
||||
fractionalHour %= 3600000; // fraction of hour
|
||||
|
||||
String s = sdf.format(date);
|
||||
Date pd = sdf.parse(s);
|
||||
long diffsInMillis = pd.getTime() - date.getTime();
|
||||
if (diffsInMillis != 0) {
|
||||
if (diffsInMillis != fractionalHour) {
|
||||
throw new RuntimeException("fmt= " + fmt
|
||||
+ ", diff="+diffsInMillis
|
||||
+ ", fraction=" + fractionalHour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void badDataParsing(String fmt, String text) {
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
|
||||
sdf.parse(text);
|
||||
throw new RuntimeException("didn't throw an exception: fmt=" + fmt
|
||||
+ ", text=" + text);
|
||||
} catch (ParseException e) {
|
||||
// OK
|
||||
}
|
||||
}
|
||||
|
||||
static void badFormat(String fmt) {
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
|
||||
throw new RuntimeException("Constructor didn't throw an exception: fmt=" + fmt);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// OK
|
||||
}
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat();
|
||||
sdf.applyPattern(fmt);
|
||||
throw new RuntimeException("applyPattern didn't throw an exception: fmt=" + fmt);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// OK
|
||||
}
|
||||
}
|
||||
}
|
@ -36,27 +36,44 @@ public class WeekDateTest {
|
||||
// Week dates are in the ISO numbering for day-of-week.
|
||||
static int[][][] data = {
|
||||
// Calendar year-date, Week year-date
|
||||
{{ 2005, 01, 01}, {2004, 53, 6}},
|
||||
{{ 2005, 01, 02}, {2004, 53, 7}},
|
||||
{{ 2005, 12, 31}, {2005, 52, 6}},
|
||||
{{ 2007, 01, 01}, {2007, 01, 1}},
|
||||
{{ 2007, 12, 30}, {2007, 52, 7}},
|
||||
{{ 2007, 12, 31}, {2008, 01, 1}},
|
||||
{{ 2008, 01, 01}, {2008, 01, 2}},
|
||||
{{ 2008, 12, 29}, {2009, 01, 1}},
|
||||
{{ 2008, 12, 31}, {2009, 01, 3}},
|
||||
{{ 2009, 01, 01}, {2009, 01, 4}},
|
||||
{{ 2009, 12, 31}, {2009, 53, 4}},
|
||||
{{ 2010, 01, 03}, {2009, 53, 7}},
|
||||
{{ 2009, 12, 31}, {2009, 53, 4}},
|
||||
{{ 2010, 01, 01}, {2009, 53, 5}},
|
||||
{{ 2010, 01, 02}, {2009, 53, 6}},
|
||||
{{ 2010, 01, 03}, {2009, 53, 7}},
|
||||
{{ 2008, 12, 28}, {2008, 52, 7}},
|
||||
{{ 2008, 12, 29}, {2009, 01, 1}},
|
||||
{{ 2008, 12, 30}, {2009, 01, 2}},
|
||||
{{ 2008, 12, 31}, {2009, 01, 3}},
|
||||
{{ 2009, 01, 01}, {2009, 01, 4}}
|
||||
{{ 2005, 01, 01}, { 2004, 53, 6}},
|
||||
{{ 2005, 01, 02}, { 2004, 53, 7}},
|
||||
{{ 2005, 12, 31}, { 2005, 52, 6}},
|
||||
{{ 2007, 01, 01}, { 2007, 01, 1}},
|
||||
{{ 2007, 12, 30}, { 2007, 52, 7}},
|
||||
{{ 2007, 12, 31}, { 2008, 01, 1}},
|
||||
{{ 2008, 01, 01}, { 2008, 01, 2}},
|
||||
{{ 2008, 12, 29}, { 2009, 01, 1}},
|
||||
{{ 2008, 12, 31}, { 2009, 01, 3}},
|
||||
{{ 2009, 01, 01}, { 2009, 01, 4}},
|
||||
{{ 2009, 12, 31}, { 2009, 53, 4}},
|
||||
{{ 2010, 01, 03}, { 2009, 53, 7}},
|
||||
{{ 2009, 12, 31}, { 2009, 53, 4}},
|
||||
{{ 2010, 01, 01}, { 2009, 53, 5}},
|
||||
{{ 2010, 01, 02}, { 2009, 53, 6}},
|
||||
{{ 2010, 01, 03}, { 2009, 53, 7}},
|
||||
{{ 2008, 12, 28}, { 2008, 52, 7}},
|
||||
{{ 2008, 12, 29}, { 2009, 01, 1}},
|
||||
{{ 2008, 12, 30}, { 2009, 01, 2}},
|
||||
{{ 2008, 12, 31}, { 2009, 01, 3}},
|
||||
{{ 2009, 01, 01}, { 2009, 01, 4}}
|
||||
};
|
||||
|
||||
// Data for leniency test
|
||||
static final int[][][] leniencyData = {
|
||||
{{ 2008, 12, 28}, { 2009, 0, 7}},
|
||||
{{ 2008, 12, 21}, { 2009, -1, 7}},
|
||||
{{ 2009, 1, 4}, { 2008, 53, 7}},
|
||||
};
|
||||
|
||||
static final int[][] invalidData = {
|
||||
{ 2010, -1, 1},
|
||||
{ 2010, 00, 1},
|
||||
{ 2010, 55, 1},
|
||||
{ 2010, 03, 0},
|
||||
{ 2010, 04, 8},
|
||||
{ 2010, 04, 19},
|
||||
{ 2010, 05, -1},
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
@ -65,7 +82,7 @@ public class WeekDateTest {
|
||||
int[] expected = dates[0];
|
||||
int[] weekDate = dates[1];
|
||||
// Convert ISO 8601 day-of-week to Calendar.DAY_OF_WEEK.
|
||||
int dayOfWeek = weekDate[2] == 7 ? SUNDAY : weekDate[2] + 1;
|
||||
int dayOfWeek = getCalendarDayOfWeek(weekDate[2]);
|
||||
|
||||
cal.clear();
|
||||
cal.setWeekDate(weekDate[0], weekDate[1], dayOfWeek);
|
||||
@ -102,21 +119,55 @@ public class WeekDateTest {
|
||||
n, cal.getActualMaximum(WEEK_OF_YEAR));
|
||||
throw new RuntimeException(s);
|
||||
}
|
||||
|
||||
cal.setWeekDate(cal.getWeekYear(), 1, MONDAY);
|
||||
System.out.println(cal.getTime());
|
||||
if (cal.getWeeksInWeekYear() != n) {
|
||||
String s = String.format("first day: got %d, expected %d%n",
|
||||
cal.getWeeksInWeekYear(), n);
|
||||
throw new RuntimeException(s);
|
||||
}
|
||||
|
||||
cal.setWeekDate(cal.getWeekYear(), n, SUNDAY);
|
||||
System.out.println(cal.getTime());
|
||||
if (cal.getWeeksInWeekYear() != n) {
|
||||
String s = String.format("last day: got %d, expected %d%n",
|
||||
cal.getWeeksInWeekYear(), n);
|
||||
throw new RuntimeException(s);
|
||||
}
|
||||
}
|
||||
|
||||
// Test lenient mode with out of range values.
|
||||
for (int[][] dates : leniencyData) {
|
||||
int[] expected = dates[0];
|
||||
int[] weekDate = dates[1];
|
||||
// Convert ISO 8601 day-of-week to Calendar.DAY_OF_WEEK.
|
||||
int dayOfWeek = getCalendarDayOfWeek(weekDate[2]);
|
||||
|
||||
cal.clear();
|
||||
cal.setWeekDate(weekDate[0], weekDate[1], dayOfWeek);
|
||||
if (cal.get(YEAR) != expected[0]
|
||||
|| cal.get(MONTH)+1 != expected[1]
|
||||
|| cal.get(DAY_OF_MONTH) != expected[2]) {
|
||||
String s = String.format("got=%4d-%02d-%02d, expected=%4d-%02d-%02d",
|
||||
cal.get(YEAR), cal.get(MONTH)+1, cal.get(DAY_OF_MONTH),
|
||||
expected[0], expected[1], expected[2]);
|
||||
throw new RuntimeException(s);
|
||||
}
|
||||
}
|
||||
|
||||
// Test non-lenient mode
|
||||
cal.setLenient(false);
|
||||
for (int[] date : invalidData) {
|
||||
cal.clear();
|
||||
try {
|
||||
// Use the raw dayOfWeek value as invalid data
|
||||
cal.setWeekDate(date[0], date[1], date[2]);
|
||||
String s = String.format("didn't throw an IllegalArgumentException with"
|
||||
+ " %d, %d, %d",date[0], date[1], date[2]);
|
||||
throw new RuntimeException(s);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// OK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static GregorianCalendar newCalendar() {
|
||||
@ -130,4 +181,8 @@ public class WeekDateTest {
|
||||
cal.setMinimalDaysInFirstWeek(4);
|
||||
return cal;
|
||||
}
|
||||
|
||||
private static int getCalendarDayOfWeek(int isoDayOfWeek) {
|
||||
return (isoDayOfWeek == 7) ? SUNDAY : isoDayOfWeek + 1;
|
||||
}
|
||||
}
|
||||
|
1293
jdk/test/java/util/Locale/LocaleEnhanceTest.java
Normal file
1293
jdk/test/java/util/Locale/LocaleEnhanceTest.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 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.
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
@ -20,6 +22,7 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
@ -112,6 +115,8 @@ public class LocaleTestFmwk {
|
||||
prompt = true;
|
||||
} else if (args[i].equals("-nothrow")) {
|
||||
nothrow = true;
|
||||
} else if (args[i].equals("-exitcode")) {
|
||||
exitcode = true;
|
||||
} else {
|
||||
Object m = testMethods.get( args[i] );
|
||||
if( m != null ) {
|
||||
@ -165,7 +170,12 @@ public class LocaleTestFmwk {
|
||||
}
|
||||
}
|
||||
if (nothrow) {
|
||||
System.exit(errorCount);
|
||||
if (exitcode) {
|
||||
System.exit(errorCount);
|
||||
}
|
||||
if (errorCount > 0) {
|
||||
throw new IllegalArgumentException("encountered " + errorCount + " errors");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +245,7 @@ public class LocaleTestFmwk {
|
||||
*/
|
||||
void usage() {
|
||||
System.out.println(getClass().getName() +
|
||||
": [-verbose] [-nothrow] [-prompt] [test names]");
|
||||
": [-verbose] [-nothrow] [-exitcode] [-prompt] [test names]");
|
||||
|
||||
System.out.println("test names:");
|
||||
Enumeration methodNames = testMethods.keys();
|
||||
@ -246,6 +256,7 @@ public class LocaleTestFmwk {
|
||||
|
||||
private boolean prompt = false;
|
||||
private boolean nothrow = false;
|
||||
private boolean exitcode = false;
|
||||
protected boolean verbose = false;
|
||||
|
||||
private PrintWriter log;
|
||||
|
292
jdk/test/java/util/Locale/icuLocales.txt
Normal file
292
jdk/test/java/util/Locale/icuLocales.txt
Normal file
@ -0,0 +1,292 @@
|
||||
af
|
||||
af-NA
|
||||
af-ZA
|
||||
am
|
||||
am-ET
|
||||
ar
|
||||
ar-AE
|
||||
ar-BH
|
||||
ar-DZ
|
||||
ar-EG
|
||||
ar-IQ
|
||||
ar-JO
|
||||
ar-KW
|
||||
ar-LB
|
||||
ar-LY
|
||||
ar-MA
|
||||
ar-OM
|
||||
ar-QA
|
||||
ar-SA
|
||||
ar-SD
|
||||
ar-SY
|
||||
ar-TN
|
||||
ar-YE
|
||||
as
|
||||
as-IN
|
||||
az
|
||||
az-Cyrl
|
||||
az-Cyrl-AZ
|
||||
az-Latn
|
||||
az-Latn-AZ
|
||||
be
|
||||
be-BY
|
||||
bg
|
||||
bg-BG
|
||||
bn
|
||||
bn-BD
|
||||
bn-IN
|
||||
bo
|
||||
bo-CN
|
||||
bo-IN
|
||||
ca
|
||||
ca-ES
|
||||
cs
|
||||
cs-CZ
|
||||
cy
|
||||
cy-GB
|
||||
da
|
||||
da-DK
|
||||
de
|
||||
de-AT
|
||||
de-BE
|
||||
de-CH
|
||||
de-DE
|
||||
de-LI
|
||||
de-LU
|
||||
el
|
||||
el-CY
|
||||
el-GR
|
||||
en
|
||||
en-AU
|
||||
en-BE
|
||||
en-BW
|
||||
en-BZ
|
||||
en-CA
|
||||
en-GB
|
||||
en-HK
|
||||
en-IE
|
||||
en-IN
|
||||
en-JM
|
||||
en-MH
|
||||
en-MT
|
||||
en-NA
|
||||
en-NZ
|
||||
en-PH
|
||||
en-PK
|
||||
en-SG
|
||||
en-TT
|
||||
en-US
|
||||
en-US-posix
|
||||
en-VI
|
||||
en-ZA
|
||||
en-ZW
|
||||
eo
|
||||
es
|
||||
es-AR
|
||||
es-BO
|
||||
es-CL
|
||||
es-CO
|
||||
es-CR
|
||||
es-DO
|
||||
es-EC
|
||||
es-ES
|
||||
es-GT
|
||||
es-HN
|
||||
es-MX
|
||||
es-NI
|
||||
es-PA
|
||||
es-PE
|
||||
es-PR
|
||||
es-PY
|
||||
es-SV
|
||||
es-US
|
||||
es-UY
|
||||
es-VE
|
||||
et
|
||||
et-EE
|
||||
eu
|
||||
eu-ES
|
||||
fa
|
||||
fa-AF
|
||||
fa-IR
|
||||
fi
|
||||
fi-FI
|
||||
fo
|
||||
fo-FO
|
||||
fr
|
||||
fr-BE
|
||||
fr-CA
|
||||
fr-CH
|
||||
fr-FR
|
||||
fr-LU
|
||||
fr-MC
|
||||
fr-SN
|
||||
ga
|
||||
ga-IE
|
||||
gl
|
||||
gl-ES
|
||||
gsw
|
||||
gsw-CH
|
||||
gu
|
||||
gu-IN
|
||||
gv
|
||||
gv-GB
|
||||
ha
|
||||
ha-Latn
|
||||
ha-Latn-GH
|
||||
ha-Latn-NE
|
||||
ha-Latn-NG
|
||||
haw
|
||||
haw-US
|
||||
he
|
||||
he-IL
|
||||
hi
|
||||
hi-IN
|
||||
hr
|
||||
hr-HR
|
||||
hu
|
||||
hu-HU
|
||||
hy
|
||||
hy-AM
|
||||
hy-AM-revised
|
||||
id
|
||||
id-ID
|
||||
ii
|
||||
ii-CN
|
||||
is
|
||||
is-IS
|
||||
it
|
||||
it-CH
|
||||
it-IT
|
||||
ja
|
||||
ja-JP
|
||||
ka
|
||||
ka-GE
|
||||
kk
|
||||
kk-Cyrl
|
||||
kk-Cyrl-KZ
|
||||
kl
|
||||
kl-GL
|
||||
km
|
||||
km-KH
|
||||
kn
|
||||
kn-IN
|
||||
ko
|
||||
ko-KR
|
||||
kok
|
||||
kok-IN
|
||||
kw
|
||||
kw-GB
|
||||
lt
|
||||
lt-LT
|
||||
lv
|
||||
lv-LV
|
||||
mk
|
||||
mk-MK
|
||||
ml
|
||||
ml-IN
|
||||
mr
|
||||
mr-IN
|
||||
ms
|
||||
ms-BN
|
||||
ms-MY
|
||||
mt
|
||||
mt-MT
|
||||
nb
|
||||
nb-NO
|
||||
ne
|
||||
ne-IN
|
||||
ne-NP
|
||||
nl
|
||||
nl-BE
|
||||
nl-NL
|
||||
nn
|
||||
nn-NO
|
||||
om
|
||||
om-ET
|
||||
om-KE
|
||||
or
|
||||
or-IN
|
||||
pa
|
||||
pa-Arab
|
||||
pa-Arab-PK
|
||||
pa-Guru
|
||||
pa-Guru-IN
|
||||
pl
|
||||
pl-PL
|
||||
ps
|
||||
ps-AF
|
||||
pt
|
||||
pt-BR
|
||||
pt-PT
|
||||
ro
|
||||
ro-MD
|
||||
ro-RO
|
||||
ru
|
||||
ru-RU
|
||||
ru-UA
|
||||
si
|
||||
si-LK
|
||||
sk
|
||||
sk-SK
|
||||
sl
|
||||
sl-SI
|
||||
so
|
||||
so-DJ
|
||||
so-ET
|
||||
so-KE
|
||||
so-SO
|
||||
sq
|
||||
sq-AL
|
||||
sr
|
||||
sr-Cyrl
|
||||
sr-Cyrl-BA
|
||||
sr-Cyrl-ME
|
||||
sr-Cyrl-RS
|
||||
sr-Latn
|
||||
sr-Latn-BA
|
||||
sr-Latn-ME
|
||||
sr-Latn-RS
|
||||
sv
|
||||
sv-FI
|
||||
sv-SE
|
||||
sw
|
||||
sw-KE
|
||||
sw-TZ
|
||||
ta
|
||||
ta-IN
|
||||
te
|
||||
te-IN
|
||||
th
|
||||
th-TH
|
||||
ti
|
||||
ti-ER
|
||||
ti-ET
|
||||
tr
|
||||
tr-TR
|
||||
uk
|
||||
uk-UA
|
||||
ur
|
||||
ur-IN
|
||||
ur-PK
|
||||
uz
|
||||
uz-Arab
|
||||
uz-Arab-AF
|
||||
uz-Cyrl
|
||||
uz-Cyrl-UZ
|
||||
uz-Latn
|
||||
uz-Latn-UZ
|
||||
vi
|
||||
vi-VN
|
||||
zh
|
||||
zh-Hans
|
||||
zh-Hans-CN
|
||||
zh-Hans-HK
|
||||
zh-Hans-MO
|
||||
zh-Hans-SG
|
||||
zh-Hant
|
||||
zh-Hant-HK
|
||||
zh-Hant-MO
|
||||
zh-Hant-TW
|
||||
zu
|
||||
zu-ZA
|
BIN
jdk/test/java/util/Locale/serialized/java6locale_ROOT
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_ROOT
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale__US
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale__US
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale___Java
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale___Java
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale_en
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_en
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale_en_US
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_en_US
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale_en_US_Java
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_en_US_Java
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale_iw_IL
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_iw_IL
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale_ja_JP_JP
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_ja_JP_JP
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale_no_NO_NY
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_no_NO_NY
Normal file
Binary file not shown.
BIN
jdk/test/java/util/Locale/serialized/java6locale_th_TH_TH
Normal file
BIN
jdk/test/java/util/Locale/serialized/java6locale_th_TH_TH
Normal file
Binary file not shown.
51
jdk/test/java/util/TimeZone/Bug6912560.java
Normal file
51
jdk/test/java/util/TimeZone/Bug6912560.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6912560
|
||||
* @run main/othervm Bug6912560
|
||||
* @summary Make sure that file path canonicalization in
|
||||
* sun.util.calendar.ZoneInfoFile works with the default security
|
||||
* manager.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public class Bug6912560 {
|
||||
public static void main(String[] args) {
|
||||
// set the user.timezone property
|
||||
String tzname = "Asia/Tokyo";
|
||||
System.setProperty("user.timezone", tzname);
|
||||
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
if (!tzname.equals(tz.getID())) {
|
||||
throw new RuntimeException("got " + tz.getID()
|
||||
+ ", expected " + tzname);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test skip method returned from AudioFloatFormatConverter.getAudioInputStream */
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
|
||||
import com.sun.media.sound.AudioFloatFormatConverter;
|
||||
|
||||
public class SkipTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AudioFloatFormatConverter converter = new AudioFloatFormatConverter();
|
||||
byte[] data = { 10, 20, 30, 40, 30, 20, 10 };
|
||||
AudioFormat format = new AudioFormat(8000, 8, 1, true, false);
|
||||
AudioFormat format2 = new AudioFormat(16000, 8, 1, true, false);
|
||||
AudioInputStream ais = new AudioInputStream(new ByteArrayInputStream(
|
||||
data), format, data.length);
|
||||
AudioInputStream ais2 = converter.getAudioInputStream(format2, ais);
|
||||
byte[] data2 = new byte[30];
|
||||
int ret = ais2.read(data2, 0, data2.length);
|
||||
ais.reset();
|
||||
AudioInputStream ais3 = converter.getAudioInputStream(format2, ais);
|
||||
byte[] data3 = new byte[100];
|
||||
ais3.skip(7);
|
||||
int ret2 = ais3.read(data3, 7, data3.length);
|
||||
if (ret2 != ret - 7)
|
||||
throw new Exception("Skip doesn't work correctly (" + ret2 + " != "
|
||||
+ (ret - 7) + ")");
|
||||
for (int i = 7; i < ret2 + 7; i++) {
|
||||
if (data3[i] != data2[i])
|
||||
throw new Exception("Skip doesn't work correctly (" + data3[i]
|
||||
+ " != " + data2[i] + ")");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test AudioFloatInputStream.getFrameLength() returned from
|
||||
ModelByteBufferWavetable openStream method */
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
import com.sun.media.sound.*;
|
||||
|
||||
public class OpenStream {
|
||||
|
||||
static float[] testarray;
|
||||
|
||||
static byte[] test_byte_array;
|
||||
|
||||
static byte[] test_byte_array_8ext;
|
||||
|
||||
static AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
|
||||
|
||||
static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false);
|
||||
|
||||
static ModelByteBuffer buffer;
|
||||
|
||||
static ModelByteBuffer buffer_wave;
|
||||
|
||||
static ModelByteBuffer buffer8;
|
||||
|
||||
static ModelByteBuffer buffer16_8;
|
||||
|
||||
static ModelByteBuffer buffer24;
|
||||
|
||||
static File test_file;
|
||||
|
||||
static ModelByteBuffer buffer_wave_ondisk;
|
||||
|
||||
static void setUp() throws Exception {
|
||||
testarray = new float[1024];
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
double ii = i / 1024.0;
|
||||
ii = ii * ii;
|
||||
testarray[i] = (float) Math.sin(10 * ii * 2 * Math.PI);
|
||||
testarray[i] += (float) Math.sin(1.731 + 2 * ii * 2 * Math.PI);
|
||||
testarray[i] += (float) Math.sin(0.231 + 6.3 * ii * 2 * Math.PI);
|
||||
testarray[i] *= 0.3;
|
||||
}
|
||||
test_byte_array = new byte[testarray.length * 2];
|
||||
AudioFloatConverter.getConverter(format).toByteArray(testarray,
|
||||
test_byte_array);
|
||||
buffer = new ModelByteBuffer(test_byte_array);
|
||||
|
||||
byte[] test_byte_array2 = new byte[testarray.length * 3];
|
||||
buffer24 = new ModelByteBuffer(test_byte_array2);
|
||||
test_byte_array_8ext = new byte[testarray.length];
|
||||
byte[] test_byte_array_8_16 = new byte[testarray.length * 2];
|
||||
AudioFloatConverter.getConverter(format24).toByteArray(testarray,
|
||||
test_byte_array2);
|
||||
int ix = 0;
|
||||
int x = 0;
|
||||
for (int i = 0; i < test_byte_array_8ext.length; i++) {
|
||||
test_byte_array_8ext[i] = test_byte_array2[ix++];
|
||||
test_byte_array_8_16[x++] = test_byte_array2[ix++];
|
||||
test_byte_array_8_16[x++] = test_byte_array2[ix++];
|
||||
}
|
||||
buffer16_8 = new ModelByteBuffer(test_byte_array_8_16);
|
||||
buffer8 = new ModelByteBuffer(test_byte_array_8ext);
|
||||
|
||||
AudioInputStream ais = new AudioInputStream(buffer.getInputStream(),
|
||||
format, testarray.length);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos);
|
||||
buffer_wave = new ModelByteBuffer(baos.toByteArray());
|
||||
|
||||
test_file = File.createTempFile("test", ".raw");
|
||||
FileOutputStream fos = new FileOutputStream(test_file);
|
||||
fos.write(baos.toByteArray());
|
||||
fos.close();
|
||||
buffer_wave_ondisk = new ModelByteBuffer(test_file);
|
||||
|
||||
}
|
||||
|
||||
static void tearDown() throws Exception {
|
||||
if (!test_file.delete())
|
||||
test_file.deleteOnExit();
|
||||
}
|
||||
|
||||
public static void testOpenStream(ModelByteBufferWavetable wavetable)
|
||||
throws Exception {
|
||||
AudioFloatInputStream ais = wavetable.openStream();
|
||||
long frames = wavetable.getBuffer().capacity()
|
||||
/ wavetable.getFormat().getFrameSize();
|
||||
long framelength = ais.getFrameLength();
|
||||
ais.close();
|
||||
if (frames != framelength) {
|
||||
throw new Exception("Incorrect framelength returned (" + frames
|
||||
+ " != " + framelength + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
setUp();
|
||||
|
||||
try {
|
||||
testOpenStream(new ModelByteBufferWavetable(buffer, format));
|
||||
testOpenStream(new ModelByteBufferWavetable(buffer_wave, format));
|
||||
testOpenStream(new ModelByteBufferWavetable(buffer_wave_ondisk,
|
||||
format));
|
||||
} finally {
|
||||
tearDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test ModelStandardIndexedDirector class */
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.sun.media.sound.ModelConnectionBlock;
|
||||
import com.sun.media.sound.ModelDirectedPlayer;
|
||||
import com.sun.media.sound.ModelPerformer;
|
||||
import com.sun.media.sound.ModelStandardDirector;
|
||||
import com.sun.media.sound.ModelStandardIndexedDirector;
|
||||
|
||||
public class ModelStandardIndexedDirectorTest {
|
||||
|
||||
private static String treeToString(TreeSet<Integer> set)
|
||||
{
|
||||
StringBuffer buff = new StringBuffer();
|
||||
boolean first = true;
|
||||
for(Integer s : set)
|
||||
{
|
||||
if(!first)
|
||||
buff.append(";");
|
||||
buff.append(s);
|
||||
first = false;
|
||||
}
|
||||
return buff.toString();
|
||||
}
|
||||
|
||||
private static void testDirector(ModelPerformer[] performers) throws Exception
|
||||
{
|
||||
final TreeSet<Integer> played = new TreeSet<Integer>();
|
||||
ModelDirectedPlayer player = new ModelDirectedPlayer()
|
||||
{
|
||||
public void play(int performerIndex,
|
||||
ModelConnectionBlock[] connectionBlocks) {
|
||||
played.add(performerIndex);
|
||||
}
|
||||
};
|
||||
ModelStandardIndexedDirector idirector =
|
||||
new ModelStandardIndexedDirector(performers, player);
|
||||
ModelStandardDirector director =
|
||||
new ModelStandardDirector(performers, player);
|
||||
|
||||
for (int n = 0; n < 128; n++)
|
||||
{
|
||||
for (int v = 0; v < 128; v++)
|
||||
{
|
||||
director.noteOn(n, v);
|
||||
String p1 = treeToString(played);
|
||||
played.clear();
|
||||
idirector.noteOn(n, v);
|
||||
String p2 = treeToString(played);
|
||||
played.clear();
|
||||
if(!p1.equals(p2))
|
||||
throw new Exception(
|
||||
"Note = " + n + ", Vel = " + v + " failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testDirectorCombinations(
|
||||
ModelPerformer[] performers) throws Exception
|
||||
{
|
||||
for (int i = 0; i < performers.length; i++) {
|
||||
ModelPerformer[] performers2 = new ModelPerformer[i];
|
||||
for (int j = 0; j < performers2.length; j++) {
|
||||
performers2[j] = performers[i];
|
||||
}
|
||||
testDirector(performers2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addPerformer(
|
||||
List<ModelPerformer> performers,
|
||||
int keyfrom,
|
||||
int keyto,
|
||||
int velfrom,
|
||||
int velto)
|
||||
{
|
||||
ModelPerformer performer = new ModelPerformer();
|
||||
performer.setKeyFrom(keyfrom);
|
||||
performer.setKeyTo(keyto);
|
||||
performer.setVelFrom(velfrom);
|
||||
performer.setVelTo(velto);
|
||||
performers.add(performer);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
// Test collection of normal values
|
||||
List<ModelPerformer> performers = new ArrayList<ModelPerformer>();
|
||||
addPerformer(performers, 0, 0, 0, 127);
|
||||
addPerformer(performers, 0, 50, 0, 127);
|
||||
addPerformer(performers, 0, 127, 0, 127);
|
||||
addPerformer(performers, 21, 21, 0, 127);
|
||||
addPerformer(performers, 21, 60, 0, 127);
|
||||
addPerformer(performers, 21, 127, 0, 127);
|
||||
addPerformer(performers, 50, 50, 0, 127);
|
||||
addPerformer(performers, 50, 60, 0, 127);
|
||||
addPerformer(performers, 50, 127, 0, 127);
|
||||
addPerformer(performers, 73, 73, 0, 127);
|
||||
addPerformer(performers, 73, 80, 0, 127);
|
||||
addPerformer(performers, 73, 127, 0, 127);
|
||||
addPerformer(performers, 127, 127, 0, 127);
|
||||
addPerformer(performers, 0, 0, 60, 127);
|
||||
addPerformer(performers, 0, 50, 60, 127);
|
||||
addPerformer(performers, 0, 127, 60, 127);
|
||||
addPerformer(performers, 21, 21, 60, 127);
|
||||
addPerformer(performers, 21, 60, 60, 127);
|
||||
addPerformer(performers, 21, 127, 60, 127);
|
||||
addPerformer(performers, 50, 50, 60, 127);
|
||||
addPerformer(performers, 50, 60, 60, 127);
|
||||
addPerformer(performers, 50, 127, 60, 127);
|
||||
addPerformer(performers, 73, 73, 60, 127);
|
||||
addPerformer(performers, 73, 80, 60, 127);
|
||||
addPerformer(performers, 73, 127, 60, 127);
|
||||
addPerformer(performers, 127, 127, 60, 127);
|
||||
addPerformer(performers, 0, 0, 80, 83);
|
||||
addPerformer(performers, 0, 50, 80, 83);
|
||||
addPerformer(performers, 0, 127, 80, 83);
|
||||
addPerformer(performers, 21, 21, 80, 83);
|
||||
addPerformer(performers, 21, 60, 80, 83);
|
||||
addPerformer(performers, 21, 127, 80, 83);
|
||||
addPerformer(performers, 50, 50, 80, 83);
|
||||
addPerformer(performers, 50, 60, 80, 83);
|
||||
addPerformer(performers, 50, 127, 80, 83);
|
||||
addPerformer(performers, 73, 73, 80, 83);
|
||||
addPerformer(performers, 73, 80, 80, 83);
|
||||
addPerformer(performers, 73, 127, 80, 83);
|
||||
addPerformer(performers, 127, 127, 80, 83);
|
||||
|
||||
|
||||
testDirectorCombinations(
|
||||
performers.toArray(
|
||||
new ModelPerformer[performers.size()])
|
||||
);
|
||||
|
||||
// Test reversed values
|
||||
performers.clear();
|
||||
addPerformer(performers, 50, 30, 80, 83);
|
||||
addPerformer(performers, 30, 30, 50, 30);
|
||||
addPerformer(performers, 37, 30, 50, 30);
|
||||
testDirector(
|
||||
performers.toArray(
|
||||
new ModelPerformer[performers.size()])
|
||||
);
|
||||
|
||||
// Test out-of-range values
|
||||
performers.clear();
|
||||
addPerformer(performers, -20, 6, 0, 127);
|
||||
addPerformer(performers, 0, 300, 0, 300);
|
||||
addPerformer(performers, -2, -8, -5, -9);
|
||||
|
||||
testDirector(
|
||||
performers.toArray(
|
||||
new ModelPerformer[performers.size()])
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test SoftChannel program and bank change */
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.sound.midi.*;
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
import com.sun.media.sound.*;
|
||||
|
||||
public class ProgramAndBankChange {
|
||||
|
||||
private static SimpleInstrument generateTestInstrument(Patch patch) {
|
||||
ModelOscillator osc = new ModelOscillator() {
|
||||
public float getAttenuation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getChannels() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public ModelOscillatorStream open(float samplerate) {
|
||||
return new ModelOscillatorStream() {
|
||||
public void close() throws IOException {
|
||||
}
|
||||
|
||||
public void noteOff(int velocity) {
|
||||
}
|
||||
|
||||
public void noteOn(MidiChannel channel, VoiceStatus voice,
|
||||
int noteNumber, int velocity) {
|
||||
}
|
||||
|
||||
public int read(float[][] buffer, int offset, int len)
|
||||
throws IOException {
|
||||
return len;
|
||||
}
|
||||
|
||||
public void setPitch(float ipitch) {
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
ModelPerformer performer = new ModelPerformer();
|
||||
performer.getOscillators().add(osc);
|
||||
SimpleInstrument testinstrument = new SimpleInstrument();
|
||||
testinstrument.setPatch(patch);
|
||||
testinstrument.add(performer);
|
||||
return testinstrument;
|
||||
}
|
||||
|
||||
private static void assertTrue(boolean value) throws Exception {
|
||||
if (!value)
|
||||
throw new RuntimeException("assertTrue fails!");
|
||||
}
|
||||
|
||||
private static void testProgramAndBank(SoftSynthesizer soft,
|
||||
AudioInputStream stream, Patch patch) throws Exception {
|
||||
|
||||
int program = patch.getProgram();
|
||||
int bank = patch.getBank();
|
||||
|
||||
MidiChannel channel = soft.getChannels()[0];
|
||||
byte[] buff = new byte[2048];
|
||||
|
||||
channel.programChange(bank, program);
|
||||
channel.noteOn(64, 64);
|
||||
stream.read(buff, 0, buff.length);
|
||||
|
||||
int foundprogram = -1;
|
||||
int foundbank = -1;
|
||||
VoiceStatus[] vstatus = soft.getVoiceStatus();
|
||||
for (int i = 0; i < vstatus.length; i++) {
|
||||
if (vstatus[i].active) {
|
||||
foundprogram = vstatus[i].program;
|
||||
foundbank = vstatus[i].bank;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(foundprogram == program);
|
||||
assertTrue(foundbank == bank);
|
||||
|
||||
channel.noteOn(64, 0);
|
||||
stream.read(buff, 0, buff.length);
|
||||
|
||||
channel = soft.getChannels()[1];
|
||||
// Send MSB Bank
|
||||
channel.controlChange(0x00, bank / 128);
|
||||
// Send LSB Bank
|
||||
channel.controlChange(0x20, bank % 128);
|
||||
// Send Program Change
|
||||
channel.programChange(program);
|
||||
channel.noteOn(64, 64);
|
||||
stream.read(buff, 0, buff.length);
|
||||
|
||||
foundprogram = -1;
|
||||
foundbank = -1;
|
||||
vstatus = soft.getVoiceStatus();
|
||||
for (int i = 0; i < vstatus.length; i++) {
|
||||
if (vstatus[i].active) {
|
||||
foundprogram = vstatus[i].program;
|
||||
foundbank = vstatus[i].bank;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(foundprogram == program);
|
||||
assertTrue(foundbank == bank);
|
||||
channel.noteOn(64, 0);
|
||||
stream.read(buff, 0, buff.length);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SoftSynthesizer soft = new SoftSynthesizer();
|
||||
AudioInputStream stream = soft.openStream(null, null);
|
||||
soft.unloadAllInstruments(soft.getDefaultSoundbank());
|
||||
|
||||
soft.loadInstrument(generateTestInstrument(new Patch(0, 0)));
|
||||
soft.loadInstrument(generateTestInstrument(new Patch(7, 0)));
|
||||
soft.loadInstrument(generateTestInstrument(new Patch(20, 10)));
|
||||
soft.loadInstrument(generateTestInstrument(new Patch(3678, 15)));
|
||||
soft.loadInstrument(generateTestInstrument(new Patch(4678, 15)));
|
||||
|
||||
testProgramAndBank(soft, stream, new Patch(0, 0));
|
||||
testProgramAndBank(soft, stream, new Patch(7, 0));
|
||||
testProgramAndBank(soft, stream, new Patch(20, 10));
|
||||
testProgramAndBank(soft, stream, new Patch(3678, 15));
|
||||
testProgramAndBank(soft, stream, new Patch(4678, 15));
|
||||
|
||||
soft.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test SoftSynthesizer getAvailableInstruments method */
|
||||
|
||||
import javax.sound.midi.MidiDevice;
|
||||
import javax.sound.midi.MidiUnavailableException;
|
||||
import javax.sound.midi.Patch;
|
||||
import javax.sound.midi.Soundbank;
|
||||
import javax.sound.sampled.*;
|
||||
import javax.sound.midi.MidiDevice.Info;
|
||||
|
||||
import com.sun.media.sound.*;
|
||||
|
||||
public class GetAvailableInstruments2 {
|
||||
|
||||
private static void assertEquals(Object a, Object b) throws Exception {
|
||||
if (!a.equals(b))
|
||||
throw new RuntimeException("assertEquals fails!");
|
||||
}
|
||||
|
||||
private static void assertTrue(boolean value) throws Exception {
|
||||
if (!value)
|
||||
throw new RuntimeException("assertTrue fails!");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AudioSynthesizer synth = new SoftSynthesizer();
|
||||
synth.openStream(null, null);
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if (defsbk != null) {
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
assertTrue(defsbk.getInstruments().length == synth
|
||||
.getAvailableInstruments().length);
|
||||
}
|
||||
synth.close();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test SoftSynthesizer getLoadedInstruments method */
|
||||
|
||||
import javax.sound.midi.MidiDevice;
|
||||
import javax.sound.midi.MidiUnavailableException;
|
||||
import javax.sound.midi.Patch;
|
||||
import javax.sound.midi.Soundbank;
|
||||
import javax.sound.sampled.*;
|
||||
import javax.sound.midi.MidiDevice.Info;
|
||||
|
||||
import com.sun.media.sound.*;
|
||||
|
||||
public class GetLoadedInstruments2 {
|
||||
|
||||
private static void assertEquals(Object a, Object b) throws Exception {
|
||||
if (!a.equals(b))
|
||||
throw new RuntimeException("assertEquals fails!");
|
||||
}
|
||||
|
||||
private static void assertTrue(boolean value) throws Exception {
|
||||
if (!value)
|
||||
throw new RuntimeException("assertTrue fails!");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AudioSynthesizer synth = new SoftSynthesizer();
|
||||
synth.openStream(null, null);
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if (defsbk != null) {
|
||||
assertTrue(defsbk.getInstruments().length == synth
|
||||
.getLoadedInstruments().length);
|
||||
}
|
||||
synth.close();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test SoftSynthesizer getPropertyInfo method */
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sound.midi.MidiDevice;
|
||||
import javax.sound.midi.MidiUnavailableException;
|
||||
import javax.sound.midi.Patch;
|
||||
import javax.sound.midi.Soundbank;
|
||||
import javax.sound.sampled.*;
|
||||
import javax.sound.sampled.AudioFormat.Encoding;
|
||||
import javax.sound.midi.MidiDevice.Info;
|
||||
|
||||
import com.sun.media.sound.*;
|
||||
|
||||
public class GetPropertyInfo {
|
||||
|
||||
private static void assertTrue(boolean value) throws Exception {
|
||||
if (!value)
|
||||
throw new RuntimeException("assertTrue fails!");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SoftSynthesizer synth = new SoftSynthesizer();
|
||||
Map<String, Object> p = new HashMap<String, Object>();
|
||||
p.put("format", "8000 HZ 24 BIT MONO UNSIGNED BIG-ENDIAN");
|
||||
p.put("control rate", 125);
|
||||
p.put("reverb", false);
|
||||
p.put("auto gain control", "false");
|
||||
AudioSynthesizerPropertyInfo[] ap = synth.getPropertyInfo(p);
|
||||
for (int i = 0; i < ap.length; i++) {
|
||||
if (ap[i].name.equals("control rate"))
|
||||
assertTrue(Math.abs((Float) ap[i].value - 125.0) < 0.001);
|
||||
if (ap[i].name.equals("reverb"))
|
||||
assertTrue((Boolean) ap[i].value == false);
|
||||
if (ap[i].name.equals("auto gain control"))
|
||||
assertTrue((Boolean) ap[i].value == false);
|
||||
if (ap[i].name.equals("format")) {
|
||||
AudioFormat format = (AudioFormat) ap[i].value;
|
||||
assertTrue(format.getChannels() == 1);
|
||||
assertTrue(format.getSampleSizeInBits() == 24);
|
||||
assertTrue(format.isBigEndian());
|
||||
assertTrue(Math.abs(format.getSampleRate() - 8000) < 0.001);
|
||||
assertTrue(format.getEncoding() == Encoding.PCM_UNSIGNED);
|
||||
}
|
||||
}
|
||||
p = new HashMap<String, Object>();
|
||||
p.put("format", "9000 Hz, 8 bit, 4 channels");
|
||||
ap = synth.getPropertyInfo(p);
|
||||
for (int i = 0; i < ap.length; i++) {
|
||||
if (ap[i].name.equals("format")) {
|
||||
AudioFormat format = (AudioFormat) ap[i].value;
|
||||
assertTrue(format.getChannels() == 4);
|
||||
assertTrue(format.getSampleSizeInBits() == 8);
|
||||
assertTrue(!format.isBigEndian());
|
||||
assertTrue(Math.abs(format.getSampleRate() - 9000) < 0.001);
|
||||
assertTrue(format.getEncoding() == Encoding.PCM_SIGNED);
|
||||
}
|
||||
}
|
||||
|
||||
p = new HashMap<String, Object>();
|
||||
p.put("format", "PCM_UNSIGNED 44100.0 Hz, 16 bit, 3 channels, 6 bytes/frame, big-endian");
|
||||
ap = synth.getPropertyInfo(p);
|
||||
for (int i = 0; i < ap.length; i++) {
|
||||
if (ap[i].name.equals("format")) {
|
||||
AudioFormat format = (AudioFormat) ap[i].value;
|
||||
assertTrue(format.getChannels() == 3);
|
||||
assertTrue(format.getSampleSizeInBits() == 16);
|
||||
assertTrue(format.isBigEndian());
|
||||
assertTrue(Math.abs(format.getSampleRate() - 44100) < 0.001);
|
||||
assertTrue(format.getEncoding() == Encoding.PCM_UNSIGNED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -55,7 +55,6 @@ public class LoadAllInstruments {
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if(defsbk != null)
|
||||
{
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
SimpleSoundbank sbk = new SimpleSoundbank();
|
||||
SimpleInstrument ins = new SimpleInstrument();
|
||||
|
@ -55,7 +55,6 @@ public class LoadInstrument {
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if(defsbk != null)
|
||||
{
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
SimpleSoundbank sbk = new SimpleSoundbank();
|
||||
SimpleInstrument ins = new SimpleInstrument();
|
||||
|
@ -55,7 +55,6 @@ public class LoadInstruments {
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if(defsbk != null)
|
||||
{
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
SimpleSoundbank sbk = new SimpleSoundbank();
|
||||
SimpleInstrument ins = new SimpleInstrument();
|
||||
|
@ -56,15 +56,15 @@ public class RemapInstrument {
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if(defsbk != null)
|
||||
{
|
||||
Instrument ins0 = defsbk.getInstrument(new Patch(0,0));
|
||||
Instrument ins3 = defsbk.getInstrument(new Patch(0,3));
|
||||
Instrument ins10 = defsbk.getInstrument(new Patch(0,10));
|
||||
assertTrue(synth.remapInstrument(ins0, ins10));
|
||||
assertTrue(synth.remapInstrument(ins3, ins10));
|
||||
Instrument[] loaded = synth.getLoadedInstruments();
|
||||
for (int i = 0; i < loaded.length; i++) {
|
||||
if(loaded[i].getPatch().getBank() == 0)
|
||||
if(loaded[i].getPatch().getProgram() == 10)
|
||||
if(loaded[i].getPatch().getBank() == ins3.getPatch().getBank())
|
||||
if(loaded[i].getPatch().getProgram() == ins3.getPatch().getProgram())
|
||||
{
|
||||
assertEquals(loaded[i].getName(), ins0.getName());
|
||||
assertEquals(loaded[i].getName(), ins10.getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test Disable/enable loading default soundbank in SoftSynthesizer */
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sound.midi.MidiDevice;
|
||||
import javax.sound.midi.MidiUnavailableException;
|
||||
import javax.sound.midi.Patch;
|
||||
import javax.sound.midi.Soundbank;
|
||||
import javax.sound.sampled.*;
|
||||
import javax.sound.midi.MidiDevice.Info;
|
||||
|
||||
import com.sun.media.sound.*;
|
||||
|
||||
public class TestDisableLoadDefaultSoundbank {
|
||||
|
||||
private static void assertEquals(Object a, Object b) throws Exception {
|
||||
if (!a.equals(b))
|
||||
throw new RuntimeException("assertEquals fails!");
|
||||
}
|
||||
|
||||
private static void assertTrue(boolean value) throws Exception {
|
||||
if (!value)
|
||||
throw new RuntimeException("assertTrue fails!");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AudioSynthesizer synth = new SoftSynthesizer();
|
||||
synth.openStream(null, null);
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if (defsbk != null) {
|
||||
assertTrue(defsbk.getInstruments().length == synth
|
||||
.getLoadedInstruments().length);
|
||||
}
|
||||
synth.close();
|
||||
Map<String, Object> p = new HashMap<String, Object>();
|
||||
p.put("load default soundbank", false);
|
||||
synth.openStream(null, p);
|
||||
if (defsbk != null) {
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
}
|
||||
synth.close();
|
||||
|
||||
}
|
||||
}
|
@ -55,9 +55,8 @@ public class UnloadAllInstruments {
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if(defsbk != null)
|
||||
{
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
assertTrue(synth.getAvailableInstruments().length == 0);
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
synth.loadAllInstruments(defsbk);
|
||||
assertTrue(synth.getLoadedInstruments().length != 0);
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
|
@ -55,7 +55,6 @@ public class UnloadInstrument {
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if(defsbk != null)
|
||||
{
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
SimpleSoundbank sbk = new SimpleSoundbank();
|
||||
SimpleInstrument ins = new SimpleInstrument();
|
||||
|
@ -55,7 +55,6 @@ public class UnloadInstruments {
|
||||
Soundbank defsbk = synth.getDefaultSoundbank();
|
||||
if(defsbk != null)
|
||||
{
|
||||
assertTrue(synth.getLoadedInstruments().length == 0);
|
||||
synth.unloadAllInstruments(defsbk);
|
||||
SimpleSoundbank sbk = new SimpleSoundbank();
|
||||
SimpleInstrument ins = new SimpleInstrument();
|
||||
|
250
jdk/test/javax/sound/midi/Gervill/SoftTuning/RealTimeTuning.java
Normal file
250
jdk/test/javax/sound/midi/Gervill/SoftTuning/RealTimeTuning.java
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@summary Test RealTime-tunings using SoftReciver.send method */
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.sound.midi.*;
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
import com.sun.media.sound.*;
|
||||
|
||||
public class RealTimeTuning {
|
||||
|
||||
private static class PitchSpy {
|
||||
public float pitch = 0;
|
||||
|
||||
public Soundbank getSoundBank() {
|
||||
ModelOscillator osc = new ModelOscillator() {
|
||||
public float getAttenuation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getChannels() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ModelOscillatorStream open(float samplerate) {
|
||||
return new ModelOscillatorStream() {
|
||||
public void close() throws IOException {
|
||||
pitch = 0;
|
||||
}
|
||||
|
||||
public void noteOff(int velocity) {
|
||||
pitch = 0;
|
||||
}
|
||||
|
||||
public void noteOn(MidiChannel channel,
|
||||
VoiceStatus voice, int noteNumber, int velocity) {
|
||||
pitch = noteNumber * 100;
|
||||
}
|
||||
|
||||
public int read(float[][] buffer, int offset, int len)
|
||||
throws IOException {
|
||||
return len;
|
||||
}
|
||||
|
||||
public void setPitch(float ipitch) {
|
||||
pitch = ipitch;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
ModelPerformer performer = new ModelPerformer();
|
||||
performer.getOscillators().add(osc);
|
||||
SimpleInstrument testinstrument = new SimpleInstrument();
|
||||
testinstrument.setPatch(new Patch(0, 0));
|
||||
testinstrument.add(performer);
|
||||
SimpleSoundbank testsoundbank = new SimpleSoundbank();
|
||||
testsoundbank.addInstrument(testinstrument);
|
||||
return testsoundbank;
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendTuningChange(Receiver recv, int channel,
|
||||
int tuningpreset, int tuningbank) throws InvalidMidiDataException {
|
||||
// Data Entry
|
||||
ShortMessage sm1 = new ShortMessage();
|
||||
sm1.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 04);
|
||||
ShortMessage sm2 = new ShortMessage();
|
||||
sm2.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
|
||||
|
||||
// Tuning Bank
|
||||
ShortMessage sm3 = new ShortMessage();
|
||||
sm3.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06, tuningbank);
|
||||
// Data Increment
|
||||
ShortMessage sm4 = new ShortMessage();
|
||||
sm4.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
|
||||
// Data Decrement
|
||||
ShortMessage sm5 = new ShortMessage();
|
||||
sm5.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
|
||||
|
||||
// Data Entry
|
||||
ShortMessage sm6 = new ShortMessage();
|
||||
sm6.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 03);
|
||||
ShortMessage sm7 = new ShortMessage();
|
||||
sm7.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
|
||||
|
||||
// Tuning program
|
||||
ShortMessage sm8 = new ShortMessage();
|
||||
sm8
|
||||
.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06,
|
||||
tuningpreset);
|
||||
// Data Increment
|
||||
ShortMessage sm9 = new ShortMessage();
|
||||
sm9.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
|
||||
// Data Decrement
|
||||
ShortMessage sm10 = new ShortMessage();
|
||||
sm10.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
|
||||
|
||||
recv.send(sm1, -1);
|
||||
recv.send(sm2, -1);
|
||||
recv.send(sm3, -1);
|
||||
recv.send(sm4, -1);
|
||||
recv.send(sm5, -1);
|
||||
recv.send(sm6, -1);
|
||||
recv.send(sm7, -1);
|
||||
recv.send(sm8, -1);
|
||||
recv.send(sm9, -1);
|
||||
recv.send(sm10, -1);
|
||||
|
||||
}
|
||||
|
||||
private static void assertTrue(boolean value) throws Exception {
|
||||
if (!value)
|
||||
throw new RuntimeException("assertTrue fails!");
|
||||
}
|
||||
|
||||
public static void testTunings(int[] msg, int tuningProgram,
|
||||
int tuningBank, int targetNote, float targetPitch, boolean realtime)
|
||||
throws Exception {
|
||||
AudioSynthesizer synth = new SoftSynthesizer();
|
||||
AudioInputStream stream = synth.openStream(null, null);
|
||||
Receiver recv = synth.getReceiver();
|
||||
MidiChannel channel = synth.getChannels()[0];
|
||||
byte[] buff = new byte[2048];
|
||||
|
||||
// Create test instrument which we can use to monitor pitch changes
|
||||
PitchSpy pitchspy = new PitchSpy();
|
||||
|
||||
synth.unloadAllInstruments(synth.getDefaultSoundbank());
|
||||
synth.loadAllInstruments(pitchspy.getSoundBank());
|
||||
|
||||
SysexMessage sysex = null;
|
||||
|
||||
// Send tuning changes
|
||||
if (msg != null) {
|
||||
byte[] bmsg = new byte[msg.length];
|
||||
for (int i = 0; i < bmsg.length; i++)
|
||||
bmsg[i] = (byte) msg[i];
|
||||
sysex = new SysexMessage();
|
||||
sysex.setMessage(bmsg, bmsg.length);
|
||||
if (targetPitch == 0) {
|
||||
targetPitch = (float) new SoftTuning(bmsg)
|
||||
.getTuning(targetNote);
|
||||
// Check if targetPitch != targetNote * 100
|
||||
assertTrue(Math.abs(targetPitch - targetNote * 100.0) > 0.001);
|
||||
}
|
||||
}
|
||||
|
||||
if (tuningProgram != -1)
|
||||
sendTuningChange(recv, 0, tuningProgram, tuningBank);
|
||||
|
||||
// First test without tunings
|
||||
channel.noteOn(targetNote, 64);
|
||||
stream.read(buff, 0, buff.length);
|
||||
assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
|
||||
|
||||
// Test if realtime/non-realtime works
|
||||
if (sysex != null)
|
||||
recv.send(sysex, -1);
|
||||
stream.read(buff, 0, buff.length);
|
||||
if (realtime)
|
||||
assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
|
||||
else
|
||||
assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
|
||||
|
||||
// Test if tunings works
|
||||
channel.noteOn(targetNote, 0);
|
||||
stream.read(buff, 0, buff.length);
|
||||
assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
|
||||
|
||||
channel.noteOn(targetNote, 64);
|
||||
stream.read(buff, 0, buff.length);
|
||||
assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
|
||||
|
||||
channel.noteOn(targetNote, 0);
|
||||
stream.read(buff, 0, buff.length);
|
||||
assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
|
||||
|
||||
stream.close();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Test with no-tunings
|
||||
testTunings(null, -1, -1, 60, 6000, false);
|
||||
|
||||
int[] msg;
|
||||
// 0x02 SINGLE NOTE TUNING CHANGE (REAL-TIME)
|
||||
msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x02, 0x10, 0x02, 36, 36, 64,
|
||||
0, 60, 70, 0, 0, 0xf7 };
|
||||
testTunings(msg, 0x10, 0, 60, 7000, true);
|
||||
|
||||
// 0x07 SINGLE NOTE TUNING CHANGE (NON REAL-TIME) (BANK)
|
||||
msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
|
||||
36, 64, 0, 60, 80, 0, 0, 0xf7 };
|
||||
testTunings(msg, 0x07, 0x05, 60, 8000, false);
|
||||
|
||||
// 0x07 SINGLE NOTE TUNING CHANGE (REAL-TIME) (BANK)
|
||||
msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
|
||||
36, 64, 0, 60, 80, 0, 0, 0xf7 };
|
||||
testTunings(msg, 0x07, 0x05, 60, 8000, true);
|
||||
|
||||
// 0x08 scale/octave tuning 1-byte form (Non Real-Time)
|
||||
msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
|
||||
10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
|
||||
testTunings(msg, -1, -1, 60, 0, false);
|
||||
|
||||
// 0x08 scale/octave tuning 1-byte form (REAL-TIME)
|
||||
msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
|
||||
10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
|
||||
testTunings(msg, -1, -1, 60, 0, true);
|
||||
|
||||
// 0x09 scale/octave tuning 2-byte form (Non Real-Time)
|
||||
msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
|
||||
10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
|
||||
30, 35, 40, 45, 50, 51, 52, 0xf7 };
|
||||
testTunings(msg, -1, -1, 60, 0, false);
|
||||
|
||||
// 0x09 scale/octave tuning 2-byte form (REAL-TIME)
|
||||
msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
|
||||
10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
|
||||
30, 35, 40, 45, 50, 51, 52, 0xf7 };
|
||||
testTunings(msg, -1, -1, 60, 0, true);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6944033
|
||||
* @summary Tests that PCM_FLOAT encoding is supported
|
||||
* @compile -source 1.7 PCM_FLOAT_support.java
|
||||
* @run main PCM_FLOAT_support
|
||||
* @author Alex Menkov
|
||||
*
|
||||
*/
|
||||
|
||||
import javax.sound.sampled.AudioFormat.Encoding;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
|
||||
|
||||
public class PCM_FLOAT_support {
|
||||
|
||||
static Encoding pcmFloatEnc;
|
||||
|
||||
static boolean testFailed = false;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// 1st checks Encoding.PCM_FLOAT is available
|
||||
pcmFloatEnc = Encoding.PCM_FLOAT;
|
||||
|
||||
Encoding[] encodings = AudioSystem.getTargetEncodings(pcmFloatEnc);
|
||||
out("conversion from PCM_FLOAT to " + encodings.length + " encodings:");
|
||||
for (Encoding e: encodings) {
|
||||
out(" - " + e);
|
||||
}
|
||||
if (encodings.length == 0) {
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
test(Encoding.PCM_SIGNED);
|
||||
test(Encoding.PCM_UNSIGNED);
|
||||
|
||||
if (testFailed) {
|
||||
throw new Exception("test failed");
|
||||
}
|
||||
out("test passed.");
|
||||
}
|
||||
|
||||
static void out(String s) {
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
static boolean test(Encoding enc) {
|
||||
out("conversion " + enc + " -> PCM_FLOAT:");
|
||||
Encoding[] encodings = AudioSystem.getTargetEncodings(enc);
|
||||
for (Encoding e: encodings) {
|
||||
if (e.equals(pcmFloatEnc)) {
|
||||
out(" - OK");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
out(" - FAILED (not supported)");
|
||||
testFailed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user