/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
* 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:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFileSet;
import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.pdom.PDOM.ChangeEvent;
import org.eclipse.cdt.internal.core.pdom.PDOM.DebugLockInfo;
import org.eclipse.cdt.internal.core.pdom.PDOM.IListener;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* The PDOMProxy is returned by the PDOMManager before the indexer kicks in. Also and more
* importantly it is returned when the indexer has been shut down (clients may not be aware
* of this yet). Doing that prevents the creation of empty pdoms for deleted projects.
*/
public class PDOMProxy implements IPDOM {
private PDOM fDelegate;
private int fReadLockCount;
private Set<IListener> fListeners= new HashSet<IListener>();
private Map<Thread, DebugLockInfo> fLockDebugging;
public PDOMProxy() {
if (PDOM.sDEBUG_LOCKS) {
fLockDebugging= new HashMap<Thread, DebugLockInfo>();
}
}
@Override
public synchronized void acquireReadLock() throws InterruptedException {
if (fDelegate != null) {
fDelegate.acquireReadLock();
} else {
fReadLockCount++;
if (PDOM.sDEBUG_LOCKS) {
PDOM.incReadLock(fLockDebugging);
}
}
}
@Override
public IIndexMacro[] findMacros(char[] name, boolean isPrefix, boolean caseSensitive,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (fDelegate != null)
return fDelegate.findMacros(name, isPrefix, caseSensitive, filter, monitor);
return IIndexMacro.EMPTY_INDEX_MACRO_ARRAY;
}
@Override
public synchronized IIndexFragmentBinding adaptBinding(IBinding binding) throws CoreException {
if (fDelegate != null)
return fDelegate.adaptBinding(binding);
return null;
}
@Override
public synchronized IIndexFragmentBinding findBinding(IASTName astName) throws CoreException {
if (fDelegate != null)
return fDelegate.findBinding(astName);
return null;
}
@Override
public synchronized IIndexFragmentBinding[] findBindings(char[][] names, IndexFilter filter,
IProgressMonitor monitor) throws CoreException {
if (fDelegate != null)
return fDelegate.findBindings(names, filter, monitor);
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
@Override
public synchronized IIndexFragmentBinding[] findBindings(Pattern[] patterns, boolean isFullyQualified,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (fDelegate != null)
return fDelegate.findBindings(patterns, isFullyQualified, filter, monitor);
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
@Override
public synchronized IIndexFragmentBinding[] findBindings(char[] name, boolean filescope,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (fDelegate != null)
return fDelegate.findBindings(name, filescope, filter, monitor);
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
@Override
public synchronized IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, boolean filescope,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (fDelegate != null)
return fDelegate.findBindingsForPrefix(prefix, filescope, filter, monitor);
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
@Override
public synchronized IIndexFragmentBinding[] findBindingsForContentAssist(char[] prefix, boolean filescope,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (fDelegate != null)
return fDelegate.findBindingsForContentAssist(prefix, filescope, filter, monitor);
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
@Override
public synchronized IIndexFragmentInclude[] findIncludedBy(IIndexFragmentFile file) throws CoreException {
if (fDelegate != null)
return fDelegate.findIncludedBy(file);
return new IIndexFragmentInclude[0];
}
@Override
public synchronized IIndexFragmentName[] findNames(IBinding binding, int flags)
throws CoreException {
if (fDelegate != null)
return fDelegate.findNames(binding, flags);
return IIndexFragmentName.EMPTY_NAME_ARRAY;
}
@Override
public synchronized long getCacheHits() {
if (fDelegate != null)
return fDelegate.getCacheHits();
return 0;
}
@Override
public synchronized long getCacheMisses() {
if (fDelegate != null)
return fDelegate.getCacheMisses();
return 0;
}
@Deprecated
@Override
public synchronized IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
if (fDelegate != null)
return fDelegate.getFile(linkageID, location);
return null;
}
@Override
public IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros sigMacros) throws CoreException {
if (fDelegate != null)
return fDelegate.getFile(linkageID, location, sigMacros);
return null;
}
@Override
public IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location)
throws CoreException {
if (fDelegate != null)
return fDelegate.getFiles(linkageID, location);
return IIndexFragmentFile.EMPTY_ARRAY;
}
@Override
public synchronized IIndexFragmentFile[] getFiles(IIndexFileLocation location) throws CoreException {
if (fDelegate != null)
return fDelegate.getFiles(location);
return IIndexFragmentFile.EMPTY_ARRAY;
}
@Override
public synchronized long getLastWriteAccess() {
if (fDelegate != null)
return fDelegate.getLastWriteAccess();
return 0;
}
@Override
public synchronized IIndexLinkage[] getLinkages() {
if (fDelegate != null)
return fDelegate.getLinkages();
return new IIndexLinkage[0];
}
@Override
public synchronized String getProperty(String propertyName) throws CoreException {
if (fDelegate != null)
return fDelegate.getProperty(propertyName);
return null;
}
@Override
public synchronized void releaseReadLock() {
// read-locks not forwarded to delegate need to be released here
if (fReadLockCount > 0) {
fReadLockCount--;
if (PDOM.sDEBUG_LOCKS)
PDOM.decReadLock(fLockDebugging);
} else if (fDelegate != null) {
fDelegate.releaseReadLock();
}
}
@Override
public boolean hasWaitingReaders() {
return fDelegate != null && fDelegate.hasWaitingReaders();
}
@Override
public synchronized void resetCacheCounters() {
if (fDelegate != null)
fDelegate.resetCacheCounters();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public synchronized Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(PDOMProxy.class)) {
return this;
}
return null;
}
@Override
public synchronized void addListener(IListener listener) {
if (fDelegate != null) {
fDelegate.addListener(listener);
} else {
fListeners.add(listener);
}
}
@Override
public synchronized PDOMLinkage[] getLinkageImpls() {
if (fDelegate != null)
return fDelegate.getLinkageImpls();
return new PDOMLinkage[0];
}
@Override
public synchronized void removeListener(IListener listener) {
if (fDelegate != null) {
fDelegate.removeListener(listener);
} else {
fListeners.remove(listener);
}
}
public synchronized void setDelegate(WritablePDOM pdom) {
fDelegate= pdom;
try {
while (fReadLockCount > 0) {
pdom.acquireReadLock();
fReadLockCount--;
}
if (PDOM.sDEBUG_LOCKS) {
pdom.adjustThreadForReadLock(fLockDebugging);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
for (IListener listener : fListeners) {
pdom.addListener(listener);
}
ChangeEvent event= new ChangeEvent();
event.setReloaded();
for (IListener listener : fListeners) {
listener.handleChange(fDelegate, event);
}
}
@Override
public IIndexFragmentFileSet createFileSet() {
return new PDOMFileSet();
}
@Override
public synchronized IIndexFragmentFile[] getAllFiles() throws CoreException {
if (fDelegate != null)
return fDelegate.getAllFiles();
return IIndexFragmentFile.EMPTY_ARRAY;
}
@Override
public synchronized IIndexFragmentBinding[] findMacroContainers(Pattern pattern, IndexFilter filter,
IProgressMonitor monitor) throws CoreException {
if (fDelegate != null) {
return fDelegate.findMacroContainers(pattern, filter, monitor);
}
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
@Override
public Object getCachedResult(Object key) {
return null;
}
@Override
public Object putCachedResult(Object key, Object value, boolean replace) {
return value;
}
@Override
public void clearResultCache() {
if (fDelegate != null)
fDelegate.clearResultCache();
}
@Override
public IIndexScope[] getInlineNamespaces() throws CoreException {
if (fDelegate != null)
return fDelegate.getInlineNamespaces();
return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY;
}
}