001: package com.bm.ejb3metadata.finder;
002:
003: import java.io.File;
004: import java.io.FileInputStream;
005: import java.io.FileNotFoundException;
006: import java.io.IOException;
007: import java.io.InputStream;
008: import java.net.URL;
009: import java.util.ArrayList;
010: import java.util.HashSet;
011: import java.util.List;
012: import java.util.Set;
013:
014: import org.apache.log4j.Logger;
015:
016: import com.bm.ejb3metadata.utils.MetadataUtils;
017: import com.bm.utils.Ejb3Utils;
018:
019: /**
020: * This class discover implementations for interfaces. The current implementation
021: * takes "is happy" with one possible impelmentation. If a interface has two
022: * implementations itīs currently not defined which one if going to be returned
023: *
024: * @author Daniel Wiese
025: * @since 13.11.2005
026: */
027: public class ClassFinder {
028:
029: private static final Logger log = Logger
030: .getLogger(ClassFinder.class);
031:
032: private final Set<String> allClasses = new HashSet<String>();
033:
034: private boolean isInitailized = false;
035:
036: /**
037: * Searches all classes in a given directory (up to top lever and from there
038: * recursive) of in a given jar file.
039: *
040: * @param firstSearchClue -
041: * the location of this class will be used as a hint , where to
042: * start with the search
043: * @return - a list of classes (format: com/siemens/MyClass)
044: */
045: public List<String> getListOfClasses(Class firstSearchClue) {
046: if (!isInitailized) {
047: this .init(firstSearchClue.getName());
048: }
049: return new ArrayList<String>(allClasses);
050: }
051:
052: /**
053: * Searches all classer in a given directory (up to top lever and from there
054: * recursive) of in a given jar file.
055: *
056: * @param firstSearchClue
057: * @return
058: */
059: public List<String> getListOfClasses(String firstSearchClue) {
060: if (!isInitailized) {
061: this .init(firstSearchClue);
062: }
063: return new ArrayList<String>(allClasses);
064: }
065:
066: private void init(String toFind) {
067: // Translate the package name into an absolute path
068: boolean isLoadInJar = false;
069: String name = toFind.replace('.', '/');
070: URL loc = getClass().getResource("/" + name + ".class");
071: File f = new File(Ejb3Utils.getDecodedFilename(loc));
072: // Class file is inside a jar file.
073: if (f.getPath().startsWith("file:")) {
074: String s = f.getPath();
075: int index = s.indexOf('!');
076: // It confirm it is a jar file
077: if (index != -1) {
078: isLoadInJar = true;
079: }
080: }
081:
082: if (!isLoadInJar) {
083: File rootDirectory = MetadataUtils.getRootPackageDir(f,
084: toFind);
085: findClassesRecursive("", rootDirectory);
086: // generate interface-impl map
087: } else {
088: findImplementationInJarFiles(loc);
089: }
090: }
091:
092: private void findImplementationInJarFiles(URL locationInJar) {
093: String jarName = MetadataUtils.isolateJarName(locationInJar);
094: try {
095: InputStream input = new FileInputStream(jarName);
096:
097: List<String> back = MetadataUtils
098: .scanFileNamesInArchive(input);
099: input.close();
100: this .findClassesFromList(back);
101: // generate interface-impl map
102:
103: } catch (FileNotFoundException e) {
104: log.error("File not found", e);
105: throw new IllegalArgumentException(
106: "Cant find implementation");
107: } catch (IOException e) {
108: log.error("File not found", e);
109: throw new IllegalArgumentException(
110: "Cant find implementation");
111: }
112:
113: }
114:
115: /**
116: * Iterate over a given root directory and search class files
117: *
118: * @author Daniel Wiese
119: * @since 13.11.2005
120: * @param currentPackageName -
121: * the package we are starting with
122: * @param directory .
123: * the current directory
124: */
125: private void findClassesRecursive(String currentPackageName,
126: File directory) {
127:
128: if (directory.exists()) {
129: // Get the list of the files contained in the package
130: File[] files = directory.listFiles();
131: String[] fileNames = directory.list();
132: for (int i = 0; i < files.length; i++) {
133:
134: // we are only interested in .class files
135: if (fileNames[i].endsWith(".class")) {
136: // removes the .class extension
137: String classname = fileNames[i].substring(0,
138: fileNames[i].length() - 6);
139:
140: // Try to find the class on the class path
141: final String toAdd = currentPackageName + "."
142: + classname;
143: this .allClasses.add(toAdd.replace('.', '/'));
144:
145: } else if (files[i].isDirectory()) {
146: String newPackageName = "";
147: if (currentPackageName.equals("")) {
148: newPackageName = fileNames[i];
149: } else {
150: newPackageName = currentPackageName + "."
151: + fileNames[i];
152: }
153: findClassesRecursive(newPackageName, files[i]);
154: }
155: }
156: }
157: }
158:
159: /**
160: * Iterate over a given root directory and search class files
161: *
162: * @author Daniel Wiese
163: * @since 13.11.2005
164: * @param currentPackageName -
165: * the package we are starting with
166: * @param directory .
167: * the current directory
168: */
169: private void findClassesFromList(List<String> files) {
170:
171: for (String file : files) {
172: if (file.endsWith(".class")) {
173: // removes the .class extension
174: String classname = file.substring(0, file.length() - 6);
175: classname = classname.replace("\\", "/");
176: this.allClasses.add(classname);
177: }
178: }
179: }
180: }
|