diff options
Diffstat (limited to 'web/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java')
-rw-r--r-- | web/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java | 647 |
1 files changed, 647 insertions, 0 deletions
diff --git a/web/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java b/web/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java new file mode 100644 index 0000000000..23b90ab4c9 --- /dev/null +++ b/web/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java @@ -0,0 +1,647 @@ +/******************************************************************************* + * 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; + } + +} |