001: /*
002:
003: Derby - Class org.apache.derbyTesting.functionTests.tests.i18n.MessageBundleTest
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derbyTesting.functionTests.tests.i18n;
023:
024: import org.apache.derbyTesting.junit.BaseTestCase;
025: import org.apache.derby.shared.common.reference.SQLState;
026: import org.apache.derby.shared.common.reference.MessageId;
027:
028: import java.util.HashSet;
029: import java.lang.reflect.Field;
030: import java.util.ResourceBundle;
031: import java.util.Locale;
032: import java.util.Iterator;
033:
034: /**
035: * This class does everything we can to validate that the messages_en.properties
036: * file is in synch with SQLState.java and MessageId.java. We want to make sure
037: * that message ids defined in SQLState and MessageId have matching messages
038: * in the messages properties file, and also find out if there are any messages
039: * that don't have matching ids in the SQLState and MessageId files. The
040: * first is a bug, the second is something to be aware of.
041: */
042: public class MessageBundleTest extends BaseTestCase {
043: public MessageBundleTest(String name) {
044: super (name);
045: }
046:
047: // The list of ids. We use a HashSet so we can detect duplicates easily
048: static HashSet sqlStateIds = new HashSet();
049: static HashSet messageIdIds = new HashSet();
050: static HashSet messageBundleIds = new HashSet();
051:
052: static {
053: try {
054: // Load all the ids for the SQLState class
055: loadClassIds(SQLState.class, sqlStateIds);
056:
057: // Load all the ids for the MessageId class
058: loadClassIds(MessageId.class, messageIdIds);
059:
060: // Load all the ids for the messages_en properties file
061: loadMessageBundleIds();
062: } catch (Exception e) {
063: e.printStackTrace();
064: throw new RuntimeException(e.getMessage());
065: }
066: }
067:
068: static void loadClassIds(Class idclass, HashSet set)
069: throws Exception {
070: Field[] fields = idclass.getFields();
071:
072: int length = fields.length;
073: for (int i = 0; i < length; i++) {
074: String id = (String) fields[i].get(null);
075:
076: if (id.length() == 2) {
077: // Skip past identifiers that are just categories
078: continue;
079: }
080:
081: // Skip past "special" SQL States that are not expected
082: // to have messages
083: if (id.equals("close.C.1"))
084: continue;
085: if (id.equals("rwupd"))
086: continue;
087: if (id.equals("02502"))
088: continue;
089: if (id.equals("XSAX0"))
090: continue;
091:
092: if (!set.add(id)) {
093: System.err.println("ERROR: The id " + id
094: + " was found twice in " + idclass.getName());
095: }
096: }
097: }
098:
099: /**
100: * Load all the message ids from messages_en.properties into a HashSet.
101: * This assumes its available on the classpath
102: */
103: static void loadMessageBundleIds() throws Exception {
104: ResourceBundle bundle;
105:
106: // The messages_*.properties files are split into fifty separate
107: // message bundle files. We need to load each one in turn
108: int numBundles = 50;
109:
110: for (int i = 0; i < numBundles; i++) {
111: loadMessageBundle(i);
112: }
113: }
114:
115: static void loadMessageBundle(int index) {
116: String bundleName = "org.apache.derby.loc.m" + index;
117:
118: ResourceBundle bundle = ResourceBundle.getBundle(bundleName,
119: Locale.ENGLISH);
120:
121: java.util.Enumeration keys = bundle.getKeys();
122:
123: while (keys.hasMoreElements()) {
124: String key = (String) keys.nextElement();
125:
126: if (!messageBundleIds.add(key)) {
127: System.err.println("ERROR: the key " + key
128: + " exists twice in messages_en.properties");
129: }
130: }
131: }
132:
133: /**
134: * See if there are any message ids in SQLState.java that are
135: * not in the message bundle
136: */
137: public void testSQLStateOrphanedIds() throws Exception {
138: Iterator it = sqlStateIds.iterator();
139:
140: while (it.hasNext()) {
141: String sqlStateId = (String) it.next();
142:
143: if (!messageBundleIds.contains(sqlStateId)) {
144: // Don't fail out on the first one, we want to catch
145: // all of them. Just note there was a failure and continue
146: System.err.println("ERROR: Message id " + sqlStateId
147: + " in SQLState.java was not found in"
148: + " messages_en.properties");
149: }
150: }
151: }
152:
153: /**
154: * See if there are any message ids in MessageId.java not in
155: * the message bundle
156: */
157: public void testMessageIdOrphanedIds() throws Exception {
158: Iterator it = messageIdIds.iterator();
159:
160: while (it.hasNext()) {
161: String sqlStateId = (String) it.next();
162:
163: if (!messageBundleIds.contains(sqlStateId)) {
164: // Don't fail out on the first one, we want to catch
165: // all of them. Just note there was a failure and continue
166: System.err.println("ERROR: Message id " + sqlStateId
167: + " in MessageId.java was not found in"
168: + " messages_en.properties");
169: }
170: }
171: }
172:
173: /**
174: * See if there are any message ids in the message bundle that
175: * are <b>not</b> in SQLState.java or MessageId.java
176: */
177: public void testMessageBundleOrphanedMessages() throws Exception {
178: Iterator it = messageBundleIds.iterator();
179:
180: while (it.hasNext()) {
181: String msgid = (String) it.next();
182:
183: if (sqlStateIds.contains(msgid)) {
184: continue;
185: }
186:
187: if (messageIdIds.contains(msgid)) {
188: continue;
189: }
190:
191: // Don't fail out on the first one, we want to catch
192: // all of them. Just note there was a failure and continue
193: System.err
194: .println("WARNING: Message id "
195: + msgid
196: + " in messages_en.properties is not "
197: + "referenced in either SQLState.java or MessageId.java");
198: }
199: }
200: }
|