2 * Copyright (c) 2003-2005 The BISON Project
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 package peersim.config;
23 import java.util.zip.*;
26 * Provides static methods to obtain the package-qualified class name
27 * of a class, given just the non-qualified name, and to obtain
28 * the non-qualified name, given the package-qualified class name.
30 * Inspired from some code written by David Postill (david@postill.org.uk)
31 * (found in http://groups.google.com).
34 * @author Alberto Montresor
35 * @version $Revision: 1.9 $
40 //--------------------------------------------------------------------------
41 //Fields and initialization
42 //--------------------------------------------------------------------------
45 /** Local map containing the associations */
46 private static Map<String,String> map = new TreeMap<String,String>();
48 /** The number of directories that have been touched by the search.
49 This does not include directories in jar files. */
50 private static int visitedDirs = 0;
52 private static final int maxDirs;
60 } catch (IOException e) {
64 if(visitedDirs >= maxDirs )
66 System.err.println("Configuration: some directories in your "+
67 "classpath probably contain filesystem\nConfiguration: "+
68 "loops because the number of visited directories "+
69 "reached "+maxDirs+".\nConfiguration: This means automatic "+
70 "class lookup might fail and you might have\nConfiguration: "+
71 "to fully qualify class names in the configuration.");
76 //--------------------------------------------------------------------------
77 //Public static methods
78 //--------------------------------------------------------------------------
81 * Returns the non-qualified name of a class, removing all the package
84 public static String getShortName(String className) {
86 int index = className.lastIndexOf('.');
90 return className.substring(index+1);
95 * Returns the package-qualified name associated to the specified
96 * non-qualified name, if exists. Otherwise it returns null.
98 * Only classes reachable from the classpath defined by the
99 * "java.class.path" property are considered.
100 * Jar files and directories are both parsed.
101 * If multiple classes with the same name but different
102 * fully-qualified names are present, a comma-separated list
103 * of fully-qualified class names is returned.
105 * @param name the non-qualified name of the class to be searched
106 * @return the qualified name, if exists.
108 public static String getQualifiedName(String name)
110 return map.get(name);
113 //--------------------------------------------------------------------------
114 //Private static methods
115 //--------------------------------------------------------------------------
118 * Finds all the classes reachable from the current classpath;
119 * for each of them, inserts an association (name, fully-qualified
120 * name) in the specified map. Both names are String objects.
122 * Only classes reachable from the classpath defined by the
123 * "java.class.path" property are considered.
124 * Jar files and directories are both parsed.
125 * If multiple classes with the same name but different
126 * fully-qualified names are present, they are inserted
127 * in the map as associations (name, comma-separated list of
128 * fully-qualified names).
131 * @throws IOException
133 private static void findClasses(Map<String,String> map)
136 String classPath = System.getProperty( "java.class.path" );
137 String separator = System.getProperty( "path.separator" );
138 String filesep = System.getProperty( "file.separator");
139 StringTokenizer path = new StringTokenizer( classPath, separator );
141 while( path.hasMoreTokens() ) {
143 String pathElement = path.nextToken();
144 File pathFile = new File( pathElement );
146 if( pathFile.isDirectory() ) {
147 if (!pathElement.endsWith(filesep)) {
148 pathElement = pathElement + filesep;
149 pathFile = new File( pathElement);
151 findClassInPathDir( map, pathElement, pathFile );
152 // Search directories
153 } else if ( pathFile.exists() ) {
154 findClassInJar( map, pathFile);
159 //--------------------------------------------------------------------------
164 * @param map the map where to insert associations
165 * @param pathFile the file name of the associated jar file
166 * @throws IOException
168 private static void findClassInJar(Map<String,String> map, File pathFile)
171 ZipFile zipFile = new ZipFile( pathFile );
172 Enumeration entries = zipFile.entries();
173 while( entries.hasMoreElements() ) {
175 String entry = entries.nextElement().toString();
176 if( entry.endsWith( ".class" ) ) {
177 // File names in ZIP archives (so, also in JARs)
178 // are separated by forward slashes '/', independently
179 // of the architecture.
180 String className = classname( entry, "/" );
181 String shortName = getShortName( className );
182 if (map.containsKey(shortName)) {
184 map.get(shortName)+","+className);
186 map.put(shortName, className);
192 //--------------------------------------------------------------------------
195 * Recursively parses directories.
197 * @param map the map where to insert associations
198 * @param pathElement the path string used for recursion
199 * @param pathFile the file (directory) to be analyzed
200 * @throws IOException
202 private static void findClassInPathDir( Map<String,String> map,
203 String pathElement, File pathFile )
207 if(visitedDirs>=maxDirs) return;
209 String[] list = pathFile.list();
210 String filesep = System.getProperty( "file.separator");
212 for( int i = 0; i < list.length; i++ ) {
213 File file = new File( pathFile, list[i] );
214 if( file.isDirectory() ) {
215 findClassInPathDir( map, pathElement, file );
217 else if ( file.exists() && (file.length() != 0) && list[i].endsWith( ".class" ) ) {
218 String classFile = file.toString().substring( pathElement.length());
219 String className = classname( classFile, filesep );
220 String shortName = getShortName( className );
221 if (map.containsKey(shortName)) {
222 map.put(shortName, map.get(shortName)+","+className);
224 map.put(shortName, className);
230 //--------------------------------------------------------------------------
233 * Translates a class file name in a class name using
234 * the specified file separator.
236 private static String classname(String classFile, String filesep)
238 return classFile.replace( filesep, "." ).substring(
239 0, classFile.length() - ".class".length() );
242 //--------------------------------------------------------------------------
249 public static void main( String[] argv )
251 Iterator i = map.keySet().iterator();
252 while (i.hasNext()) {
253 String key = (String) i.next();
254 String name = map.get(key);
255 System.out.println(key + " --> " + name);