blob: 23b90ab4c97bdebfb844baa13e81a2790ceef56e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2009 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.modelhandler;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.contentproperties.JSPFContentProperties;
import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapter;
import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapterFactory;
import org.eclipse.jst.jsp.core.internal.document.PageDirectiveWatcherFactory;
import org.eclipse.jst.jsp.core.internal.domdocument.DOMModelForJSP;
import org.eclipse.jst.jsp.core.internal.encoding.IJSPHeadContentDetector;
import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentHeadContentDetector;
import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentLoader;
import org.eclipse.jst.jsp.core.internal.modelquery.JSPModelQueryAdapterImpl;
import org.eclipse.jst.jsp.core.internal.modelquery.ModelQueryAdapterFactoryForJSP;
import org.eclipse.jst.jsp.core.internal.parser.JSPReParser;
import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
import org.eclipse.jst.jsp.core.internal.provisional.contenttype.IContentDescriptionForJSP;
import org.eclipse.jst.jsp.core.internal.text.StructuredTextPartitionerForJSP;
import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeFamilyForHTML;
import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
import org.eclipse.wst.html.core.internal.text.StructuredTextPartitionerForHTML;
import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
import org.eclipse.wst.sse.core.internal.document.DocumentReader;
import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
import org.eclipse.wst.sse.core.internal.model.AbstractModelLoader;
import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistry;
import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistryImpl;
import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
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;
import org.eclipse.wst.sse.core.internal.util.Debug;
import org.eclipse.wst.xml.core.internal.DebugAdapterFactory;
import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
import org.eclipse.wst.xml.core.internal.propagate.PropagatingAdapterFactoryImpl;
import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
import org.eclipse.wst.xml.core.internal.text.rules.StructuredTextPartitionerForXML;
import org.w3c.dom.Document;
public class JSPModelLoader extends AbstractModelLoader {
protected final int MAX_BUFFERED_SIZE_FOR_RESET_MARK = 200000;
/**
* DMW - Note: I think the embeddedTypeRegistry in IModelManager can be
* removed
*/
private EmbeddedTypeRegistry embeddedContentTypeRegistry;
private final static String DEFAULT_MIME_TYPE = "text/html"; //$NON-NLS-1$
private final static String DEFAULT_LANGUAGE = "java"; //$NON-NLS-1$
public JSPModelLoader() {
super();
}
/**
* Gets the embeddedContentTypeRegistry.
*
* @return Returns a EmbeddedContentTypeRegistry
*/
private EmbeddedTypeRegistry getEmbeddedContentTypeRegistry() {
if (embeddedContentTypeRegistry == null) {
embeddedContentTypeRegistry = EmbeddedTypeRegistryImpl.getInstance();
}
return embeddedContentTypeRegistry;
}
public IStructuredModel newModel() {
DOMModelForJSP model = new DOMModelForJSP();
return model;
}
/**
* For JSP files, text/html is the default content type. This may want
* this different for types like jsv (jsp for voice xml) For now, hard
* code to new instance. In future, should get instance from registry.
*
* Specification cites HTML as the default contentType.
*/
private EmbeddedTypeHandler getJSPDefaultEmbeddedType(IStructuredModel model) {
EmbeddedTypeRegistry reg = getEmbeddedContentTypeRegistry();
String mimeType = null;
// default embedded type for fragments
if (model != null) {
IFile file = getFile(model);
if (file != null) {
mimeType = JSPFContentProperties.getProperty(JSPFContentProperties.JSPCONTENTTYPE, file, true);
}
}
mimeType = mimeType == null ? getDefaultMimeType() : mimeType;
return reg.getTypeFor(mimeType);
}
/**
* Method getDefaultMimeType.
*
* @return String
*/
private String getDefaultMimeType() {
return DEFAULT_MIME_TYPE;
}
/**
* This method must return a new instance of IStructuredDocument, that has
* been initialized with appropriate parser. For many loaders, the
* (default) parser used is known for any input. For others, the correct
* parser (and its initialization) is normall dependent on the content of
* the file. This no-argument method should assume "empty input" and would
* therefore return the default parser for the default contentType.
*
* If the parser is to handle tag libraries, it must have a TaglibSupport
* object with a valid URIResolver and this IStructuredDocument attached
* to it before the contents are set on the IStructuredDocument.
*/
public IStructuredDocument newStructuredDocument() {
IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser());
((BasicStructuredDocument) structuredDocument).setReParser(new JSPReParser());
// structuredDocument.setDocumentPartitioner(new
// JSPJavaDocumentPartioner());
// even though this is an "empty model" ... we want it to have at
// least the
// default embeddeded content type handler
EmbeddedTypeHandler embeddedType = getJSPDefaultEmbeddedType(null);
embeddedType.initializeParser(structuredDocument.getParser());
return structuredDocument;
}
public RegionParser getParser() {
// remember, the Loader
// will need to finish initialization of parser
// based on "embedded content"
return new JSPSourceParser();
}
protected void preLoadAdapt(IStructuredModel structuredModel) {
super.preLoadAdapt(structuredModel);
IDOMModel domModel = (IDOMModel) structuredModel;
//
// document must have already been set for this to
// work.
Document document = domModel.getDocument();
Assert.isNotNull(document);
// if there is a model in the adapter, this will adapt it to
// first node. After that the PropagatingAdater spreads over the
// children being
// created. Each time that happends, a side effect is to
// also "spread" sprecific registered adapters,
// they two can propigate is needed.
// This 'get' causes first to be be attached.
PropagatingAdapter propagatingAdapter = (PropagatingAdapter) ((INodeNotifier) document).getAdapterFor(PropagatingAdapter.class);
// may make this easier to use in futue
propagatingAdapter.addAdaptOnCreateFactory(new PageDirectiveWatcherFactory());
if (Debug.debugNotificationAndEvents) {
propagatingAdapter.addAdaptOnCreateFactory(new DebugAdapterFactory());
}
// For JSPs, the ModelQueryAdapter must be "attached" to the document
// before content is set in the model, so taglib initization can
// take place.
((INodeNotifier) document).getAdapterFor(ModelQueryAdapter.class);
//
}
/**
* This method must return those factories which must be attached to the
* structuredModel before content is applied.
*/
public List getAdapterFactories() {
List result = new ArrayList();
INodeAdapterFactory factory = null;
//
factory = new ModelQueryAdapterFactoryForJSP();
result.add(factory);
factory = new PropagatingAdapterFactoryImpl();
result.add(factory);
factory = new PageDirectiveAdapterFactory();
result.add(factory);
return result;
}
public IJSPHeadContentDetector getHeadParser() {
return new JSPDocumentHeadContentDetector();
}
private IContentDescription getContentDescription(IDocument doc) {
if (doc == null)
return null;
DocumentReader reader = new DocumentReader(doc);
return getContentDescription(reader);
}
/**
* Returns content description for an input stream Assumes it's JSP
* content. Closes the input stream when finished.
*
* @param reader
* @return the IContentDescription for in, or null if in is null
*/
private IContentDescription getContentDescription(Reader reader) {
if (reader == null)
return null;
IContentDescription desc = null;
try {
IContentType contentTypeJSP = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP);
desc = contentTypeJSP.getDescriptionFor(reader, IContentDescription.ALL);
}
catch (IOException e) {
Logger.logException(e);
}
finally {
if (reader != null) {
try {
reader.close();
}
catch (IOException e) {
Logger.logException(e);
}
}
}
return desc;
}
private IFile getFile(IStructuredModel model) {
if (model != null) {
String location = model.getBaseLocation();
if (location != null) {
IPath path = new Path(location);
if (!path.toFile().exists() && path.segmentCount() > 1) {
return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
}
}
}
return null;
}
/**
* Method getLanguage.
*
* @param model
* @return String
*/
private String getLanguage(IStructuredModel model) {
String result = null;
// first check the model (document itself) to see if contains
result = getLanguageFromStructuredDocument(model.getStructuredDocument());
// Note: if model contains an unsupported
// language, we'll even return it,
// since who knows what future holds.
// get default language specified in properties page
IFile file = getFile(model);
result = JSPFContentProperties.getProperty(JSPFContentProperties.JSPLANGUAGE, file, true);
// always return something
if (result == null) {
result = DEFAULT_LANGUAGE;
}
return result;
}
/**
* Method getLanguageFromStructuredDocument.
*
* @param structuredDocument
* @return String
*/
private String getLanguageFromStructuredDocument(IStructuredDocument structuredDocument) {
if (structuredDocument == null)
return null;
String result = null;
// bascially same algorithm as get encoding or
// get content type from structuredDocument.
IJSPHeadContentDetector localHeadParser = getHeadParser();
// we can be assured that its already been
// parsed. If not call parseHeaderForPageDirective()
// before calling getLanguage;
localHeadParser.set(structuredDocument);
try {
result = localHeadParser.getLanguage();
}
catch (IOException e) {
// impossible
// TODO need to reconsider design to avoid
throw new Error(e);
}
return result;
}
/**
* This is "reinitialize" since there should always be at least the
* default one assigned, before we start checking the stream
*/
private void reInitializeEmbeddedType(IStructuredModel model, EmbeddedTypeHandler oldEmbeddedContentType, EmbeddedTypeHandler newEmbeddedContentType) {
// check program logic
Assert.isNotNull(oldEmbeddedContentType, "Program error: invalid call during model initialization"); //$NON-NLS-1$
// once we know the embedded content type, we need to set it in the
// PageDirectiveAdapter ... the order of initialization is
// critical here, the doc must have been created, but its contents not
// set yet,
// and all factories must have been set up also.
IDOMModel domModel = (IDOMModel) model;
IStructuredDocument structuredDocument = model.getStructuredDocument();
IDOMDocument document = domModel.getDocument();
PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getExistingAdapter(PageDirectiveAdapter.class);
// ==> // PropagatingAdapter propagatingAdapter = (PropagatingAdapter)
// ((INodeNotifier)
// document).getExistingAdapter(PropagatingAdapter.class);
// ==> // ModelQueryAdapter modelQueryAdapter = (ModelQueryAdapter)
// ((INodeNotifier)
// document).getExistingAdapter(ModelQueryAdapter.class);
oldEmbeddedContentType.uninitializeFactoryRegistry(model.getFactoryRegistry());
oldEmbeddedContentType.uninitializeParser(structuredDocument.getParser());
// since 'document' is not recreated in this
// reinit path, we need to remove all adapters,
// except for the propagated adapters (including page
// directive adapter, and model query adapter).
// to accomplish this, we'll just remove all, then
// add back with a call to pre-load adapt.
// let clients decide to unload adapters from document
// Collection oldAdapters = document.getAdapters();
// Iterator oldAdaptersIterator = oldAdapters.iterator();
// while (oldAdaptersIterator.hasNext()) {
// INodeAdapter oldAdapter = (INodeAdapter)
// oldAdaptersIterator.next();
// if (oldAdapter != pageDirectiveAdapter && oldAdapter !=
// propagatingAdapter && oldAdapter != modelQueryAdapter) {
// // DO NOT remove directly!
// // can change contents while in notifity loop!
// //oldAdaptersIterator.remove();
// document.removeAdapter(oldAdapter);
// }
// }
// DMW: I believe something like the following is needed,
// since releases cached adapters
// if (document instanceof DocumentImpl) {
// ((DocumentImpl) document).releaseDocumentType();
// ((DocumentImpl) document).releaseStyleSheets();
// }
// remember, embedded type factories are automatically cleared when
// embededType changed
pageDirectiveAdapter.setEmbeddedType(newEmbeddedContentType);
// // but still need to clear the page directive watchers, and let
// them be rediscovered (with new, accurate node as target)
// pageDirectiveAdapter.clearPageWatchers();
if (newEmbeddedContentType != null) {
// need to null out or else ModelParserAdapter
// won't get reinitialized
((DOMModelImpl) model).setModelParser(null);
newEmbeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
newEmbeddedContentType.initializeParser(structuredDocument.getParser());
// partitioner setup is the responsibility of this loader
IDocumentPartitioner documentPartitioner = structuredDocument.getDocumentPartitioner();
// ISSUE: this logic is flawed, not sure of original intent, but
// added null/type checks for safety.
if (documentPartitioner != null && documentPartitioner instanceof StructuredTextPartitionerForJSP) {
if (newEmbeddedContentType.getFamilyId().equals(ContentTypeIdForXML.ContentTypeID_XML)) {
((StructuredTextPartitionerForJSP) documentPartitioner).setEmbeddedPartitioner(new StructuredTextPartitionerForXML());
}
else if (newEmbeddedContentType.getFamilyId().equals(ContentTypeIdForHTML.ContentTypeID_HTML)) {
((StructuredTextPartitionerForJSP) documentPartitioner).setEmbeddedPartitioner(new StructuredTextPartitionerForHTML());
}
}
}
// adding language here, in this convienent central
// location, but some obvious renaming or refactoring
// wouldn't hurt, in future.
// I needed to add this language setting for JSP Fragment support
// Note: this is the one that counts, since at this point,
// the model has an ID, so we can look up IFile, etc.
String language = getLanguage(model);
if (language != null && language.length() > 0) {
pageDirectiveAdapter.setLanguage(language);
}
}
/**
* This is "reinitialize" since there should always be at least the
* default one assigned, before we start checking the stream
*/
private void initCloneOfEmbeddedType(IStructuredModel model, EmbeddedTypeHandler oldEmbeddedContentType, EmbeddedTypeHandler newEmbeddedContentType) {
// check program logic
Assert.isNotNull(oldEmbeddedContentType, "Program error: invalid call during model initialization"); //$NON-NLS-1$
// once we know the embedded content type, we need to set it in the
// PageDirectiveAdapter ... the order of initialization is
// critical here, the doc must have been created, but its contents not
// set yet,
// and all factories must have been set up also.
IDOMModel domModel = (IDOMModel) model;
IStructuredDocument structuredDocument = model.getStructuredDocument();
IDOMDocument document = domModel.getDocument();
PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getAdapterFor(PageDirectiveAdapter.class);
// ==> // PropagatingAdapter propagatingAdapter = (PropagatingAdapter)
// ((INodeNotifier) document).getAdapterFor(PropagatingAdapter.class);
// ==> // ModelQueryAdapter modelQueryAdapter = (ModelQueryAdapter)
// ((INodeNotifier) document).getAdapterFor(ModelQueryAdapter.class);
// because, even in the clone case, the model has been paritally
// intialized with
// the old embedded type (during createModel), we need to unitialize
// parts of it, based on the old (or default) ones
oldEmbeddedContentType.uninitializeFactoryRegistry(model.getFactoryRegistry());
oldEmbeddedContentType.uninitializeParser(structuredDocument.getParser());
// remember, embedded type factories are automatically cleared when
// embededType changed
pageDirectiveAdapter.setEmbeddedType(newEmbeddedContentType);
if (newEmbeddedContentType != null) {
newEmbeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
newEmbeddedContentType.initializeParser(structuredDocument.getParser());
}
// adding language here, in this convienent central
// location, but some obvious renaming or refactoring
// wouldn't hurt, in future.
// I needed to add this language setting for JSP Fragment support
// Note: this is the one that counts, since at this point,
// the model has an ID, so we can look up IFile, etc.
String language = getLanguage(model);
if (language != null && language.length() > 0) {
pageDirectiveAdapter.setLanguage(language);
}
}
private EmbeddedTypeHandler getEmbeddedType(IStructuredModel model) {
Document doc = ((IDOMModel) model).getDocument();
PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) ((INodeNotifier) doc).getAdapterFor(PageDirectiveAdapter.class);
EmbeddedTypeHandler embeddedHandler = pageDirectiveAdapter.getEmbeddedType();
return embeddedHandler;
}
/* (non-Javadoc)
* @see org.eclipse.wst.sse.core.internal.model.AbstractModelLoader#initEmbeddedTypePre(org.eclipse.wst.sse.core.internal.provisional.IStructuredModel)
*/
protected void initEmbeddedTypePre(IStructuredModel model) {
JSPModelLoader.this.initEmbeddedTypePre(model, model.getStructuredDocument());
}
protected void initEmbeddedTypePre(IStructuredModel model, IStructuredDocument structuredDocument) {
// note: this will currently only work for models backed by files
EmbeddedTypeHandler embeddedContentType = null;
IDOMModel domModel = (IDOMModel) model;
if (embeddedContentType == null) {
IContentDescription desc = getContentDescription(structuredDocument);
if (desc != null) {
Object prop = null;
prop = desc.getProperty(IContentDescriptionForJSP.CONTENT_FAMILY_ATTRIBUTE);
if (prop != null) {
if (ContentTypeFamilyForHTML.HTML_FAMILY.equals(prop)) {
embeddedContentType = EmbeddedTypeRegistryImpl.getInstance().getTypeFor("text/html");
}
}
if (embeddedContentType == null) {
prop = desc.getProperty(IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE);
if (prop != null) {
embeddedContentType = EmbeddedTypeRegistryImpl.getInstance().getTypeFor((String) prop);
}
}
}
}
IDOMDocument document = domModel.getDocument();
PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getAdapterFor(PageDirectiveAdapter.class);
if (embeddedContentType != null) {
pageDirectiveAdapter.setEmbeddedType(embeddedContentType);
embeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
}
else {
// use default embeddedType if it couldn't determine one
embeddedContentType = getJSPDefaultEmbeddedType(model);
pageDirectiveAdapter.setEmbeddedType(embeddedContentType);
embeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
}
}
protected void initEmbeddedTypePost(IStructuredModel model) {
// should already be initialized (from initEmbeddedTypePre)
// via IContentDescription
setLanguageInPageDirective(model);
}
/**
* As part of the model cloning process, ensure that the new model has the
* same embedded content type handler as the old model, and that it is
* properly initialized
*/
protected void initEmbeddedType(IStructuredModel oldModel, IStructuredModel newModel) {
EmbeddedTypeHandler existingEmbeddedType = getEmbeddedType(oldModel);
if (existingEmbeddedType == null) {
initEmbeddedTypePre(newModel, newModel.getStructuredDocument());
initEmbeddedTypePost(newModel);
}
else {
EmbeddedTypeHandler newEmbeddedContentType = existingEmbeddedType.newInstance();
// initEmbeddedType(newModel);
initCloneOfEmbeddedType(newModel, existingEmbeddedType, newEmbeddedContentType);
setLanguageInPageDirective(newModel);
}
}
protected void setLanguageInPageDirective(IStructuredModel newModel) {
if (newModel instanceof IDOMModel) {
IDOMDocument document = ((IDOMModel) newModel).getDocument();
PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getAdapterFor(PageDirectiveAdapter.class);
String language = getLanguage(newModel);
pageDirectiveAdapter.setLanguage(language);
}
}
public IStructuredModel reinitialize(IStructuredModel model) {
EmbeddedTypeHandler oldHandler = null;
EmbeddedTypeHandler newHandler = null;
Object reinitStateData = model.getReinitializeStateData();
if (reinitStateData instanceof EmbeddedTypeStateData) {
EmbeddedTypeStateData oldStateData = (EmbeddedTypeStateData) reinitStateData;
oldHandler = oldStateData.getOldHandler();
newHandler = oldStateData.getNewHandler();
// note. We should already have the new handler in the model's
// (documents) adapters,
// so need need to use the old one to undo the old state data
reInitializeEmbeddedType(model, oldHandler, newHandler);
}
else {
// for language ... we someday MIGHT have to do something
// here, but for now, we don't have any model-side language
// sensitive adapters.
}
return super.reinitialize(model);
}
public IModelLoader newInstance() {
return new JSPModelLoader();
}
public IDocumentLoader getDocumentLoader() {
if (documentLoaderInstance == null) {
documentLoaderInstance = new JSPDocumentLoader();
}
return documentLoaderInstance;
}
/**
* Ensures that an InputStream has mark/reset support.
*/
public static InputStream getMarkSupportedStream(InputStream original) {
if (original == null)
return null;
if (original.markSupported())
return original;
return new BufferedInputStream(original);
}
protected byte[] getBytes(InputStream inputStream, int max) throws IOException {
byte[] smallBuffer = new byte[max];
byte[] returnBuffer = null;
int nRead = inputStream.read(smallBuffer, 0, max);
if (nRead < max) {
// empty file will return -1;
if (nRead < 0)
nRead = 0;
byte[] smallerBuffer = new byte[nRead];
System.arraycopy(smallBuffer, 0, smallerBuffer, 0, nRead);
returnBuffer = smallerBuffer;
}
else {
returnBuffer = smallBuffer;
}
return returnBuffer;
}
public IStructuredModel createModel(IStructuredModel oldModel) {
IStructuredModel model = super.createModel(oldModel);
// For JSPs, the ModelQueryAdapter must be "attached" to the document
// before content is set in the model, so taglib initialization can
// take place.
// In this "clone model" case, we create a ModelQuery adapter
// create a new instance from the old data. Note: I think this
// "forced fit" only works here since the implementation of
// ModelQueryAdapter does not
// have to be released.
ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(model);
if (modelQueryAdapter == null) {
modelQueryAdapter = getModelQueryAdapter(oldModel);
IDOMDocument document = ((IDOMModel) model).getDocument();
document.addAdapter(new JSPModelQueryAdapterImpl(modelQueryAdapter.getCMDocumentCache(), modelQueryAdapter.getModelQuery(), modelQueryAdapter.getIdResolver()));
}
return model;
}
private ModelQueryAdapter getModelQueryAdapter(IStructuredModel model) {
IDOMDocument document = ((IDOMModel) model).getDocument();
ModelQueryAdapter modelQueryAdapter = (ModelQueryAdapter) ((INodeNotifier) document).getAdapterFor(ModelQueryAdapter.class);
return modelQueryAdapter;
}
}