OSDN Git Service

mainエントリのパッケージを変更。
[jindolf/Jindolf.git] / src / main / java / jp / sfjp / jindolf / dxchg / WebIPC.java
1 /*
2  * Inter Process Communication with Web browser
3  *
4  * License : The MIT License
5  * Copyright(c) 2009 olyutorskii
6  */
7
8 package jp.sfjp.jindolf.dxchg;
9
10 import java.awt.GraphicsEnvironment;
11 import java.awt.HeadlessException;
12 import java.io.IOException;
13 import java.lang.reflect.Field;
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import java.net.URI;
17
18 /**
19  * Webブラウザとのプロセス間通信。
20  * java.awt.Desktopの代用品。
21  * JRE1.6でしか使えない。がしかし、JRE1.5でもコンパイル&ロード可能。
22  * ※参照: java.awt.Desktop
23  */
24 public final class WebIPC{
25
26     private static final Class<?> DESKTOP_KLASS;
27     private static final Method   METHOD_ISDESKTOPSUPPORTED;
28     private static final Method   METHOD_GETDESKTOP;
29     private static final Method   METHOD_ISSUPPORTED;
30     private static final Method   METHOD_BROWSE;
31
32     private static final Class<?> DESKTOP_ACTION_KLASS;
33     private static final Enum<?>  BROWSE_ENUM;
34
35     static{
36         DESKTOP_KLASS       = getClass("java.awt.Desktop");
37         DESKTOP_ACTION_KLASS = getInnerClass(DESKTOP_KLASS,
38                                            "java.awt.Desktop.Action");
39
40         METHOD_ISDESKTOPSUPPORTED = getMethod("isDesktopSupported");
41         METHOD_GETDESKTOP         = getMethod("getDesktop");
42         METHOD_ISSUPPORTED        = getMethod("isSupported",
43                                              DESKTOP_ACTION_KLASS);
44         METHOD_BROWSE             = getMethod("browse",
45                                              URI.class);
46
47         BROWSE_ENUM = getEnumMember(DESKTOP_ACTION_KLASS, "BROWSE");
48     }
49
50
51     private final Object desktop;
52
53
54     /**
55      * 見えないコンストラクタ。
56      * @throws HeadlessException GUI環境が未接続
57      * @throws UnsupportedOperationException 未サポート
58      */
59     private WebIPC()
60             throws HeadlessException,
61                    UnsupportedOperationException {
62         super();
63
64         try{
65             this.desktop = METHOD_GETDESKTOP.invoke(null, (Object[]) null);
66         }catch(InvocationTargetException e){
67             Throwable targetException = e.getTargetException();
68
69             if(targetException instanceof RuntimeException){
70                 throw (RuntimeException) targetException;
71             }
72             if(targetException instanceof Error){
73                 throw (Error) targetException;
74             }
75
76             AssertionError thw = new AssertionError();
77             thw.initCause(e);
78             throw thw;
79         }catch(IllegalAccessException e){
80             AssertionError thw = new AssertionError();
81             thw.initCause(e);
82             throw thw;
83         }
84
85         return;
86     }
87
88
89     /**
90      * クラス名からClassインスタンスを探す。
91      * @param klassName クラス名
92      * @return Classインスタンス。クラスが見つからなければnull。
93      */
94     private static Class<?> getClass(String klassName){
95         Class<?> result;
96         try{
97             result = Class.forName(klassName);
98         }catch(ClassNotFoundException e){
99             result = null;
100         }
101         return result;
102     }
103
104     /**
105      * 内部クラス名からClassインスタンスを探す。
106      * @param parent 囲む親クラス。
107      * @param canonical 内部クラスのカノニカル名
108      * @return Classインスタンス。クラスが見つからなければnull。
109      */
110     private static Class<?> getInnerClass(Class<?> parent,
111                                             String canonical){
112         if(parent == null) return null;
113
114         Class<?> result = null;
115
116         Class<?>[] innerKlasses = parent.getClasses();
117         for(Class<?> klass : innerKlasses){
118             if(klass.getCanonicalName().equals(canonical)){
119                 result = klass;
120                 break;
121             }
122         }
123
124         return result;
125     }
126
127     /**
128      * Desktopクラスのメソッド名からMethodインスタンスを探す。
129      * @param methodName メソッド名
130      * @param paramTypes 引数型並び
131      * @return Methodインスタンス。見つからなければnull。
132      */
133     private static Method getMethod(String methodName,
134                                      Class<?>... paramTypes){
135         if(DESKTOP_KLASS == null) return null;
136
137         Method result;
138
139         try{
140             result = DESKTOP_KLASS.getMethod(methodName, paramTypes);
141         }catch(NoSuchMethodException e){
142             result = null;
143         }
144
145         return result;
146     }
147
148     /**
149      * Enumのメンバを探す。
150      * @param parent Enumの型
151      * @param memberName メンバ名
152      * @return Enumインスタンス。見つからなければnull。
153      */
154     private static Enum<?> getEnumMember(Class<?> parent,
155                                            String memberName){
156         if(parent == null) return null;
157
158         Field field;
159         try{
160             field = parent.getField(memberName);
161         }catch(NoSuchFieldException e){
162             return null;
163         }
164
165         Object value;
166         try{
167             value = field.get(null);
168         }catch(IllegalAccessException e){
169             return null;
170         }catch(IllegalArgumentException e){
171             return null;
172         }
173
174         if( ! (value instanceof Enum) ) return null;
175
176         return (Enum<?>) value;
177     }
178
179     /**
180      * JRE1.6より提供されたjava.awt.Desktopが利用可能か判定する。
181      * ※参照: java.awt.DesktopのisDesktopSupported()
182      * @return Desktopが利用可能ならtrue。JRE1.5以前だとたぶんfalse。
183      */
184     public static boolean isDesktopSupported(){
185         if(METHOD_ISDESKTOPSUPPORTED == null) return false;
186
187         Object invokeResult;
188         try{
189             invokeResult = METHOD_ISDESKTOPSUPPORTED.invoke(null,
190                                                             (Object[]) null);
191         }catch(InvocationTargetException e){
192             Throwable targetException = e.getTargetException();
193
194             if(targetException instanceof RuntimeException){
195                 throw (RuntimeException) targetException;
196             }else if(targetException instanceof Error){
197                 throw (Error) targetException;
198             }
199
200             AssertionError thw = new AssertionError();
201             thw.initCause(e);
202             throw thw;
203         }catch(IllegalAccessException e){
204             AssertionError thw = new AssertionError();
205             thw.initCause(e);
206             throw thw;
207         }
208
209         if( ! (invokeResult instanceof Boolean) ){
210             assert false;
211             return false;
212         }
213
214         boolean result = (Boolean) invokeResult;
215
216         return result;
217     }
218
219     /**
220      * WebIPCインスタンスを得る。
221      * ※参照: java.awt.DesktopのgetDesktop()
222      * @return インスタンス
223      * @throws java.awt.HeadlessException スクリーンデバイスが見つからない
224      * @throws java.lang.UnsupportedOperationException 未サポートの機能
225      */
226     public static WebIPC getWebIPC()
227             throws HeadlessException,
228                    UnsupportedOperationException {
229         if(GraphicsEnvironment.isHeadless()) throw new HeadlessException();
230         if( ! isDesktopSupported() ){
231             throw new UnsupportedOperationException();
232         }
233
234         WebIPC webIPC = new WebIPC();
235
236         return webIPC;
237     }
238
239     /**
240      * Webブラウザに任意のURIを表示させる。
241      * ※参照: java.awt.Desktopのbrowse(java.net.URI)
242      * @param uri URI
243      * @throws NullPointerException 引数がnull
244      * @throws UnsupportedOperationException 未サポートの機能
245      * @throws IOException ブラウザが見つからない
246      * @throws SecurityException セキュリティ違反
247      * @throws IllegalArgumentException URI形式が変
248      */
249     public void browse(URI uri)
250             throws NullPointerException,
251                    UnsupportedOperationException,
252                    IOException,
253                    SecurityException,
254                    IllegalArgumentException {
255         if(uri == null) throw new NullPointerException();
256         if( ! isSupported(Action.BROWSE) ){
257             throw new UnsupportedOperationException();
258         }
259
260         try{
261             METHOD_BROWSE.invoke(this.desktop, uri);
262         }catch(InvocationTargetException e){
263             Throwable targetException = e.getTargetException();
264
265             if(targetException instanceof IOException){
266                 throw (IOException) targetException;
267             }
268             if(targetException instanceof RuntimeException){
269                 throw (RuntimeException) targetException;
270             }
271             if(targetException instanceof Error){
272                 throw (Error) targetException;
273             }
274
275             AssertionError thw = new AssertionError();
276             thw.initCause(e);
277             throw thw;
278         }catch(IllegalAccessException e){
279             AssertionError thw = new AssertionError();
280             thw.initCause(e);
281             throw thw;
282         }
283
284         return;
285     }
286
287     /**
288      * 指定した機能(アクション)がサポートされているか否か判定する。
289      * ※参照: java.awt.Desktop#isSupported(java.awt.Desktop.Action)
290      * @param action アクション
291      * @return アクションがサポートされていればtrue。
292      */
293     public boolean isSupported(Action action){
294         switch(action){
295         case BROWSE:
296             break;
297         default:
298             return false;
299         }
300
301         Object invokeResult;
302         try{
303             invokeResult = METHOD_ISSUPPORTED.invoke(this.desktop,
304                                                      BROWSE_ENUM);
305         }catch(InvocationTargetException e){
306             Throwable targetException = e.getTargetException();
307
308             if(targetException instanceof RuntimeException){
309                 throw (RuntimeException) targetException;
310             }
311             if(targetException instanceof Error){
312                 throw (Error) targetException;
313             }
314
315             AssertionError thw = new AssertionError();
316             thw.initCause(e);
317             throw thw;
318         }catch(IllegalAccessException e){
319             AssertionError thw = new AssertionError();
320             thw.initCause(e);
321             throw thw;
322         }
323
324         if( ! (invokeResult instanceof Boolean) ){
325             assert false;
326             return false;
327         }
328
329         boolean result = (Boolean) invokeResult;
330
331         return result;
332     }
333
334     /**
335      * 各種デスクトップアクション。
336      * ※参照 java.awt.Desktop.Action
337      */
338     public static enum Action{
339         /** Webブラウザでのブラウズ。 */
340         BROWSE,
341     //  EDIT,
342     //  MAIL,
343     //  OPEN,
344     //  PRINT,
345     }
346
347 }