4 * License : The MIT License
\r
5 * Copyright(c) 2009 olyutorskii
\r
8 package jp.sourceforge.jindolf;
\r
10 import java.io.File;
\r
11 import java.lang.reflect.InvocationTargetException;
\r
12 import java.lang.reflect.Method;
\r
13 import java.lang.reflect.Modifier;
\r
14 import java.net.URI;
\r
15 import java.net.URISyntaxException;
\r
16 import java.net.URL;
\r
17 import java.security.CodeSource;
\r
18 import java.security.ProtectionDomain;
\r
19 import java.util.Locale;
\r
23 * JRE1.6 API へのリフレクションアクセスを含む。
\r
25 public final class FileUtils{
\r
27 private static final String SCHEME_FILE = "file";
\r
29 /** JRE1.6のjava.io.File#setReadableに相当。 */
\r
30 private static final Method METHOD_SETREADABLE;
\r
31 /** JRE1.6のjava.io.File#setWritableに相当。 */
\r
32 private static final Method METHOD_SETWRITABLE;
\r
33 /** Locale.ROOT代替品。 */
\r
34 private static final Locale ROOT = new Locale("", "", "");
\r
41 method = File.class.getMethod(
\r
42 "setReadable", Boolean.TYPE, Boolean.TYPE);
\r
43 modifiers = method.getModifiers();
\r
44 if( ! Modifier.isPublic(modifiers) ){
\r
47 }catch(NoSuchMethodException e){
\r
49 }catch(SecurityException e){
\r
52 METHOD_SETREADABLE = method;
\r
55 method = File.class.getMethod(
\r
56 "setWritable", Boolean.TYPE, Boolean.TYPE);
\r
57 modifiers = method.getModifiers();
\r
58 if( ! Modifier.isPublic(modifiers) ){
\r
61 }catch(NoSuchMethodException e){
\r
63 }catch(SecurityException e){
\r
66 METHOD_SETWRITABLE = method;
\r
68 assert ! ( isMacOSXFs() && isWindowsOSFs() );
\r
75 private FileUtils(){
\r
77 throw new AssertionError();
\r
82 * なるべく自分にだけ許可を与え自分以外には許可を与えないように
\r
84 * @param method setReadableかsetWritableのいずれかのメソッド。
\r
86 * @param file 操作対象のファイル。
\r
88 * @throws SecurityException セキュリティ上の許可が無い場合
\r
90 private static boolean invokeOwnerOnly(Method method, File file)
\r
91 throws SecurityException{
\r
92 if(method == null) return false;
\r
93 if(file == null) throw new NullPointerException();
\r
98 result1 = method.invoke(file, false, false);
\r
99 result2 = method.invoke(file, true, true);
\r
100 }catch(IllegalAccessException e){
\r
103 }catch(IllegalArgumentException e){
\r
106 }catch(ExceptionInInitializerError e){
\r
109 }catch(InvocationTargetException e){
\r
110 Throwable cause = e.getCause();
\r
111 if(cause instanceof SecurityException){
\r
112 throw (SecurityException) cause;
\r
113 }else if(cause instanceof RuntimeException){
\r
114 throw (RuntimeException) cause;
\r
115 }else if(cause instanceof Error){
\r
116 throw (Error) cause;
\r
123 assert result1 instanceof Boolean;
\r
124 assert result2 instanceof Boolean;
\r
125 Boolean bresult1 = (Boolean) result1;
\r
126 Boolean bresult2 = (Boolean) result2;
\r
128 return bresult1 && bresult2;
\r
132 * なるべく自分にだけ読み書き許可を与え
\r
133 * 自分以外には読み書き許可を与えないように
\r
135 * JRE1.6環境でなければなにもしない。
\r
136 * @param file 操作対象ファイル
\r
137 * @return 成功すればtrue
\r
138 * @throws SecurityException セキュリティ上の許可が無い場合
\r
140 public static boolean setOwnerOnlyAccess(File file)
\r
141 throws SecurityException{
\r
142 boolean readresult = invokeOwnerOnly(METHOD_SETREADABLE, file);
\r
143 boolean writeresult = invokeOwnerOnly(METHOD_SETWRITABLE, file);
\r
144 return readresult & writeresult;
\r
148 * 任意の絶対パスの祖先の内、存在するもっとも近い祖先を返す。
\r
149 * @param file 任意の絶対パス
\r
150 * @return 存在するもっとも近い祖先。一つも存在しなければnull。
\r
151 * @throws IllegalArgumentException 引数が絶対パスでない
\r
153 public static File findExistsAncestor(File file)
\r
154 throws IllegalArgumentException{
\r
155 if(file == null) return null;
\r
156 if( ! file.isAbsolute() ) throw new IllegalArgumentException();
\r
157 if(file.exists()) return file;
\r
158 File parent = file.getParentFile();
\r
159 return findExistsAncestor(parent);
\r
163 * 任意の絶対パスのルートファイルシステムもしくはドライブレターを返す。
\r
164 * @param file 任意の絶対パス
\r
165 * @return ルートファイルシステムもしくはドライブレター
\r
166 * @throws IllegalArgumentException 引数が絶対パスでない
\r
168 public static File findRootFile(File file)
\r
169 throws IllegalArgumentException{
\r
170 if( ! file.isAbsolute() ) throw new IllegalArgumentException();
\r
171 File parent = file.getParentFile();
\r
172 if(parent == null) return file;
\r
173 return findRootFile(parent);
\r
179 * @return 絶対パス。絶対化に失敗した場合は元の引数。
\r
181 public static File supplyFullPath(File file){
\r
182 if(file.isAbsolute()) return file;
\r
187 absFile = file.getAbsoluteFile();
\r
188 }catch(SecurityException e){
\r
196 * 任意のディレクトリがアクセス可能な状態にあるか判定する。
\r
197 * アクセス可能の条件を満たすためには、与えられたパスが
\r
203 * @param path 任意のディレクトリ
\r
204 * @return アクセス可能ならtrue
\r
206 public static boolean isAccessibleDirectory(File path){
\r
207 if(path == null) return false;
\r
209 if( ! path.exists() ) return false;
\r
210 if( ! path.isDirectory() ) return false;
\r
211 if( ! path.canRead() ) return false;
\r
212 if( ! path.canWrite() ) return false;
\r
218 * クラスがローカルファイルからロードされたのであれば
\r
220 * @param klass 任意のクラス
\r
221 * @return ロード元ファイル。見つからなければnull。
\r
223 public static File getClassSourceFile(Class<?> klass){
\r
224 ProtectionDomain domain;
\r
226 domain = klass.getProtectionDomain();
\r
227 }catch(SecurityException e){
\r
231 CodeSource src = domain.getCodeSource();
\r
233 URL location = src.getLocation();
\r
234 String scheme = location.getProtocol();
\r
235 if( ! scheme.equals(SCHEME_FILE) ) return null;
\r
239 uri = location.toURI();
\r
240 }catch(URISyntaxException e){
\r
245 File file = new File(uri);
\r
251 * すでに存在するJARファイルか判定する。
\r
252 * @param file 任意のファイル
\r
253 * @return すでに存在するJARファイルであればtrue
\r
255 public static boolean isExistsJarFile(File file){
\r
256 if(file == null) return false;
\r
257 if( ! file.exists() ) return false;
\r
258 if( ! file.isFile() ) return false;
\r
260 String name = file.getName();
\r
261 if( ! name.matches("^.+\\.[jJ][aA][rR]$") ) return false;
\r
263 // TODO ファイル先頭マジックナンバーのテストも必要?
\r
269 * クラスがローカルJARファイルからロードされたのであれば
\r
271 * @param klass 任意のクラス
\r
272 * @return ロード元JARファイルの格納ディレクトリ。
\r
273 * JARが見つからない、もしくはロード元がJARファイルでなければnull。
\r
275 public static File getJarDirectory(Class<?> klass){
\r
276 File jarFile = getClassSourceFile(klass);
\r
277 if(jarFile == null) return null;
\r
279 if( ! isExistsJarFile(jarFile) ){
\r
283 return jarFile.getParentFile();
\r
288 * システムプロパティuser.homeで示されたホームディレクトリを返す。
\r
289 * @return ホームディレクトリ。何らかの事情でnullを返す場合もあり。
\r
291 public static File getHomeDirectory(){
\r
294 homeProp = System.getProperty("user.home");
\r
295 }catch(SecurityException e){
\r
299 File homeFile = new File(homeProp);
\r
306 * @return MacOSX環境ならtrue
\r
308 public static boolean isMacOSXFs(){
\r
309 if(File.separatorChar != '/') return false;
\r
313 osName = System.getProperty("os.name");
\r
314 }catch(SecurityException e){
\r
318 if(osName == null) return false;
\r
320 osName = osName.toLowerCase(ROOT);
\r
322 if(osName.startsWith("mac os x")){
\r
330 * Windows環境か否か判定する。
\r
331 * @return Windows環境ならtrue
\r
333 public static boolean isWindowsOSFs(){
\r
334 if(File.separatorChar != '\\') return false;
\r
338 osName = System.getProperty("os.name");
\r
339 }catch(SecurityException e){
\r
343 if(osName == null) return false;
\r
345 osName = osName.toLowerCase(ROOT);
\r
347 if(osName.startsWith("windows")){
\r
355 * アプリケーション設定ディレクトリを返す。
\r
356 * 存在の有無、アクセスの可否は関知しない。
\r
357 * @return アプリケーション設定ディレクトリ
\r
359 public static File getAppSetDir(){
\r
360 File home = getHomeDirectory();
\r
361 if(home == null) return null;
\r
363 File result = home;
\r
366 result = new File(result, "Library");
\r
367 result = new File(result, "Application Support");
\r
370 // TODO Win環境での%APPDATA%サポート
\r
376 * ファイル名を表示するためのJLabel用HTML文字列を生成する。
\r
377 * Windows日本語環境では、バックスラッシュ記号が円通貨記号に置換される。
\r
378 * @param file 対象ファイル
\r
379 * @return HTML文字列断片
\r
381 public static String getHtmledFileName(File file){
\r
382 String pathName = file.getPath();
\r
384 Locale locale = Locale.getDefault();
\r
385 String lang = locale.getLanguage();
\r
387 if( FileUtils.isWindowsOSFs() && lang.equals("ja") ){
\r
388 pathName = pathName.replace(File.separator, "¥");
\r
391 return "<code>" + pathName + "</code>";
\r