This commit is contained in:
Alex Menkov 2010-09-14 14:09:26 +04:00
commit bf0670e111
80 changed files with 8910 additions and 789 deletions

View File

@ -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 \

View File

@ -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);
}

View File

@ -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();

View File

@ -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();

View File

@ -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));
}

View File

@ -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.

View File

@ -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);

View File

@ -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)

View File

@ -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() {

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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));
}

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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,

View File

@ -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.");
}

View File

@ -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>
*/

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}
/**

View File

@ -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;
}
/**

View File

@ -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

View File

@ -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&#xE5;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();

View File

@ -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()}.

View File

@ -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.

View File

@ -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.
*/

View File

@ -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");
}
}
}

View File

@ -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;
}
/**

View File

@ -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

View 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;
}
}
}

View 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);
}
}
}

View 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();
}
}

View 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());
}
}
}

View 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();
}
}

View 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);
}
}

View 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;
}
}
}

View File

@ -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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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
}
}
}

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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;

View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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);
}
}
}

View 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.
*/
/* @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] + ")");
}
}
}

View File

@ -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();
}
}
}

View File

@ -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()])
);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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();

View 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);
}
}

View File

@ -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;
}
}