001: /*
002: * JavaSource.java
003: *
004: * Copyright (C) 1998-2003 Peter Graves
005: * $Id: JavaSource.java,v 1.6 2003/05/18 19:26:02 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.util.ArrayList;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: public final class JavaSource implements Constants {
029: private static final char SEPARATOR_CHAR = LocalFile
030: .getSeparatorChar();
031:
032: public static File findSource(String className, String sourcePath) {
033: final List dirNames = Utilities
034: .getDirectoriesInPath(sourcePath);
035: if (dirNames != null) {
036: String fileName = className.replace('.', SEPARATOR_CHAR)
037: .concat(".java");
038: Iterator iter = dirNames.iterator();
039: while (iter.hasNext()) {
040: File dir = File.getInstance((String) iter.next());
041: if (dir != null) {
042: File file = File.getInstance(dir, fileName);
043: if (file != null && file.isFile())
044: return file;
045: }
046: }
047: // Not found. Try looking for short name of file.
048: int index = fileName.lastIndexOf(SEPARATOR_CHAR);
049: if (index >= 0) {
050: String shortName = fileName.substring(index + 1);
051: Log.debug("shortName = |" + shortName + "|");
052: iter = dirNames.iterator();
053: while (iter.hasNext()) {
054: File dir = File.getInstance((String) iter.next());
055: if (dir != null) {
056: File file = File.getInstance(dir, shortName);
057: if (file != null && file.isFile()) {
058: Log.debug("file = " + file.canonicalPath());
059: return file;
060: }
061: }
062: }
063: }
064: }
065: return null;
066: }
067:
068: // Returns file containing source for class referenced in buffer.
069: public static File findSource(Buffer buffer, String className,
070: boolean exact) {
071: String[] candidates;
072: if (exact) {
073: candidates = new String[1];
074: candidates[0] = className;
075: } else
076: candidates = getCandidates(className);
077: return findSource(buffer, candidates);
078: }
079:
080: private static File findSource(Buffer buffer, String[] candidates) {
081: final String[] imports = getImports(buffer);
082:
083: // Look for import in JDK source path.
084: final String jdkSourcePath = buffer
085: .getStringProperty(Property.JDK_SOURCE_PATH);
086: if (jdkSourcePath != null) {
087: final List dirNames = Utilities
088: .getDirectoriesInPath(jdkSourcePath);
089: if (dirNames != null) {
090: // Tell the user if the JDK source path is bogus.
091: for (Iterator it = dirNames.iterator(); it.hasNext();) {
092: String name = (String) it.next();
093: File dir = File.getInstance(name);
094: String message = null;
095: if (dir == null) {
096: message = "Invalid directory " + name;
097: } else if (!dir.isDirectory()) {
098: message = "The directory "
099: + dir.canonicalPath()
100: + " does not exist.";
101: }
102: if (message != null)
103: MessageDialog.showMessageDialog(message,
104: "Error");
105: }
106: for (int i = 0; i < candidates.length; i++) {
107: File file = findImport(candidates[i], imports,
108: dirNames, ".java");
109: if (file != null)
110: return file;
111: }
112: }
113: }
114:
115: // Look for import relative to package root directory.
116: File packageRootDir = JavaSource
117: .getPackageRootDirectory(buffer);
118: if (packageRootDir != null) {
119: for (int i = 0; i < candidates.length; i++) {
120: File file = findImport(candidates[i], imports,
121: packageRootDir, ".java");
122: if (file != null)
123: return file;
124: }
125: }
126:
127: // Look in current directory (i.e. current package).
128: File currentDir = buffer.getCurrentDirectory();
129: for (int i = 0; i < candidates.length; i++) {
130: File file = File.getInstance(currentDir, candidates[i]
131: .concat(".java"));
132: if (file != null && file.isFile())
133: return file;
134: }
135:
136: return null;
137: }
138:
139: private static String[] getCandidates(String s) {
140: ArrayList list = new ArrayList();
141: int index = s.indexOf('.');
142: while (index >= 0) {
143: list.add(s.substring(0, index));
144: index = s.indexOf('.', index + 1);
145: }
146: list.add(s);
147: String[] array = new String[list.size()];
148: return (String[]) list.toArray(array);
149: }
150:
151: public static String getPackageName(Buffer buffer) {
152: String packageName = null;
153: for (Line line = buffer.getFirstLine(); line != null; line = line
154: .next()) {
155: String trim = line.trim();
156: if (!trim.startsWith("package"))
157: continue;
158: trim = trim.substring(7);
159: if (trim.length() == 0)
160: continue;
161: char c = trim.charAt(0);
162: if (c != ' ' && c != '\t')
163: continue;
164: trim = trim.trim();
165: final int length = trim.length();
166: if (length == 0)
167: continue;
168: FastStringBuffer sb = new FastStringBuffer();
169: for (int i = 0; i < length; i++) {
170: c = trim.charAt(i);
171: if (c == ' ' || c == '\t' || c == ';')
172: break;
173: sb.append(c);
174: }
175: packageName = sb.toString();
176: }
177: return packageName;
178: }
179:
180: public static File getPackageRootDirectory(Buffer buffer) {
181: final File file = buffer.getFile();
182: if (file == null || file.isRemote())
183: return null;
184: final File parentDir = file.getParentFile();
185: if (parentDir == null)
186: return null;
187: final String packageName = getPackageName(buffer);
188: if (packageName == null)
189: return null;
190: final String packagePrefix = packageName.replace('.', LocalFile
191: .getSeparatorChar());
192: final String dirName = parentDir.canonicalPath();
193: if (dirName.endsWith(packagePrefix)) {
194: String packageRootDirName = dirName.substring(0, dirName
195: .length()
196: - packagePrefix.length());
197: return File.getInstance(packageRootDirName);
198: }
199: return null;
200: }
201:
202: public static String[] getImports(Buffer buffer) {
203: if (buffer.getModeId() != JAVA_MODE)
204: return null;
205: ArrayList list = new ArrayList();
206: list.add("java.lang.*");
207: for (Line line = buffer.getFirstLine(); line != null; line = line
208: .next()) {
209: String trim = line.trim();
210: if (!trim.startsWith("import"))
211: continue;
212: trim = trim.substring(6);
213: if (trim.length() == 0)
214: continue;
215: if (trim.charAt(0) != ' ' && trim.charAt(0) != '\t')
216: continue;
217: trim = trim.trim();
218: FastStringBuffer sb = new FastStringBuffer();
219: for (int i = 0; i < trim.length(); i++) {
220: char c = trim.charAt(i);
221: if (c == ' ' || c == '\t' || c == ';')
222: break;
223: sb.append(c);
224: }
225: list.add(sb.toString());
226: }
227: String[] array = new String[list.size()];
228: return (String[]) list.toArray(array);
229: }
230:
231: // Returns null if file not found.
232: private static File findImport(String className, String[] imports,
233: List dirNames, String extension) {
234: // Iterate through directories.
235: final int size = dirNames.size();
236: for (int i = 0; i < size; i++) {
237: final String dirName = (String) dirNames.get(i);
238: final File dir = File.getInstance(dirName);
239: if (dir != null) {
240: File file = findImport(className, imports, dir, ".java");
241: if (file != null)
242: return file;
243: }
244: }
245: return null;
246: }
247:
248: // Returns null if file not found.
249: public static File findImport(String className, String[] imports,
250: File dir, String extension) {
251: if (dir == null)
252: return null;
253: if (className.indexOf('.') >= 0) {
254: // Canonical class name.
255: String fileName = className.replace('.', SEPARATOR_CHAR)
256: .concat(extension);
257: File file = File.getInstance(dir, fileName);
258: return (file != null && file.isFile()) ? file : null;
259: }
260: if (imports != null) {
261: String suffix = ".".concat(className);
262: for (int i = 0; i < imports.length; i++) {
263: String s = imports[i];
264: if (s.endsWith(suffix)) {
265: // Found it!
266: String fileName = s.replace('.', SEPARATOR_CHAR)
267: .concat(extension);
268: File file = File.getInstance(dir, fileName);
269: return (file != null && file.isFile()) ? file
270: : null;
271: }
272: if (s.endsWith(".*")) {
273: String prefix = s.substring(0, s.length() - 1);
274: String canonicalName = prefix.concat(className);
275: String filename = canonicalName.replace('.',
276: SEPARATOR_CHAR).concat(extension);
277: File file = File.getInstance(dir, filename);
278: if (file != null && file.isFile())
279: return file;
280: }
281: }
282: }
283: return null;
284: }
285: }
|