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-2006 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.gsfret.source.usages;
043:
044: import java.io.File;
045: import java.io.IOException;
046: import java.lang.ref.WeakReference;
047: import java.net.URL;
048: import java.util.Collections;
049: import java.util.List;
050: import java.util.Map;
051: import java.util.Set;
052: import java.util.logging.Logger;
053: import org.netbeans.modules.gsf.api.Index.SearchResult;
054: import org.netbeans.modules.gsf.api.CancellableTask;
055: import org.netbeans.modules.gsf.api.IndexDocument;
056: import org.netbeans.modules.gsf.api.Indexer;
057: import org.netbeans.modules.gsf.api.NameKind;
058: import org.netbeans.modules.gsf.api.ParserResult;
059: import org.netbeans.napi.gsfret.source.CompilationController;
060: import org.netbeans.napi.gsfret.source.CompilationInfo;
061: import org.netbeans.modules.gsfpath.api.queries.SourceForBinaryQuery;
062: import org.netbeans.modules.gsf.Language;
063: import org.netbeans.modules.gsf.LanguageRegistry;
064: import org.netbeans.napi.gsfret.source.ClassIndex;
065: import org.netbeans.napi.gsfret.source.Phase;
066: import org.netbeans.napi.gsfret.source.Source;
067: import org.netbeans.modules.gsfret.source.SourceAccessor;
068: import org.openide.filesystems.FileObject;
069: import org.openide.filesystems.URLMapper;
070: import org.openide.util.Exceptions;
071:
072: /**
073: * This file is originally from Retouche, the Java Support
074: * infrastructure in NetBeans. I have modified the file as little
075: * as possible to make merging Retouche fixes back as simple as
076: * possible.
077: *
078: *
079: * @author Petr Hrebejk, Tomas Zezula
080: */
081: public class PersistentClassIndex extends ClassIndexImpl {
082:
083: private final Index index;
084: private final URL root;
085: private final boolean isSource;
086: private WeakReference<Source> dirty;
087: private static final Logger LOGGER = Logger
088: .getLogger(PersistentClassIndex.class.getName());
089:
090: /** Creates a new instance of ClassesAndMembersUQ */
091: private PersistentClassIndex(final Language language,
092: final URL root, final File cacheRoot, final boolean source)
093: throws IOException, IllegalArgumentException {
094: assert root != null;
095: this .root = root;
096: this .index = LuceneIndex.create(language, cacheRoot, this );
097: this .isSource = source;
098: // BEGIN TOR MODIFICATIONS
099: this .language = language;
100: this .cacheRoot = cacheRoot;
101: // END TOR MODIFICATIONS
102: }
103:
104: // public BinaryAnalyser getBinaryAnalyser () {
105: // return new BinaryAnalyser (this.index);
106: // }
107:
108: public SourceAnalyser getSourceAnalyser() {
109: return new SourceAnalyser(this .index);
110: }
111:
112: public FileObject[] getSourceRoots() {
113: FileObject[] rootFos;
114: if (isSource) {
115: FileObject rootFo = URLMapper.findFileObject(this .root);
116: rootFos = rootFo == null ? new FileObject[0]
117: : new FileObject[] { rootFo };
118: } else {
119: rootFos = SourceForBinaryQuery.findSourceRoots(this .root)
120: .getRoots();
121: }
122: return rootFos;
123: }
124:
125: // Factory method
126:
127: public static ClassIndexImpl create(Language language, URL root,
128: final File cacheRoot, final boolean indexNow)
129: throws IOException, IllegalArgumentException {
130: return new PersistentClassIndex(language, root, cacheRoot,
131: indexNow);
132: }
133:
134: public synchronized void setDirty(final Source js) {
135: if (js == null) {
136: this .dirty = null;
137: } else if (this .dirty == null || this .dirty.get() != js) {
138: this .dirty = new WeakReference(js);
139: }
140: }
141:
142: public @Override
143: String toString() {
144: return "CompromiseUQ[" + this .root.toExternalForm() + "]"; // NOI18N
145: }
146:
147: //Protected methods --------------------------------------------------------
148: protected final void close() throws IOException {
149: this .index.close();
150: }
151:
152: // Private methods ---------------------------------------------------------
153:
154: private Void runIndexers(final CompilationInfo info)
155: throws IOException {
156:
157: Set<String> mimeTypes = info.getEmbeddedMimeTypes();
158: final SourceAnalyser sa = getSourceAnalyser();
159: long st = System.currentTimeMillis();
160: for (String mimeType : mimeTypes) {
161: for (ParserResult result : info
162: .getEmbeddedResults(mimeType)) {
163: assert result != null;
164:
165: Language language = LanguageRegistry.getInstance()
166: .getLanguageByMimeType(mimeType);
167: Indexer indexer = language.getIndexer();
168: if (indexer != null) {
169: sa.analyseUnitAndStore(indexer, result);
170: }
171: }
172: }
173: long et = System.currentTimeMillis();
174: return null;
175: }
176:
177: private void updateDirty() {
178: WeakReference<Source> jsRef;
179: synchronized (this ) {
180: jsRef = this .dirty;
181: }
182: if (jsRef != null) {
183: final Source js = jsRef.get();
184: if (js != null) {
185: final long startTime = System.currentTimeMillis();
186: if (SourceAccessor.getINSTANCE().isDispatchThread()) {
187: //Already under javac's lock
188: try {
189: ClassIndexManager
190: .get(language)
191: .writeLock(
192: new ClassIndexManager.ExceptionAction<Void>() {
193: public Void run()
194: throws IOException {
195: CompilationInfo compilationInfo = SourceAccessor
196: .getINSTANCE()
197: .getCurrentCompilationInfo(
198: js,
199: Phase.RESOLVED);
200: if (compilationInfo != null) {
201: //Not cancelled
202: return runIndexers(compilationInfo);
203: }
204: return null;
205: }
206: });
207: } catch (IOException ioe) {
208: Exceptions.printStackTrace(ioe);
209: }
210: } else {
211: try {
212: js
213: .runUserActionTask(
214: new CancellableTask<CompilationController>() {
215: public void run(
216: final CompilationController controller) {
217: try {
218: ClassIndexManager
219: .get(
220: language)
221: .writeLock(
222: new ClassIndexManager.ExceptionAction<Void>() {
223: public Void run()
224: throws IOException {
225: controller
226: .toPhase(Phase.RESOLVED);
227: return runIndexers(controller);
228: }
229: });
230: } catch (IOException ioe) {
231: Exceptions
232: .printStackTrace(ioe);
233: }
234: }
235:
236: public void cancel() {
237: }
238: }, true);
239: } catch (IOException ioe) {
240: Exceptions.printStackTrace(ioe);
241: }
242: }
243: synchronized (this ) {
244: this .dirty = null;
245: }
246: final long endTime = System.currentTimeMillis();
247: LOGGER.fine("PersistentClassIndex.updateDirty took: "
248: + (endTime - startTime) + " ms"); //NOI18N
249: }
250: }
251: }
252:
253: // BEGIN TOR MODIFICATIONS
254: public void search(final String primaryField, final String name,
255: final NameKind kind,
256: final Set<ClassIndex.SearchScope> scope,
257: final Set<SearchResult> result, final Set<String> terms)
258: throws IOException {
259: updateDirty();
260: try {
261: ClassIndexManager
262: .readLock(new ClassIndexManager.ExceptionAction<Void>() {
263: public Void run() throws IOException {
264: index.search(primaryField, name, kind,
265: scope, result, terms);
266: return null;
267: }
268: });
269: } catch (IOException ioe) {
270: Exceptions.printStackTrace(ioe);
271: }
272: }
273:
274: public Map<String, String> getTimeStamps() throws IOException {
275: return this .index.getTimeStamps();
276: }
277:
278: /** For development purposes only */
279: public File getSegment() {
280: return cacheRoot;
281: }
282:
283: private File cacheRoot;
284: private Language language;
285:
286: public URL getRoot() {
287: return root;
288: }
289:
290: // For the symbol dumper only
291: public org.apache.lucene.index.IndexReader getDumpIndexReader()
292: throws IOException {
293: if (index instanceof LuceneIndex) {
294: try {
295: return ((LuceneIndex) index).getDumpIndexReader();
296: } catch (IOException ioe) {
297: ioe.printStackTrace();
298: }
299: }
300:
301: return null;
302: }
303:
304: @Override
305: public void storeEmpty() {
306: List<IndexDocument> list = Collections.emptyList();
307: try {
308: this .index.store(null, list);
309: } catch (IOException ex) {
310: Exceptions.printStackTrace(ex);
311: }
312: }
313: // END TOR MODIFICATIONS
314:
315: }
|