4 * License : The MIT License
5 * Copyright(c) 2011 olyutorskii
8 package jp.sfjp.jindolf;
10 import java.awt.Frame;
11 import java.io.PrintStream;
12 import javax.swing.JOptionPane;
18 * JREに含まれるjava.langパッケージ仕様のバージョンは互換性があるものとする。
20 * <p>なるべく昔のJREでも動くように。
21 * 少なくとも1.2以降。できれば1.0以降。
22 * 原則、1.3以降の新設ライブラリは利用禁止。
24 * <p>なるべく昔のコンパイラでもコンパイルできるように。
25 * 少なくとも1.2以降。できれば1.0以降。
26 * 原則、assert文、総称ジェネリクス、アノテーションは禁止。
28 * <p>できればBasic-Latinに入らない文字(日本語)の出力も禁止。
30 * <p>ランタイム存在検査用のクラスは、ロードや初期化が軽いほうが望ましい。
31 * そしていずれJindolfの実行に必要なものであるのが望ましい。
33 * Jindolfに関係ないクラスの連鎖ロードが起きにくいほうが望ましい。
35 public final class JreChecker {
37 /** Jindolfが実行時に必要とするJREの版。 */
38 public static final String REQUIRED_JRE_VER = "1.7";
41 public static final int EXIT_CODE_INCOMPAT_JRE = 1;
43 private static final PrintStream STDERR = System.err;
45 private static final String DIALOG_TITLE =
46 "JRE Incompatibility detected...";
48 private static final int MAX_LINE = 40;
49 private static final int DEF_LINES = 5;
50 private static final int INIT_SBUF = 100;
56 * <p><code>assert false;</code> 書きたいけど書いちゃだめ。
65 * クラス名に相当するクラスがロードできるか判定する。
66 * @param klassName FQDNなクラス名
69 public static boolean hasClass(String klassName){
73 Class.forName(klassName); // 1.2Laterな3引数版メソッドは利用禁止
75 }catch(ClassNotFoundException e){
83 * JRE 1.1 相当のランタイムライブラリが提供されているか判定する。
84 * @return 提供されているならtrue
85 * @see java.io.Serializable
87 public static boolean has11Runtime(){
88 boolean result = hasClass("java.io.Serializable");
93 * JRE 1.2 相当のランタイムライブラリが提供されているか判定する。
94 * @return 提供されているならtrue
95 * @see java.util.Iterator
97 public static boolean has12Runtime(){
99 if(has11Runtime()) result = hasClass("java.util.Iterator");
105 * JRE 1.3 相当のランタイムライブラリが提供されているか判定する。
106 * @return 提供されているならtrue
107 * @see java.util.TimerTask
109 public static boolean has13Runtime(){
111 if(has12Runtime()) result = hasClass("java.util.TimerTask");
117 * JRE 1.4 相当のランタイムライブラリが提供されているか判定する。
118 * @return 提供されているならtrue
119 * @see java.lang.CharSequence
121 public static boolean has14Runtime(){
123 if(has13Runtime()) result = hasClass("java.lang.CharSequence");
129 * JRE 1.5 相当のランタイムライブラリが提供されているか判定する。
130 * @return 提供されているならtrue
131 * @see java.lang.Appendable
133 public static boolean has15Runtime(){
135 if(has14Runtime()) result = hasClass("java.lang.Appendable");
141 * JRE 1.6 相当のランタイムライブラリが提供されているか判定する。
142 * @return 提供されているならtrue
143 * @see java.util.Deque
145 public static boolean has16Runtime(){
147 if(has15Runtime()) result = hasClass("java.util.Deque");
153 * JRE 1.7 相当のランタイムライブラリが提供されているか判定する。
154 * @return 提供されているならtrue
155 * @see java.lang.AutoCloseable
157 public static boolean has17Runtime(){
159 if(has16Runtime()) result = hasClass("java.lang.AutoCloseable");
167 * JREもしくは<code>java.lang</code>パッケージの
170 * <li>システムプロパティ<code>java.specification.version</code>
171 * <li>システムプロパティ<code>java.version</code>
172 * <li><code>java.lang</code>パッケージの仕様バージョン
173 * </ol>の順でバージョンが求められる。
174 * @return 仕様バージョン文字列。不明ならnull
176 public static String getLangPkgSpec(){
180 result = System.getProperty("java.specification.version");
181 }catch(SecurityException e){
184 if(result != null) return result;
187 result = System.getProperty("java.version");
188 }catch(SecurityException e){
191 if(result != null) return result;
193 Package javaLangPkg = java.lang.Object.class.getPackage();
194 if(javaLangPkg == null) return null;
196 result = javaLangPkg.getSpecificationVersion();
202 * システムプロパティ<code>java.home</code>の取得が試みられる。
203 * @return インストール情報。不明ならnull
205 public static String getJreHome(){
209 result = System.getProperty("java.home");
210 }catch(SecurityException e){
221 public static String buildErrMessage(){
222 // このクラスではStringBuilder禁止
223 StringBuffer message = new StringBuffer(INIT_SBUF);
225 message.append("ERROR : Java JRE ")
226 .append(REQUIRED_JRE_VER)
227 .append(" compatible or later required.");
229 String specVer = getLangPkgSpec();
231 message.append("\nbut\u0020")
233 .append("\u0020detected.");
236 String jreHome = getJreHome();
238 message.append(" [ ")
243 return message.toString();
247 * 指定された文字数で行の長さを改行文字で揃える。
252 * @param limit 行ごとの最大文字数
255 public static String alignLine(String text, int limit){
256 // このクラスではStringBuilder禁止
257 int textLength = text.length();
258 StringBuffer message = new StringBuffer(textLength + DEF_LINES);
262 for(int idx = 0; idx < textLength; idx++){
263 if(lineLength >= limit){
264 message.append('\n');
268 char ch = text.charAt(idx);
271 if(ch == '\n') lineLength = 0;
275 String result = message.toString();
280 * JRE環境をチェックする。(JRE1.7)
282 * <p>もしJREの非互換性が検出されたらエラーメッセージを報告する。
284 * @return 互換性があれば0、無ければ非0
286 public static int checkJre(){
287 if(has17Runtime()) return 0;
289 String message = buildErrMessage();
290 STDERR.println(message);
293 showErrorDialog(message);
296 return EXIT_CODE_INCOMPAT_JRE;
300 * Swingダイアログでエラーを報告する。
302 * <p>ボタンを押すまでの間、実行はブロックされる。
304 * <p>GUIに接続できなければ何か例外を投げるかもしれない。
308 public static void showErrorDialog(String text){
309 String aligned = alignLine(text, MAX_LINE);
312 JOptionPane.showMessageDialog(
314 aligned, DIALOG_TITLE,
315 JOptionPane.ERROR_MESSAGE );