/******************************************************************************* * Copyright (c) 2008 xored software, Inc. * * 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: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.core.search.indexing.core; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.IPath; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.core.caching.IContentCache; import org.eclipse.dltk.core.environment.EnvironmentPathUtils; import org.eclipse.dltk.core.environment.IEnvironment; import org.eclipse.dltk.core.environment.IFileHandle; import org.eclipse.dltk.core.search.index.Index; import org.eclipse.dltk.core.search.indexing.AbstractJob; import org.eclipse.dltk.core.search.indexing.IProjectIndexer; import org.eclipse.dltk.core.search.indexing.IProjectIndexer.Internal; import org.eclipse.dltk.core.search.indexing.ReadWriteMonitor; import org.eclipse.dltk.internal.core.ModelManager; /** * @since 2.0 */ public abstract class IndexRequest extends AbstractJob { private IProjectIndexer indexer; public IndexRequest(IProjectIndexer indexer) { this.indexer = indexer; } public IProjectIndexer.Internal getIndexer() { return (Internal) indexer; } /** * Returns all the document names. Read lock is acquired automatically. * * @param index * @return * @throws IOException */ protected String[] queryDocumentNames(final Index index) throws IOException { final ReadWriteMonitor monitor = index.monitor; monitor.enterRead(); try { return index.queryDocumentNames(null); } finally { monitor.exitRead(); } } protected Map<String, ISourceModule> collectSourceModulePaths( Collection<ISourceModule> modules, IPath containerPath) { final Map<String, ISourceModule> paths = new HashMap<String, ISourceModule>(); for (Iterator<ISourceModule> i = modules.iterator(); i.hasNext();) { final ISourceModule module = i.next(); paths.put(SourceIndexUtil.containerRelativePath(containerPath, module), module); } return paths; } /** * Check changes of the specified modules compared to the index. Returns the * {@link List} of changes. List items could be {@link String} if that * document should be removed from the index or ISourceModule if that module * should be indexed. If there are no changes the empty {@link List} is * returned. If <code>environment</code> is specified then it is used to * retrieve the modification time of the files to compare with the * modification time of the index. * * @param index * @param modules * @param containerPath * @param environment * could be <code>null</code> * @param parentFolders * - will be filled if cache folder timestamp update are * performed. * @return * @throws ModelException * @throws IOException */ protected List<Object> checkChanges(Index index, Collection<ISourceModule> modules, IPath containerPath, IEnvironment environment, Set<IFileHandle> parentFolders) throws ModelException, IOException { IContentCache coreCache = ModelManager.getModelManager().getCoreCache(); final String[] documents = queryDocumentNames(index); if (documents != null && documents.length != 0) { // final long indexLastModified = // index.getIndexFile().lastModified(); final List<Object> changes = new ArrayList<Object>(); final Map<String, ISourceModule> m = collectSourceModulePaths( modules, containerPath); if (DEBUG) { log("documents.length=" + documents.length); //$NON-NLS-1$ log("modules.size=" + modules.size()); //$NON-NLS-1$ log("map.size=" + m.size()); //$NON-NLS-1$ } for (int i = 0; i < documents.length; ++i) { final String document = documents[i]; final ISourceModule module = m.remove(document); if (module == null) { changes.add(document); } else if (environment != null) { // final IFileHandle handle = environment // .getFile(EnvironmentPathUtils.getLocalPath(module // .getPath())); IFileHandle handle = EnvironmentPathUtils.getFile(module, false); if (handle != null) { // Check content cache for file changes String indexed = coreCache .getCacheEntryAttributeString(handle, "indexed", true); if (indexed == null) { IFileHandle parent = handle.getParent(); if (parentFolders.add(parent) && documents.length > 1) { coreCache.updateFolderTimestamps(parent); } changes.add(module); coreCache.setCacheEntryAttribute(handle, "indexed", ""); } } } } if (!m.isEmpty()) { changes.addAll(m.values()); } return changes; } else { return new ArrayList<Object>(modules); } } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((indexer == null) ? 0 : indexer.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; IndexRequest other = (IndexRequest) obj; if (indexer == null) { if (other.indexer != null) return false; } else if (!indexer.equals(other.indexer)) return false; return true; } }