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.apt.utils;
043:
044: import org.netbeans.modules.cnd.utils.cache.FilePathCache;
045: import java.io.File;
046: import java.lang.ref.Reference;
047: import java.lang.ref.SoftReference;
048: import java.util.Iterator;
049: import java.util.Map;
050: import java.util.concurrent.ConcurrentHashMap;
051: import java.util.concurrent.locks.Lock;
052: import java.util.concurrent.locks.ReentrantLock;
053: import org.netbeans.modules.cnd.apt.debug.APTTraceFlags;
054: import org.netbeans.modules.cnd.apt.support.ResolvedPath;
055:
056: /**
057: *
058: * @author Vladimir Voskresensky
059: */
060: public class APTIncludeUtils {
061:
062: private APTIncludeUtils() {
063: }
064:
065: /**
066: * finds file relatively to the baseFile
067: * caller must check that resolved path is not the same as base file
068: * to prevent recursive inclusions
069: */
070: public static ResolvedPath resolveFilePath(String file,
071: String baseFile) {
072: if (baseFile != null) {
073: String folder = new File(baseFile).getParent();
074: File fileFromBasePath = new File(folder, file);
075: if (!isDirectory(fileFromBasePath)
076: && exists(fileFromBasePath)) {
077: //return fileFromBasePath.getAbsolutePath();
078: return new ResolvedPath(folder, fileFromBasePath
079: .getAbsolutePath(), true, 0);
080: }
081: }
082: return null;
083: }
084:
085: public static ResolvedPath resolveAbsFilePath(String file) {
086: if (APTTraceFlags.APT_ABSOLUTE_INCLUDES) {
087: File absFile = new File(file);
088: if (absFile.isAbsolute() && !isDirectory(absFile)
089: && exists(absFile)) {
090: return new ResolvedPath(absFile.getParent(), file,
091: false, 0);
092: }
093: }
094: return null;
095: }
096:
097: public static void clearFileExistenceCache() {
098: mapRef.clear();
099: mapFoldersRef.clear();
100: }
101:
102: public static ResolvedPath resolveFilePath(Iterator<String> it,
103: String file, int dirOffset) {
104: while (it.hasNext()) {
105: String sysPrefix = it.next();
106: File fileFromPath = new File(new File(sysPrefix), file);
107: if (!isDirectory(fileFromPath) && exists(fileFromPath)) {
108: return new ResolvedPath(sysPrefix, fileFromPath
109: .getAbsolutePath(), false, dirOffset);
110: }
111: dirOffset++;
112: }
113: return null;
114: }
115:
116: private static boolean exists(File file) {
117: if (APTTraceFlags.OPTIMIZE_INCLUDE_SEARCH) {
118: //calls++;
119: String path = file.getAbsolutePath();
120: Boolean exists;
121: // synchronized (mapRef) {
122: Map<String, Boolean> files = getFilesMap();
123: exists = files.get(path);
124: if (exists == null) {
125: exists = Boolean.valueOf(file.exists());
126: files.put(FilePathCache.getString(path).toString(),
127: exists);
128: } else {
129: //hits ++;
130: }
131: // }
132: return exists.booleanValue();
133: } else {
134: return file.exists();
135: }
136: }
137:
138: private static boolean isDirectory(File file) {
139: if (APTTraceFlags.OPTIMIZE_INCLUDE_SEARCH) {
140: //calls++;
141: String path = file.getAbsolutePath();
142: Boolean exists;
143: // synchronized (mapFoldersRef) {
144: Map<String, Boolean> dirs = getFoldersMap();
145: exists = dirs.get(path);
146: if (exists == null) {
147: exists = Boolean.valueOf(file.isDirectory());
148: dirs.put(FilePathCache.getString(path).toString(),
149: exists);
150: } else {
151: //hits ++;
152: }
153: // }
154: return exists.booleanValue();
155: } else {
156: return file.isDirectory();
157: }
158: }
159:
160: // public static String getHitRate() {
161: // return "" + hits + "/" + calls; // NOI18N
162: // }
163: // private static int calls = 0;
164: // private static int hits = 0;
165:
166: private static Map<String, Boolean> getFilesMap() {
167: Map<String, Boolean> map = mapRef.get();
168: if (map == null) {
169: try {
170: maRefLock.lock();
171: map = mapRef.get();
172: if (map == null) {
173: map = new ConcurrentHashMap<String, Boolean>();
174: mapRef = new SoftReference<Map<String, Boolean>>(
175: map);
176: }
177: } finally {
178: maRefLock.unlock();
179: }
180: }
181: return map;
182: }
183:
184: private static Map<String, Boolean> getFoldersMap() {
185: Map<String, Boolean> map = mapFoldersRef.get();
186: if (map == null) {
187: try {
188: mapFoldersRefLock.lock();
189: map = mapFoldersRef.get();
190: if (map == null) {
191: map = new ConcurrentHashMap<String, Boolean>();
192: mapFoldersRef = new SoftReference<Map<String, Boolean>>(
193: map);
194: }
195: } finally {
196: mapFoldersRefLock.unlock();
197: }
198: }
199: return map;
200: }
201:
202: private static Lock maRefLock = new ReentrantLock();
203: private static Lock mapFoldersRefLock = new ReentrantLock();
204:
205: private static Reference<Map<String, Boolean>> mapRef = new SoftReference<Map<String, Boolean>>(
206: new ConcurrentHashMap<String, Boolean>());
207: private static Reference<Map<String, Boolean>> mapFoldersRef = new SoftReference<Map<String, Boolean>>(
208: new ConcurrentHashMap<String, Boolean>());
209:
210: }
|