001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.fukurou.util;
017
018 import java.io.IOException;
019 import java.io.File;
020
021 import java.util.List;
022 import java.util.ArrayList;
023 import java.util.Enumeration;
024 import java.util.jar.JarFile;
025 import java.util.jar.JarEntry;
026 import java.net.URL;
027
028 /**
029 * こã?クラスは、指定ã?ãƒ?‚£レクトリパスから .class ファイルを検索するクラスですã?
030 * 検索パスは、実ファイルと、zipファイルのå†?ƒ¨、jar ファイルのå†?ƒ¨も含みますã?
031 * 検索結果はã€?class を取り除きã?ファイルパスをã?すべてドッãƒ?.)に変換した形式にしますã?
032 * これは、ほとんどクラスのフルパスæ–?—å?に相当しますã?
033 * ここで取得されたファイル名よりã?実クラスオブジェクトã?作æ?が可能になりますã?
034 *
035 * こã?クラスの main メソãƒ?ƒ‰は、クラスパスからæŒ?®šã?名前を持つクラス以下ã?ãƒ?‚£レクトリより
036 * ファイルを検索しますã?通常、このクラスの使ã�?–¹として、取得したクラスファイルå�?æ–?—å?)
037 * から、引数なしコンストラクタを呼び出して、実オブジェクトを生æ?させるã?でã€??常のフォルãƒ?
038 * から検索するより、クラスパスå†?�‹ら検索するペã?スが多いため、サンプルをそのように設å®?
039 * してã�?�¾すã?
040 *
041 * @og.rev 4.0.0.0 (2004/12/31) 新規作æ?
042 * @og.group 初期åŒ?
043 *
044 * @version 4.0
045 * @author Kazuhiko Hasegawa
046 * @since JDK5.0,
047 */
048 public final class FindClassFiles {
049 private final List<String> list = new ArrayList<String>();
050 private final int baseLen;
051
052 private static final String SUFIX = ".class" ;
053 private static final int SUFIX_LEN = SUFIX.length();
054
055 /**
056 * 検索パスを指定して構築するã?コンストラクタですã?
057 * ここで見つかったパス以下ã? classファイル(拡張子ã?小文字でã€?class )を検索しますã?
058 * こã?ファイル名ã? ファイルパスã‚?ドッãƒ?.)に置き換えã?.class を取り除ã�?�Ÿ格納しておきますã?
059 *
060 * ※ Tomcat8.0.3 では、ClassLoader の getResources(String)で取得するURL名がã€?
061 * /C:/opengionV6/uap/webapps/gf/WEB-INF/classes/org/opengion/plugin/
062 * の形式で、最後ã? "/" を取る為、filepath.length() - 1 処ç�?�—てã�?�¾したがã?
063 * Tomcat8.0.5 ではã€?C:/opengionV6/uap/webapps/gf/WEB-INF/classes/org/opengion/plugin
064 * の形式で、最後ã? "/" がなくなってã�?�¾すã?
065 * æœ?¾Œã? "/" があってもなくてもã?new File(String) でãƒ?‚£レクトリのオブジェクトを
066 * 作æ?できるため、filepath.length() に変更しますã?
067 *
068 * @og.rev 4.0.3.0 (2007/01/07) UNIXパス検索時ã?、ファイルパスの取得方法ã?不å?合対å¿?
069 * @og.rev 5.0.0.0 (2009/08/03) UNIXパス検索時ã?、ファイルパスの取得方法ã?不å?合対å¿?
070 * @og.rev 5.0.0.0 (2009/08/03) UNIXパス検索時ã?、ファイルパスの取得方法ã?不å?合対å¿?
071 * @og.rev 5.7.5.0 (2014/04/04) ファイル名ã?取得方法ã?修正
072 *
073 * @param filepath 対象となるファイル群を検索する、ファイルパス
074 * @param keyword 検索対象ファイルのキーワーãƒ?
075 */
076 // public FindClassFiles( final String filepath,final String prefix ) {
077 public FindClassFiles( final String filepath,final String keyword ) {
078 // jar:file:/実ディレクトリ!先é?クラス またã?、file:/実ディレクトリ またã?ã€?実ディレクトリ
079
080 // String dir = null;
081 String dir = filepath; // 5.5.2.6 (2012/05/25) findbugs対å¿?
082 if( filepath.startsWith( "jar:" ) || filepath.startsWith( "file:" )
083 // || ( filepath.charAt(0) == '/' && filepath.charAt(2) == ':' ) ) {
084 || ( filepath.charAt(0) == '/' ) ) { // 4.4.0.0 (2009/08/02)
085 int stAdrs = filepath.indexOf( '/' );
086 if( filepath.charAt(stAdrs+2) == ':' ) { // 4.0.3.0 (2007/01/07)
087 stAdrs++;
088 }
089 int edAdrs = filepath.lastIndexOf( '!' );
090 if( edAdrs < 0) {
091 // edAdrs = filepath.length() - 1;
092 edAdrs = filepath.length(); // 5.7.5.0 (2014/04/04) æœ?¾Œã? "/" はあってもなくてもよã�??
093 }
094 dir = filepath.substring( stAdrs,edAdrs );
095 }
096
097 File basefile = new File( dir );
098 String baseFilename = basefile.getAbsolutePath() ;
099 // baseLen = baseFilename.length() - prefix.length();
100 baseLen = baseFilename.length() - keyword.length();
101 findFilename( basefile );
102 }
103
104 /**
105 * ファイルパスã‚?ドッãƒ?.)に置き換えã?.class を取り除ã�?�Ÿ形å¼?クラスの完å?系)のæ–?—å?配å?
106 *
107 * @return ファイルパスのæ–?—å?配å?
108 */
109 public String[] getFilenames() {
110 return list.toArray( new String[list.size()] );
111 }
112
113 /**
114 * ファイルをå?帰çš?�«検索しますã?
115 * æŒ?®šã?ファイルオブジェクトが ファイルの場合ã?ã€?class であればListに追åŠ?�—ã€?
116 * .zip ã�?.jar では、findJarFiles を呼び出しますã?
117 * ファイルでなã�??合ã?ã€??列を取り出しã?自åˆ??身をå?帰çš?�«呼び出しますã?
118 *
119 * @param file ファイル
120 */
121 private void findFilename( final File file ) {
122 if( file.isFile() ) {
123 String name = file.getAbsolutePath();
124 if( name.endsWith( SUFIX ) ) {
125 list.add( name.substring( baseLen,name.length()-SUFIX_LEN ).replace( File.separatorChar,'.' ) );
126 }
127 else if( name.endsWith( ".jar" ) || name.endsWith( ".zip" ) ) {
128 findJarFiles( name );
129 }
130 }
131 else {
132 File[] filelist = file.listFiles();
133 for( int i=0; i<filelist.length; i++ ) {
134 findFilename( filelist[i] );
135 }
136 }
137 }
138
139 /**
140 * jar/zipファイルを検索しますã?
141 * 圧縮ファイルではã€?šŽ層ではなくã?Enumeration としてファイルを取りå?しますã?
142 * 拡張子で判断して、Listに追åŠ?�—てã�?��ますã?
143 *
144 * @og.rev 5.5.2.6 (2012/05/25) JarFile をã?Closer#zipClose( ZipFile ) メソãƒ?ƒ‰を利用して、close しますã?
145 *
146 * @param filename ファイルå�?
147 */
148 private void findJarFiles( final String filename ) {
149 // 5.5.2.6 (2012/05/25) findbugs対å¿?
150 JarFile jarFile = null;
151 try {
152 // JarFile jarFile = new JarFile( filename );
153 jarFile = new JarFile( filename );
154 Enumeration<JarEntry> en = jarFile.entries() ;
155 while( en.hasMoreElements() ) {
156 JarEntry ent = en.nextElement();
157 if( ! ent.isDirectory() ) {
158 String name = ent.getName();
159 if( name.endsWith( SUFIX ) ) {
160 list.add( name.substring( 0,name.length()-SUFIX_LEN ).replace( '/','.' ) );
161 }
162 }
163 }
164 }
165 catch( IOException ex ) {
166 String errMsg = "ファイル読み取りストリーãƒ?�«失敗しましたã€?
167 + " File=" + filename
168 + ex.getMessage(); // 5.1.8.0 (2010/07/01) errMsg 修正
169 throw new RuntimeException( errMsg,ex );
170 }
171 // 5.5.2.6 (2012/05/25) findbugs対å¿?
172 finally {
173 Closer.zipClose( jarFile );
174 }
175 }
176
177 /**
178 * サンプルメイン
179 * ここでは、引数に通常のファイルではなくã?クラスパスより取得しますã?
180 * 通常、取得されたファイル名ã?、クラスの完å?系のæ–?—å?なので、クラスパスより取å¾?
181 * してã�?‚‹限り、そのまま オブジェクトを構築できることを意味しますã?
182 *
183 * @param args 引数
184 */
185 public static void main( final String[] args ) {
186 try {
187 ClassLoader loader = Thread.currentThread().getContextClassLoader();
188 Enumeration<URL> enume = loader.getResources( args[0] ); // 4.3.3.6 (2008/11/15) Generics警告対å¿?
189 while( enume.hasMoreElements() ) {
190 URL url = enume.nextElement(); // 4.3.3.6 (2008/11/15) Generics警告対å¿?
191 // jar:file:/実ディレクトリ!先é?クラス またã?、file:/実ディレクトリ
192 System.out.println( "url=" + url.getFile() );
193
194 FindClassFiles filenames = new FindClassFiles( url.getFile(),args[0] );
195 String[] names = filenames.getFilenames();
196 for( int i=0; i<names.length; i++ ) {
197 System.out.println( names[i] );
198 }
199 }
200 }
201 catch( IOException ex ) {
202 String errMsg = "ファイル読み取りストリーãƒ?�«失敗しましたã€?
203 + ex.getMessage();
204 throw new RuntimeException( errMsg,ex );
205 }
206 }
207 }