blob: 2204d8954917a3b26d0d5341d193a787236a7537 [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
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.ui;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.editors.text.ILocationProvider;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.ui.texteditor.IElementStateListener;
import org.eclipse.wst.sse.core.IFactoryRegistry;
import org.eclipse.wst.sse.core.IModelManager;
import org.eclipse.wst.sse.core.IModelManagerPlugin;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.ui.extensions.breakpoint.IExtendedStorageEditorInput;
import org.eclipse.wst.sse.ui.nls.ResourceHandler;
import org.eclipse.wst.sse.ui.registry.AdapterFactoryProvider;
import org.eclipse.wst.sse.ui.registry.AdapterFactoryRegistry;
import org.eclipse.wst.sse.ui.util.Assert;
/**
* A TextFileDocumentProvider that is IStructuredModel aware. This
* implementation is marked as final since it will change significantly in C4,
* possibly even be removed.
*
* @deprecated - no longer used
*/
public final class TextFileModelProvider extends TextFileDocumentProvider implements IModelProvider {
/**
* Collection of info that goes with a model.
*/
protected class ModelInfo {
public IAnnotationModel fAnnotationModel;
public IEditorInput fElement;
public boolean fShouldReleaseOnInfoDispose;
public IStructuredModel fStructuredModel;
public ModelInfo(IStructuredModel structuredModel, IEditorInput element, IAnnotationModel model, boolean selfCreated) {
fElement = element;
fStructuredModel = structuredModel;
fAnnotationModel = model;
fShouldReleaseOnInfoDispose = selfCreated;
}
}
private static TextFileModelProvider fInstance = null;
private static IModelManager fModelManager;
public synchronized static TextFileModelProvider getInstance() {
if (fInstance == null)
fInstance = new TextFileModelProvider();
return fInstance;
}
/**
* Utility method also used in subclasses
*/
protected static IModelManager getModelManager() {
if (fModelManager == null) {
// get the model manager from the plugin
// note: we can use the static "ID" variable, since we pre-req
// that plugin
IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
fModelManager = plugin.getModelManager();
}
return fModelManager;
}
protected IElementStateListener fInternalListener;
/** IStructuredModel information of all connected elements */
private Map fModelInfoMap = new HashMap();
protected TextFileModelProvider() {
super();
}
public void addProviderFactories(IStructuredModel structuredModel) {
// (mostly) COPIED FROM FileModelProvider
EditorPlugin plugin = ((EditorPlugin) Platform.getPlugin(EditorPlugin.ID));
AdapterFactoryRegistry adapterRegistry = plugin.getAdapterFactoryRegistry();
Iterator adapterFactoryList = adapterRegistry.getAdapterFactories();
IFactoryRegistry factoryRegistry = structuredModel.getFactoryRegistry();
Assert.isNotNull(factoryRegistry, "model in invalid state");
while (adapterFactoryList.hasNext()) {
try {
AdapterFactoryProvider provider = (AdapterFactoryProvider) adapterFactoryList.next();
if (provider.isFor(structuredModel.getModelHandler())) {
provider.addAdapterFactories(structuredModel);
}
} catch (Exception e) {
Logger.logException(e);
}
}
// END COPY FileModelProvider
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#commitFileBuffer(org.eclipse.core.runtime.IProgressMonitor,
* org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo,
* boolean)
*/
protected void commitFileBuffer(IProgressMonitor monitor, FileInfo info, boolean overwrite) throws CoreException {
IStructuredModel model = getModel(info.fElement);
if (model != null) {
String contents = model.getStructuredDocument().get();
info.fTextFileBuffer.getDocument().set(contents);
}
super.commitFileBuffer(monitor, info, overwrite);
}
protected String computePath(IEditorInput input) {
/**
* Typically CVS will return a path of "filename.ext" and the input's
* name will be "filename.ext version". The path must be used to load
* the model so that the suffix will be available to compute the
* contentType properly. The editor input name can then be set as the
* base location for display on the editor title bar.
*/
String path = null;
boolean addHash = false;
try {
if (input instanceof IStorageEditorInput) {
IStorage storage = ((IStorageEditorInput) input).getStorage();
if (storage != null) {
IPath storagePath = storage.getFullPath();
String name = storage.getName();
// if either the name or storage path are null or they are
// identical, add a hash to it to guarantee uniqueness
addHash = storagePath == null || storagePath.toString().equals(name);
if (storagePath != null)
path = storagePath.makeAbsolute().toString();
if (path == null)
path = name;
}
} else if (input.getAdapter(ILocationProvider.class) != null) {
IPath locationPath = ((ILocationProvider) input.getAdapter(ILocationProvider.class)).getPath(input);
if (locationPath != null) {
path = locationPath.toString();
}
}
} catch (CoreException e) {
Logger.logException(e);
return null;
} finally {
if (path == null)
path = ""; //$NON-NLS-1$
}
if (addHash)
path = input.hashCode() + path;
return path;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createAnnotationModel(org.eclipse.core.resources.IFile)
*/
protected IAnnotationModel createAnnotationModel(IFile file) {
String id = file.getFullPath().toString();
IAnnotationModel model = new StructuredResourceMarkerAnnotationModel(file, id);
IEditorInput input = null;
Iterator i = getConnectedElementsIterator();
while (input == null && i.hasNext()) {
FileInfo info = (FileInfo) i.next();
if (getSystemFile(info).equals(file)) {
input = (IEditorInput) info.fElement;
}
}
ModelInfo modelInfo = getModelInfoFor(input);
modelInfo.fAnnotationModel = model;
return model;
}
/**
* Also create ModelInfo - extra resource synchronization classes should
* be stored within the ModelInfo
*/
protected FileInfo createFileInfo(Object element) throws CoreException {
FileInfo info = super.createFileInfo(element);
// create the corresponding ModelInfo if necessary
if (getModelInfoFor((IEditorInput) element) == null) {
createModelInfo((IEditorInput) element);
}
return info;
}
public void createModelInfo(IEditorInput input) {
if (getModelInfoFor(input) == null) {
IStructuredModel structuredModel = selfCreateModel(input);
createModelInfo(input, structuredModel, true);
}
}
/**
* To be used when model is provided to us, ensures that when setInput is
* used on this input, the given model will be used.
*/
public void createModelInfo(IEditorInput input, IStructuredModel structuredModel, boolean releaseModelOnDisconnect) {
// we have to make sure factories are added, whether we created or
// not.
if (getModelInfoFor(input) != null || getModelInfoFor(structuredModel) != null)
return;
if (input instanceof IExtendedStorageEditorInput) {
((IExtendedStorageEditorInput) input).addElementStateListener(fInternalListener);
}
addProviderFactories(structuredModel);
ModelInfo modelInfo = new ModelInfo(structuredModel, input, null, releaseModelOnDisconnect);
// to help with downstream usage, create a dummy/"null" annotation
// model
if (!(input instanceof IFileEditorInput)) {
modelInfo.fAnnotationModel = new AnnotationModel();
}
fModelInfoMap.put(input, modelInfo);
}
protected void disposeFileInfo(Object element, FileInfo info) {
if (element instanceof IEditorInput) {
IEditorInput input = (IEditorInput) element;
ModelInfo modelInfo = getModelInfoFor(input);
disposeModelInfo(modelInfo);
}
super.disposeFileInfo(element, info);
}
/**
* disconnect from this model info
*
* @param info
*/
public void disposeModelInfo(ModelInfo info) {
if (info.fElement instanceof IStorageEditorInput) {
if (info.fElement instanceof IExtendedStorageEditorInput) {
((IExtendedStorageEditorInput) info.fElement).removeElementStateListener(fInternalListener);
}
if (info.fShouldReleaseOnInfoDispose) {
info.fStructuredModel.releaseFromEdit();
}
}
fModelInfoMap.remove(info.fElement);
}
/**
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSaveDocument(org.eclipse.core.runtime.IProgressMonitor,
* java.lang.Object, org.eclipse.jface.text.IDocument, boolean)
*/
protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
new FileDocumentProvider().saveDocument(monitor, element, document, overwrite);
}
/**
* Overridden to use ModelInfo's annotation model
*
* @see org.eclipse.ui.texteditor.IDocumentProvider#getAnnotationModel(java.lang.Object)
*/
public IAnnotationModel getAnnotationModel(Object element) {
// override behavior an retrieve the annotation model from the model
// info
ModelInfo info = getModelInfoFor((IEditorInput) element);
if (info != null)
return info.fAnnotationModel;
return null;
}
public IDocument getDocument(Object element) {
IDocument document = null;
IStructuredModel model = getModel(element);
if (model != null)
document = model.getStructuredDocument();
return document;
}
protected IEditorInput getInputFor(IDocument document) {
IStructuredModel model = getModelManager().getExistingModelForRead(document);
IEditorInput input = getInputFor(model);
model.releaseFromRead();
return input;
}
protected IEditorInput getInputFor(IStructuredModel structuredModel) {
IEditorInput result = null;
ModelInfo info = getModelInfoFor(structuredModel);
if (info != null)
result = info.fElement;
return result;
}
public IStructuredModel getModel(IEditorInput element) {
IStructuredModel result = null;
ModelInfo info = getModelInfoFor(element);
if (info != null) {
result = info.fStructuredModel;
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.sse.ui.IModelProvider#getModel(java.lang.Object)
*/
public IStructuredModel getModel(Object element) {
if (element instanceof IEditorInput)
return getModel((IEditorInput) element);
return null;
}
protected ModelInfo getModelInfoFor(IEditorInput element) {
ModelInfo result = (ModelInfo) fModelInfoMap.get(element);
return result;
}
protected ModelInfo getModelInfoFor(IStructuredModel structuredModel) {
ModelInfo result = null;
if (structuredModel != null) {
ModelInfo[] modelInfos = (ModelInfo[]) fModelInfoMap.values().toArray(new ModelInfo[0]);
for (int i = 0; i < modelInfos.length; i++) {
ModelInfo info = modelInfos[i];
if (structuredModel.equals(info.fStructuredModel)) {
result = info;
break;
}
}
}
return result;
}
/**
* @param input
* @return
*/
private File getSystemFile(IEditorInput input) {
File file = null;
ILocationProvider provider = (ILocationProvider) input.getAdapter(ILocationProvider.class);
if (provider != null) {
IPath fullPath = provider.getPath(input);
if (fullPath != null) {
file = fullPath.toFile();
}
}
return file;
}
/**
* Method loadModel.
*
* @param input
* @return IStructuredModel
*/
public IStructuredModel loadModel(IEditorInput input) {
return loadModel(input, false);
}
/**
* Method loadModel.
*
* @param input
* @param logExceptions
* @return IStructuredModel
*/
public IStructuredModel loadModel(IEditorInput input, boolean logExceptions) {
InputStream contents = null;
IStructuredModel model = null;
File file = getSystemFile(input);
if (file != null) {
String path = file.getAbsolutePath();
try {
contents = new FileInputStream(file);
// first parameter must be unique
model = getModelManager().getModelForEdit(path, contents, null);
model.setBaseLocation(path);
} catch (IOException e) {
if (logExceptions)
Logger.logException(ResourceHandler.getString("32concat_EXC_", new Object[]{input}), e); //$NON-NLS-1$
}
try {
contents.close();
} catch (Exception e1) {
// do nothing, this is just to ensure the resource isn't held
// open
}
}
return model;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.texteditor.IDocumentProvider#resetDocument(java.lang.Object)
*/
public void resetDocument(Object element) throws CoreException {
super.resetDocument(element);
FileInfo info = getFileInfo(element);
File file = getSystemFile(info);
if (file != null && file.exists()) {
IStructuredModel model = getModel(element);
InputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
// possibly nothing if the file was deleted, shouldn't happen
// otherwise
}
if (fis != null) {
String oldContents = model.getStructuredDocument().get();
try {
model.reload(fis);
info.fTextFileBuffer.getDocument().set(model.getStructuredDocument().get());
} catch (IOException e1) {
Logger.logException("Exception caught reloading model from " + file.getName(), e1); //$NON-NLS-1$
model.getStructuredDocument().set(oldContents);
}
}
}
}
/**
* @param input
* @return
*/
protected IStructuredModel selfCreateModel(IEditorInput input) {
return loadModel(input);
}
}