blob: 31b986fbda638fec0aca1dee80f8edd9402797cf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.jst.jsp.core.internal.contentmodel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
import org.eclipse.core.filebuffers.IFileBuffer;
import org.eclipse.core.filebuffers.IFileBufferListener;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
import org.eclipse.wst.sse.core.internal.util.Assert;
/**
* Provides a direct mapping from IStructuredDocument to supporting
* TLDCMDocumentManager.
*
* Listens to the creation of JSP type TextFileBuffers and forces a text-less
* reparse after connecting taglib-supporting listeners. Connecting the
* listeners before the text is set would be ideal, but there is no way to
* look up taglib references since the location is not yet knowable. Since
* taglibs can affect the parsing of the document, a reparse is currently
* required to react to custom tags with tagdependent content.
*
* TODO: Remove the reparse penalty.
*/
public class TaglibController implements IDocumentSetupParticipant {
class DocumentInfo implements ITaglibIndexListener {
IStructuredDocument document;
ITextFileBuffer textFileBuffer;
TLDCMDocumentManager tldDocumentManager;
public void indexChanged(ITaglibRecordEvent event) {
tldDocumentManager.indexChanged(event);
}
}
class FileBufferListener implements IFileBufferListener {
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#bufferContentAboutToBeReplaced(org.eclipse.core.filebuffers.IFileBuffer)
*/
public void bufferContentAboutToBeReplaced(IFileBuffer buffer) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#bufferContentReplaced(org.eclipse.core.filebuffers.IFileBuffer)
*/
public void bufferContentReplaced(IFileBuffer buffer) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#bufferCreated(org.eclipse.core.filebuffers.IFileBuffer)
*/
public void bufferCreated(IFileBuffer buffer) {
if (buffer instanceof ITextFileBuffer) {
IDocument document = ((ITextFileBuffer) buffer).getDocument();
// ignore non-JSP documents
synchronized (fJSPdocuments) {
if (!fJSPdocuments.contains(document))
return;
}
Assert.isTrue(document instanceof IStructuredDocument, getClass().getName() + " SetupParticipant was called for non-IStructuredDocument"); //$NON-NLS-1$
DocumentInfo info = new DocumentInfo();
info.document = (IStructuredDocument) document;
info.textFileBuffer = (ITextFileBuffer) buffer;
info.tldDocumentManager = new TLDCMDocumentManager();
info.tldDocumentManager.setSourceParser((JSPSourceParser) info.document.getParser());
synchronized (fDocumentMap) {
fDocumentMap.put(document, info);
TaglibIndex.addTaglibIndexListener(info);
}
if (document instanceof BasicStructuredDocument) {
((BasicStructuredDocument) document).reparse(this);
}
// info.tldDocumentManager.doRebuild();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#bufferDisposed(org.eclipse.core.filebuffers.IFileBuffer)
*/
public void bufferDisposed(IFileBuffer buffer) {
if (buffer instanceof ITextFileBuffer) {
IDocument document = ((ITextFileBuffer) buffer).getDocument();
synchronized (fJSPdocuments) {
if (!fJSPdocuments.remove(document))
return;
}
}
synchronized (fDocumentMap) {
Object[] keys = fDocumentMap.keySet().toArray();
boolean removed = false;
for (int i = 0; i < keys.length && !removed; i++) {
DocumentInfo info = (DocumentInfo) fDocumentMap.get(keys[i]);
if (info != null && info.textFileBuffer.equals(buffer)) {
TaglibIndex.removeTaglibIndexListener(info);
fDocumentMap.remove(keys[i]);
removed = true;
}
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#dirtyStateChanged(org.eclipse.core.filebuffers.IFileBuffer,
* boolean)
*/
public void dirtyStateChanged(IFileBuffer buffer, boolean isDirty) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#stateChangeFailed(org.eclipse.core.filebuffers.IFileBuffer)
*/
public void stateChangeFailed(IFileBuffer buffer) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#stateChanging(org.eclipse.core.filebuffers.IFileBuffer)
*/
public void stateChanging(IFileBuffer buffer) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#stateValidationChanged(org.eclipse.core.filebuffers.IFileBuffer,
* boolean)
*/
public void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#underlyingFileDeleted(org.eclipse.core.filebuffers.IFileBuffer)
*/
public void underlyingFileDeleted(IFileBuffer buffer) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IFileBufferListener#underlyingFileMoved(org.eclipse.core.filebuffers.IFileBuffer,
* org.eclipse.core.runtime.IPath)
*/
public void underlyingFileMoved(IFileBuffer buffer, IPath path) {
}
}
static TaglibController _instance = null;
static private boolean fIsShutdown = false;
public static ITextFileBuffer getFileBuffer(IDocument document) {
synchronized (_instance.fDocumentMap) {
DocumentInfo info = (DocumentInfo) _instance.fDocumentMap.get(document);
if (info != null)
return info.textFileBuffer;
return null;
}
}
/**
* @param manager
* @return
*/
public static ITextFileBuffer getFileBuffer(TLDCMDocumentManager manager) {
// if _instance is null, we are already shutting donw
if (_instance == null)
return null;
ITextFileBuffer buffer = null;
synchronized (_instance.fDocumentMap) {
Iterator docInfos = _instance.fDocumentMap.values().iterator();
while (docInfos.hasNext() && buffer == null) {
DocumentInfo info = (DocumentInfo) docInfos.next();
if (info.tldDocumentManager.equals(manager))
buffer = info.textFileBuffer;
}
}
return buffer;
}
public static TLDCMDocumentManager getTLDCMDocumentManager(IDocument document) {
// if _instance is null, we are already shutting donw
if (_instance == null)
return null;
synchronized (_instance.fDocumentMap) {
DocumentInfo info = (DocumentInfo) _instance.fDocumentMap.get(document);
if (info != null)
return info.tldDocumentManager;
return null;
}
}
public synchronized static void shutdown() {
setShutdown(true);
FileBuffers.getTextFileBufferManager().removeFileBufferListener(_instance.fBufferListener);
_instance = null;
}
public synchronized static void startup() {
_instance = new TaglibController();
FileBuffers.getTextFileBufferManager().addFileBufferListener(_instance.fBufferListener);
setShutdown(false);
}
IFileBufferListener fBufferListener;
Map fDocumentMap;
List fJSPdocuments;
// This constructor is only to be called as part of the FileBuffer
// framework
public TaglibController() {
super();
fBufferListener = new FileBufferListener();
fJSPdocuments = new ArrayList(1);
fDocumentMap = new HashMap(1);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.filebuffers.IDocumentSetupParticipant#setup(org.eclipse.jface.text.IDocument)
*/
public void setup(IDocument document) {
// if we've already shutdown, just ignore
if (isShutdown())
return;
synchronized (_instance.fJSPdocuments) {
_instance.fJSPdocuments.add(document);
}
}
private static synchronized boolean isShutdown() {
return fIsShutdown;
}
private static synchronized void setShutdown(boolean isShutdown) {
fIsShutdown = isShutdown;
}
}