001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.openide.util;
043:
044: import java.io.ByteArrayInputStream;
045: import java.io.ByteArrayOutputStream;
046: import java.io.IOException;
047: import java.io.InputStream;
048: import java.net.MalformedURLException;
049: import java.net.URL;
050: import java.net.URLConnection;
051: import java.net.URLStreamHandler;
052: import java.util.ArrayList;
053: import java.util.Collections;
054: import java.util.HashMap;
055: import java.util.Iterator;
056: import java.util.List;
057: import java.util.Locale;
058: import java.util.Map;
059: import java.util.MissingResourceException;
060: import java.util.Properties;
061: import java.util.ResourceBundle;
062: import java.util.TreeMap;
063: import java.util.jar.Attributes;
064: import junit.framework.TestCase;
065:
066: // XXX testGetClassBundle
067: // XXX testGetLocalizedFile
068: // XXX testDebugLoader
069:
070: /**
071: * Test normal-mode functionality of {@link NbBundle}.
072: * @author Jesse Glick
073: */
074: public class NbBundleTest extends TestCase {
075:
076: public NbBundleTest(String name) {
077: super (name);
078: }
079:
080: protected void setUp() throws Exception {
081: Locale.setDefault(Locale.US);
082: NbBundle.setBranding(null);
083: NbBundle.localizedFileCache.clear();
084: NbBundle.bundleCache.clear();
085: }
086:
087: public static void testLocalizingSuffixes() throws Exception {
088: assertEquals("_en_US,_en,", locSuff());
089: Locale.setDefault(Locale.JAPAN);
090: assertEquals("_ja_JP,_ja,", locSuff());
091: NbBundle.setBranding("f4j_ce");
092: Locale.setDefault(Locale.US);
093: assertEquals(
094: "_f4j_ce_en_US,_f4j_ce_en,_f4j_ce,_f4j_en_US,_f4j_en,_f4j,_en_US,_en,",
095: locSuff());
096: Locale.setDefault(Locale.JAPAN);
097: assertEquals(
098: "_f4j_ce_ja_JP,_f4j_ce_ja,_f4j_ce,_f4j_ja_JP,_f4j_ja,_f4j,_ja_JP,_ja,",
099: locSuff());
100: }
101:
102: private static String locSuff() {
103: StringBuffer b = new StringBuffer();
104: boolean first = true;
105: Iterator<String> it = NbBundle.getLocalizingSuffixes();
106: while (it.hasNext()) {
107: if (first) {
108: first = false;
109: } else {
110: b.append(',');
111: }
112: b.append(it.next());
113: }
114: return b.toString();
115: }
116:
117: public void testGetBundle() throws Exception {
118: ResourceBundle rb = NbBundle.getBundle("foo.Bundle",
119: Locale.ENGLISH,
120: fixedLoader("foo/Bundle.properties:k=v"));
121: assertEquals("v", rb.getString("k"));
122: try {
123: rb.getString("kkk");
124: fail();
125: } catch (MissingResourceException mre) {
126: // OK
127: }
128: rb = NbBundle.getBundle("foo.Bundle", Locale.US,
129: fixedLoader("foo/Bundle.properties:k=v"));
130: assertEquals("v", rb.getString("k"));
131: rb = NbBundle.getBundle("foo.Bundle", Locale.JAPAN,
132: fixedLoader("foo/Bundle.properties:k=v"));
133: assertEquals("v", rb.getString("k"));
134: rb = NbBundle.getBundle("foo.Bundle", Locale.JAPAN,
135: fixedLoader("foo/Bundle.properties:k=v",
136: "foo/Bundle_ja.properties:k=v2"));
137: assertEquals("v2", rb.getString("k"));
138: assertEquals(Locale.JAPAN, rb.getLocale());
139: try {
140: NbBundle.getBundle("foo.Bundle", Locale.ENGLISH,
141: fixedLoader());
142: fail();
143: } catch (MissingResourceException mre) {
144: // OK
145: }
146: NbBundle.setBranding("nb");
147: rb = NbBundle.getBundle("foo.Bundle", Locale.US, fixedLoader(
148: "foo/Bundle.properties:k1=v1\nk2=v2",
149: "foo/Bundle_nb.properties:k1=v1 NB"));
150: assertEquals("v1 NB", rb.getString("k1"));
151: assertEquals("v2", rb.getString("k2"));
152: List<String> keys = new ArrayList<String>(Collections.list(rb
153: .getKeys()));
154: Collections.sort(keys);
155: assertEquals("[k1, k2]", keys.toString());
156: }
157:
158: public void testGetMessage() throws Exception {
159: ClassLoader l = fixedLoader(
160: "org/openide/util/Bundle.properties:k1=v1\nk2=v2 {0}",
161: "org/openide/util/Bundle_ja.properties:k1=v1 ja");
162: Class<?> c = l.loadClass(Dummy.class.getName());
163: assertEquals(l, c.getClassLoader());
164: assertEquals("v1", NbBundle.getMessage(c, "k1"));
165: Locale.setDefault(Locale.JAPAN);
166: assertEquals("v1 ja", NbBundle.getMessage(c, "k1"));
167: assertEquals("v2 x", NbBundle.getMessage(c, "k2", "x"));
168: }
169:
170: static class Dummy {
171: }
172:
173: /**
174: * Creates a loader which can load just fixed resources you supply.
175: * Each entry should be of the form
176: * <pre>
177: * path/to/res1:some contents
178: * for res1
179: * </pre>
180: * Resources are expected to be in ISO-8859-1.
181: * Also can define a class named Dummy.class.getName().
182: */
183: private static ClassLoader fixedLoader(String... entries)
184: throws Exception {
185: final Map<String, byte[]> data = new HashMap<String, byte[]>();
186: for (String entry : entries) {
187: int colon = entry.indexOf(':');
188: data.put(entry.substring(0, colon), entry.substring(
189: colon + 1).getBytes("ISO-8859-1"));
190: }
191: return new ClassLoader() {
192: @Override
193: public URL getResource(final String res) {
194: if (data.containsKey(res)) {
195: //System.err.println("hit for " + res);
196: try {
197: return new URL("dummy", null, 0, res,
198: new URLStreamHandler() {
199: protected URLConnection openConnection(
200: URL u) throws IOException {
201: return new URLConnection(u) {
202: public void connect()
203: throws IOException {
204: }
205:
206: @Override
207: public InputStream getInputStream()
208: throws IOException {
209: return new ByteArrayInputStream(
210: data.get(res));
211: }
212: };
213: }
214: });
215: } catch (MalformedURLException x) {
216: throw new AssertionError(x);
217: }
218: } else {
219: //System.err.println("miss for " + res);
220: return null;
221: }
222: }
223:
224: @Override
225: public Class loadClass(String n)
226: throws ClassNotFoundException {
227: if (n.equals(Dummy.class.getName())) {
228: InputStream is = NbBundleTest.class
229: .getClassLoader().getResourceAsStream(
230: n.replace('.', '/') + ".class");
231: ByteArrayOutputStream baos = new ByteArrayOutputStream();
232: byte[] buf = new byte[4096];
233: int read;
234: try {
235: while ((read = is.read(buf)) != -1) {
236: baos.write(buf, 0, read);
237: }
238: } catch (IOException x) {
239: throw new AssertionError(x);
240: }
241: return defineClass(n, baos.toByteArray(), 0, baos
242: .size());
243: } else {
244: return super .loadClass(n);
245: }
246: }
247: };
248: }
249:
250: public static void testGetLocalizedValue() throws Exception {
251: Map<String, String> m = new HashMap<String, String>();
252: m.put("k1", "v1");
253: m.put("k1_ja", "v1_ja");
254: m.put("k1_ja_JP", "v1_ja_JP");
255: m.put("k2", "v2");
256: m.put("k3_ja", "v3_ja");
257: assertEquals("v1", NbBundle.getLocalizedValue(m, "k1",
258: Locale.ENGLISH));
259: assertEquals("v1_ja", NbBundle.getLocalizedValue(m, "k1",
260: Locale.JAPANESE));
261: assertEquals("v1_ja_JP", NbBundle.getLocalizedValue(m, "k1",
262: Locale.JAPAN));
263: assertEquals("v2", NbBundle.getLocalizedValue(m, "k2",
264: Locale.ENGLISH));
265: assertEquals("v2", NbBundle.getLocalizedValue(m, "k2",
266: Locale.JAPANESE));
267: assertEquals("v2", NbBundle.getLocalizedValue(m, "k2",
268: Locale.JAPAN));
269: assertEquals(null, NbBundle.getLocalizedValue(m, "k3",
270: Locale.ENGLISH));
271: assertEquals("v3_ja", NbBundle.getLocalizedValue(m, "k3",
272: Locale.JAPANESE));
273: assertEquals("v3_ja", NbBundle.getLocalizedValue(m, "k3",
274: Locale.JAPAN));
275: Attributes attr = new Attributes();
276: attr.putValue("k1", "v1");
277: attr.putValue("k1_ja", "v1_ja");
278: attr.putValue("k1_ja_JP", "v1_ja_JP");
279: attr.putValue("k2", "v2");
280: attr.putValue("k3_ja", "v3_ja");
281: assertEquals("v1", NbBundle.getLocalizedValue(attr,
282: new Attributes.Name("k1"), Locale.ENGLISH));
283: assertEquals("v1_ja", NbBundle.getLocalizedValue(attr,
284: new Attributes.Name("k1"), Locale.JAPANESE));
285: assertEquals("v1_ja_JP", NbBundle.getLocalizedValue(attr,
286: new Attributes.Name("k1"), Locale.JAPAN));
287: assertEquals("v2", NbBundle.getLocalizedValue(attr,
288: new Attributes.Name("k2"), Locale.ENGLISH));
289: assertEquals("v2", NbBundle.getLocalizedValue(attr,
290: new Attributes.Name("k2"), Locale.JAPANESE));
291: assertEquals("v2", NbBundle.getLocalizedValue(attr,
292: new Attributes.Name("k2"), Locale.JAPAN));
293: assertEquals(null, NbBundle.getLocalizedValue(attr,
294: new Attributes.Name("k3"), Locale.ENGLISH));
295: assertEquals("v3_ja", NbBundle.getLocalizedValue(attr,
296: new Attributes.Name("k3"), Locale.JAPANESE));
297: assertEquals("v3_ja", NbBundle.getLocalizedValue(attr,
298: new Attributes.Name("k3"), Locale.JAPAN));
299: attr = new Attributes();
300: attr.putValue("Think", "Smart");
301: assertEquals("think", "THINK".toLowerCase());
302: assertEquals("Smart", NbBundle.getLocalizedValue(attr,
303: new Attributes.Name("think")));
304: assertEquals("Smart", NbBundle.getLocalizedValue(attr,
305: new Attributes.Name("THINK")));
306: Locale.setDefault(new Locale("tr", "TR"));
307: assertEquals("th\u0131nk", "THINK".toLowerCase());
308: assertEquals("Smart", NbBundle.getLocalizedValue(attr,
309: new Attributes.Name("think")));
310: assertEquals("Smart", NbBundle.getLocalizedValue(attr,
311: new Attributes.Name("THINK")));
312: }
313:
314: /** @see "#57815" */
315: public static void testSystemClassLoaderLoadedClasses()
316: throws Exception {
317: assertNotNull("OK to ask for message from class on app CP",
318: NbBundle.getMessage(NbBundle.class,
319: "OpenIDE-Module-Name"));
320: try {
321: NbBundle.getMessage(Object.class, "whatever");
322: fail();
323: } catch (MissingResourceException x) {
324: // OK
325: }
326: }
327:
328: public void testDebugInputStream() throws Exception {
329: assertEquals("basic annotation works", "{key=val (17:1)}",
330: debugIS("key=val\n", true));
331: assertEquals("annotation disabled unless loc", "{key=val}",
332: debugIS("key=val\n", false));
333: assertEquals("comments ignored", "{key=val (17:2)}", debugIS(
334: "# some comment\nkey=val\n", true));
335: assertEquals("simple multiline values handled",
336: "{k1=vee one (17:1)}",
337: debugIS("k1=vee \\\none\n", true));
338: assertEquals("whitespace starting cont lines ignored",
339: "{k1=vee one (17:1)}", debugIS("k1=vee \\\n one\n",
340: true));
341: assertEquals("whitespace around key ignored", "{k1=v1 (17:1)}",
342: debugIS(" k1 =v1\n", true));
343: assertEquals("whitespace before value ignored",
344: "{k1=v1 (17:1)}", debugIS("k1= v1\n", true));
345: assertEquals("whitespace after value significant",
346: "{k1=v1 (17:1)}", debugIS("k1=v1 \n", true));
347: assertEquals("trailing newline not required", "{k1=v1 (17:1)}",
348: debugIS("k1=v1", true));
349: assertEquals(
350: "complex case",
351: "{k1=vee one (17:1), k2=vee two (17:3)}",
352: debugIS(
353: " k1 = vee \\\n one\n k2 = vee \\\n two ",
354: true));
355: assertEquals("NOI18N works", "{k1=v1}", debugIS(
356: "#NOI18N\nk1=v1\n", true));
357: assertEquals("I18N works", "{k1=v1 (17:2)}", debugIS(
358: "#I18N\nk1=v1\n", false));
359: // XXX \ in key
360: // XXX #PART{,NO}I18N
361: // XXX Unicode escapes
362: // XXX ':' rather than '='
363: // XXX \r\n
364: // XXX key with no value, or empty value
365: // XXX value beginning with \
366: }
367:
368: private static String debugIS(String s, boolean loc)
369: throws IOException {
370: InputStream dis = new NbBundle.DebugLoader.DebugInputStream(
371: new ByteArrayInputStream(s.getBytes("ISO-8859-1")), 17,
372: loc);
373: ByteArrayOutputStream baos = new ByteArrayOutputStream();
374: byte[] buf = new byte[4096];
375: int read;
376: while ((read = dis.read(buf)) != -1) {
377: baos.write(buf, 0, read);
378: }
379: Properties p = new Properties();
380: p.load(new ByteArrayInputStream(baos.toByteArray()));
381: return new TreeMap<String, String>(
382: NbCollections.checkedMapByFilter(p, String.class,
383: String.class, true)).toString();
384: }
385:
386: }
|