/******************************************************************************* * Copyright (c) 2007 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation *******************************************************************************/ package org.eclipse.imp.indexing; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.imp.core.ErrorHandler; import org.eclipse.imp.language.Language; import org.eclipse.imp.language.LanguageRegistry; import org.eclipse.imp.language.ServiceFactory; import org.eclipse.imp.language.LanguageValidator; import org.eclipse.imp.parser.IParseController; import org.eclipse.imp.runtime.RuntimePlugin; import org.eclipse.imp.utils.StreamUtils; /* * Licensed Materials - Property of IBM, * (c) Copyright IBM Corp. 2005 All Rights Reserved */ /** * @author rfuhrer@watson.ibm.com */ public class Indexer { private final Language fLanguage; // used to locate the index file private IndexContributorBase fIndexer; private IParseController fParser; /** * The set of index entries for the current project being indexed */ private Set/*<IndexEntry>*/ fProjectEntries= new HashSet(); /** * Creates an index for the shared elements in this language */ public Indexer(String languageName) { fLanguage= LanguageRegistry.findLanguage(languageName); fIndexer= ServiceFactory.getInstance().getIndexContributor(fLanguage); fParser= ServiceFactory.getInstance().getParseController(fLanguage); } // Probably don't ever want to do this; the complete set of indexes is huge. // Instead, each project index should probably be loaded and then searched // from within the top-level search loop. public void loadAll() { IProject[] projects= ResourcesPlugin.getWorkspace().getRoot().getProjects(); for(int i= 0; i < projects.length; i++) { load(projects[i]); } } /** * Opens the index file for reading. The index file is stored in the plug-in's state location. If this is the first * time the index is opened, it will be created. The inputstream has to be closed after usage. * * @return an inputstream containing the index file */ public void load(IProject project) { try { File file= getPersistentIndexFile(project); readEntries(new BufferedReader(new FileReader(file))); } catch (IOException e) { ErrorHandler.reportError("Cannot open persistent index for " + fLanguage); } } private void readEntries(BufferedReader reader) throws IOException { String line; while ((line= reader.readLine()) != null) { IndexEntry entry= fIndexer.parseEntry(line); addEntry(entry); } } public void clearEntries() { fProjectEntries.clear(); } public void addEntry(IndexEntry entry) { fProjectEntries.add(entry); } public void createAllIndexes() { if (fParser == null) { RuntimePlugin.getInstance().writeErrorMsg("No parser for language " + fLanguage + "; indexing disabled."); return; } IProject[] projects= ResourcesPlugin.getWorkspace().getRoot().getProjects(); for(int i= 0; i < projects.length; i++) { clearEntries(); // no turds from previous projects createProjectIndex(projects[i]); save(projects[i]); } } public void createProjectIndex(IProject project) { final LanguageValidator validator= fLanguage.getValidator(); final IProgressMonitor monitor= new NullProgressMonitor(); try { project.accept(new IResourceProxyVisitor() { public boolean visit(IResourceProxy proxy) throws CoreException { if (proxy.getType() == IResource.FILE) { String name= proxy.getName(); if (fLanguage.hasExtension(name.substring(name.lastIndexOf('.') + 1))) { IFile file= (IFile) proxy.requestResource(); if (validator == null || validator.validate(file)) { String contents= StreamUtils.readStreamContents(file.getContents(), file.getCharset()); Object ast= fParser.parse(contents, monitor); if (ast != null) fIndexer.contributeEntries(ast, Indexer.this); else RuntimePlugin.getInstance().writeErrorMsg("Unable to parse file " + file.getFullPath() + "; indexing suppressed."); } } } return false; } }, 0); } catch (CoreException e) { e.printStackTrace(); } } /** * Open the index file for saving. The output stream should be closed after usage. * * @return an outputStream the user can write to. */ public void save(IProject project) { try { File file= getPersistentIndexFile(project); FileWriter writer= new FileWriter(file); for(Iterator iter= fProjectEntries.iterator(); iter.hasNext(); ) { IndexEntry entry= (IndexEntry) iter.next(); entry.saveToStream(writer); } } catch (IOException e) { ErrorHandler.reportError("Cannot open persistent index for " + fLanguage + " and project " + project.getName(), e); } } /** * Returns the index file. The index file is stored in the plug-in's state location. If this is the first time the * index is opened, it will be created. * @param project the project whose index file should be loaded * * @return the file where the persistent index is stored * @return null when the file cannot be created */ private File getPersistentIndexFile(IProject project) { try { IPath path= RuntimePlugin.getInstance().getStateLocation().append(project.getName()); File file= new File(path.toFile(), fLanguage + ".index"); if (!file.exists()) { file.createNewFile(); } return file; } catch (IOException e) { ErrorHandler.reportError("Cannot locate index file for " + fLanguage + " and project " + project.getName(), e); return null; } } }