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.cnd.modeldiscovery.provider;
043:
044: import java.io.File;
045: import java.util.ArrayList;
046: import java.util.HashMap;
047: import java.util.HashSet;
048: import java.util.LinkedHashSet;
049: import java.util.List;
050: import java.util.Map;
051: import java.util.Set;
052: import org.netbeans.modules.cnd.api.model.CsmFile;
053: import org.netbeans.modules.cnd.api.model.CsmInclude;
054: import org.netbeans.modules.cnd.api.project.NativeFileItem.Language;
055: import org.netbeans.modules.cnd.api.utils.IpeUtils;
056: import org.netbeans.modules.cnd.discovery.api.ItemProperties;
057: import org.netbeans.modules.cnd.discovery.api.ItemProperties.LanguageKind;
058: import org.netbeans.modules.cnd.discovery.api.SourceFileProperties;
059: import org.netbeans.modules.cnd.makeproject.api.configurations.Item;
060: import org.netbeans.modules.cnd.makeproject.api.remote.FilePathAdaptor;
061: import org.openide.filesystems.FileUtil;
062: import org.openide.util.Utilities;
063:
064: /**
065: *
066: * @author Alexander Simon
067: */
068: public class ModelSource implements SourceFileProperties {
069: private static final boolean TRACE_AMBIGUOUS = Boolean
070: .getBoolean("cnd.modeldiscovery.trace.ambiguous"); // NOI18N
071: private Item item;
072: private CsmFile file;
073: private Map<String, List<String>> searchBase;
074: private String itemPath;
075: private List<String> userIncludePaths;
076: private Set<String> includedFiles = new HashSet<String>();
077:
078: public ModelSource(Item item, CsmFile file,
079: Map<String, List<String>> searchBase) {
080: this .item = item;
081: this .file = file;
082: this .searchBase = searchBase;
083: }
084:
085: public Set<String> getIncludedFiles() {
086: if (userIncludePaths == null) {
087: getUserInludePaths();
088: }
089: return includedFiles;
090: }
091:
092: public String getCompilePath() {
093: return new File(getItemPath()).getParentFile()
094: .getAbsolutePath();
095: }
096:
097: public String getItemPath() {
098: if (itemPath == null) {
099: itemPath = item.getAbsPath();
100: itemPath = itemPath.replace('\\', '/');
101: itemPath = cutLocalRelative(itemPath);
102: if (Utilities.isWindows()) {
103: itemPath = itemPath.replace('/', File.separatorChar);
104: }
105: }
106: return itemPath;
107: }
108:
109: /**
110: * Path is include path like:
111: * .
112: * ../
113: * include
114: * Returns path in unix style
115: */
116: public static String convertRelativePathToAbsolute(
117: SourceFileProperties source, String path) {
118: if (!(path.startsWith("/") || (path.length() > 1 && path
119: .charAt(1) == ':'))) { // NOI18N
120: if (path.equals(".")) { // NOI18N
121: path = source.getCompilePath();
122: } else {
123: path = source.getCompilePath() + File.separator + path;
124: }
125: File file = new File(path);
126: path = FileUtil.normalizeFile(file).getAbsolutePath();
127: }
128: if (Utilities.isWindows()) {
129: path = path.replace('\\', '/');
130: }
131: return path;
132: }
133:
134: private static final String PATTERN = "/../"; // NOI18N
135:
136: public static String cutLocalRelative(String path) {
137: String pattern = PATTERN;
138: while (true) {
139: int i = path.indexOf(pattern);
140: if (i < 0) {
141: break;
142: }
143: int k = -1;
144: for (int j = i - 1; j >= 0; j--) {
145: if (path.charAt(j) == '/') {
146: k = j;
147: break;
148: }
149: }
150: if (k < 0) {
151: break;
152: }
153: path = path.substring(0, k + 1)
154: + path.substring(i + pattern.length());
155: }
156: return path;
157: }
158:
159: public String getItemName() {
160: return item.getFile().getName();
161: }
162:
163: public List<String> getUserInludePaths() {
164: if (userIncludePaths == null) {
165: List includePaths = item.getUserIncludePaths();
166: Set<String> res = new LinkedHashSet<String>();
167: for (Object o : includePaths) {
168: String path = (String) o;
169: path = getRelativepath(path);
170: res.add(path);
171: }
172: analyzeUnresolved(res, file, 0);
173: userIncludePaths = new ArrayList<String>(res);
174: }
175: return userIncludePaths;
176: }
177:
178: private String getRelativepath(String path) {
179: if (Utilities.isWindows()) {
180: path = path.replace('/', File.separatorChar);
181: }
182: path = IpeUtils.toRelativePath(getCompilePath(), path);
183: path = FilePathAdaptor.mapToRemote(path);
184: path = FilePathAdaptor.normalize(path);
185: return path;
186: }
187:
188: private void analyzeUnresolved(Set<String> res, CsmFile what,
189: int level) {
190: if (what == null) {
191: return;
192: }
193: for (CsmInclude include : what.getIncludes()) {
194: CsmFile resolved = include.getIncludeFile();
195: if (resolved == null) {
196: // unresolved include
197: String path = guessPath(include);
198: if (path != null) {
199: resolved = file.getProject().findFile(
200: path + File.separatorChar
201: + include.getIncludeName());
202: path = getRelativepath(path);
203: res.add(path);
204: if (level < 5 && resolved != null) {
205: analyzeUnresolved(res, resolved, level + 1);
206: }
207: }
208: } else {
209: includedFiles
210: .add(resolved.getAbsolutePath().toString());
211: if (level < 5) {
212: analyzeUnresolved(res, resolved, level + 1);
213: }
214: }
215: }
216: }
217:
218: private String guessPath(CsmInclude include) {
219: String name = include.getIncludeName().toString();
220: String found = name.replace('\\', '/');
221: String prefix = null;
222: String back = null;
223: int i = found.lastIndexOf('/');
224: if (i >= 0) {
225: prefix = found.substring(0, i + 1);
226: found = found.substring(i + 1);
227: i = prefix.lastIndexOf("./"); // NOI18N
228: if (i >= 0) {
229: back = prefix.substring(0, i + 2);
230: prefix = prefix.substring(i + 2);
231: if (prefix.length() == 0) {
232: prefix = null;
233: name = found;
234: } else {
235: name = prefix + '/' + found;
236: }
237: }
238: }
239: List<String> result = searchBase.get(found);
240: if (result != null && result.size() > 0) {
241: int pos = -1;
242: //TODO: resolve ambiguously
243: for (int j = 0; j < result.size(); j++) {
244: if (result.get(j).endsWith(name)) {
245: if (pos >= 0) {
246: if (TRACE_AMBIGUOUS) {
247: System.out
248: .println("Ambiguous name for item: "
249: + getItemPath()); // NOI18N
250: System.out.println(" name1: "
251: + result.get(pos)); // NOI18N
252: System.out.println(" name2: "
253: + result.get(j)); // NOI18N
254: }
255: } else {
256: pos = j;
257: }
258: }
259: }
260: if (pos >= 0) {
261: String path = result.get(pos);
262: path = path.substring(0, path.length() - name.length()
263: - 1);
264: return path;
265: }
266: }
267: if (TRACE_AMBIGUOUS) {
268: System.out.println("Unresolved name for item: "
269: + getItemPath()); // NOI18N
270: System.out.println(" from: "
271: + include.getContainingFile().getAbsolutePath()); // NOI18N
272: System.out.println(" name: " + include.getIncludeName()); // NOI18N
273: if (result != null && result.size() > 0) {
274: for (int j = 0; j < result.size(); j++) {
275: System.out.println(" candidate: " + result.get(j)); // NOI18N
276: }
277: }
278: }
279: return null;
280: }
281:
282: public List<String> getSystemInludePaths() {
283: List includePaths = item.getSystemIncludePaths();
284: List<String> res = new ArrayList<String>();
285: for (Object o : includePaths) {
286: String path = (String) o;
287: res.add(path);
288: }
289: return res;
290: }
291:
292: public Map<String, String> getUserMacros() {
293: List macros = item.getUserMacroDefinitions();
294: Map<String, String> res = new HashMap<String, String>();
295: for (Object o : macros) {
296: String macro = (String) o;
297: int i = macro.indexOf('=');
298: if (i > 0) {
299: res.put(macro.substring(0, i).trim(), macro.substring(
300: i + 1).trim());
301: } else {
302: res.put(macro, null);
303: }
304: }
305: return res;
306: }
307:
308: public Map<String, String> getSystemMacros() {
309: return null;
310: }
311:
312: public ItemProperties.LanguageKind getLanguageKind() {
313: if (item.getLanguage() == Language.C) {
314: return LanguageKind.C;
315: } else if (item.getLanguage() == Language.CPP) {
316: return LanguageKind.CPP;
317: }
318: return LanguageKind.Unknown;
319: }
320: }
|