001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.uml.core.reverseengineering.reframework;
043:
044: import java.io.File;
045: import java.io.IOException;
046: import java.util.ArrayList;
047: import java.util.List;
048:
049: import org.netbeans.modules.uml.common.generics.ETPairT;
050: import org.netbeans.modules.uml.core.support.umlsupport.StringUtilities;
051: import org.netbeans.modules.uml.core.support.umlutils.ETList;
052:
053: /**
054: */
055: public class FileSystemClassLocator implements IFileSystemClassLocator {
056: private List<String> m_BaseDirectories = new ArrayList<String>();
057:
058: /**
059: * The File System Locator will search a file system for a file that
060: * contains the file.
061: *
062: * @param value [in] The new base directory.
063: */
064: public void addBaseDirectory(String dir) {
065: if (dir != null && (dir = dir.trim()).length() > 0
066: && !m_BaseDirectories.contains(dir))
067: m_BaseDirectories.add(dir);
068: }
069:
070: /**
071: * The File System Locator will search a file system for a file that
072: * contains the class.
073: *
074: * @param value [in] The new base directory.
075: */
076: public ETPairT<String, String> locateFileForClass(String pack,
077: String className, ETList<IDependencyEvent> depends) {
078: String path = searchForFile("", className);
079:
080: // If failed to find the class then search in the package that contains the
081: // calling class.
082: String fullName = null;
083: if (path == null) {
084: fullName = pack;
085: path = searchForFile(fullName, className);
086: }
087:
088: // If the path still has not been found then search the dependencies.
089: if (path == null && depends != null && depends.size() > 0) {
090: ETPairT<String, String> p = searchDependencies(className,
091: depends);
092: path = p.getParamOne();
093: fullName = p.getParamTwo();
094: }
095:
096: if (path != null) {
097: if (fullName != null)
098: fullName += "::" + className;
099: else
100: fullName = className;
101: }
102:
103: return new ETPairT<String, String>(fullName, path);
104: }
105:
106: /**
107: * Retrieve the full path to the specified file name.
108: *
109: * @param filename [in] The short form of the file name.
110: * @param fullpath [out] The full path to the specified file.
111: * If the class is not located fullpath wil be an
112: * empty string.
113: */
114: public String locateFile(String filename) {
115: return searchForFile(filename);
116: }
117:
118: /**
119: * Searches for the class in the file system. The specified name
120: * needs to be the fully scoped name of the class.
121: *
122: * @param name [in] The name of the class.
123: * @return The file name.
124: */
125: protected String searchForFile(String name) {
126: // First remove all UML scope seperators. Replace them with directory
127: // separators.
128: String filename = StringUtilities.splice(name, "::",
129: File.separator);
130:
131: String ret = checkBaseDirectories(filename + ".java");
132: if (ret == null
133: && (ret = checkBaseDirectories(filename + ".cls")) == null)
134: ret = checkBaseDirectories(filename + ".frm");
135: return ret;
136: }
137:
138: /**
139: * Search the base directories to see if a file with the same name can be
140: * located.
141: *
142: * @param filename [in] The file to locate.
143: *
144: * @return The full path to the file or null.
145: */
146: protected String checkBaseDirectories(String filename) {
147: for (int i = 0, count = m_BaseDirectories.size(); i < count; ++i) {
148: String path = m_BaseDirectories.get(i);
149: File f = new File(path, filename);
150: if (f.exists()) {
151: try {
152: return f.getAbsoluteFile().getCanonicalPath();
153: } catch (IOException e) {
154: // We can't canonicalize the path? Use what we have, then.
155: // This may mess up some of our file-handling code.
156: return f.getAbsolutePath();
157: }
158: }
159: }
160: return null;
161: }
162:
163: /**
164: * Searches for the class with in the specified package.
165: *
166: * @param package [in] The name of the package.
167: * @param clsName [in] The name of the class.
168: * @return The file name.
169: */
170: protected String searchForFile(String pack, String clsName) {
171: if (clsName == null)
172: return null;
173: return searchForFile(pack != null && pack.length() > 0 ? pack
174: + "::" + clsName : clsName);
175: }
176:
177: protected ETPairT<String, String> searchDependencies(String name,
178: ETList<IDependencyEvent> depends) {
179: String ret = null;
180: String pack = null;
181: for (int i = 0, count = depends.size(); i < count; ++i) {
182: IDependencyEvent dep = depends.get(i);
183: if (dep == null)
184: continue;
185:
186: String depPack = dep.getSupplier();
187: if (depPack != null && depPack.length() > 0) {
188: // If the dependency is a class dependecy and it is the
189: // class that we are looking for then use that dependency;
190: if (dep.getIsClassDependency()) {
191: if (dep.isSameClass(name)) {
192: pack = depPack;
193: ret = searchForFile(pack, "");
194:
195: // Now remove the name of the class. I only need the package name.
196: int pos = pack.lastIndexOf("::");
197: if (pos != -1)
198: pack = pack.substring(0, pos);
199: break;
200: }
201: } else {
202: pack = depPack;
203: ret = searchForFile(pack, name);
204: }
205: }
206: }
207: return new ETPairT<String, String>(ret, pack);
208: }
209: }
|