blob: a6d4dbf567341ba9d0a90445ca2efe4d105eee2a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 Oracle Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Cameron Bateman/Oracle - initial API and implementation
*
********************************************************************************/
package org.eclipse.jst.jsf.test.util.mock.smodel;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.IllegalCharsetNameException;
import org.eclipse.core.internal.runtime.PlatformActivator;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jst.jsf.test.util.mock.osgi.BundleHacker;
import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
import org.eclipse.wst.sse.core.internal.encoding.CodedReaderCreator;
import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
import org.eclipse.wst.sse.core.internal.encoding.util.Logger;
import org.eclipse.wst.sse.core.internal.encoding.util.NullInputStream;
import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
import org.eclipse.wst.sse.core.internal.util.ProjectResolver;
import org.eclipse.wst.sse.core.internal.util.URIResolver;
import org.eclipse.wst.xml.core.internal.encoding.XMLDocumentLoader;
import org.eclipse.wst.xml.core.internal.modelhandler.ModelHandlerForXML;
import org.eclipse.wst.xml.core.internal.modelhandler.XMLModelLoader;
import org.osgi.framework.BundleException;
@SuppressWarnings("deprecation")
public class TestableStructuredModelFactory
{
public static void hackStatics() throws SecurityException,
NoSuchFieldException, BundleException, IllegalArgumentException,
IllegalAccessException
{
new BundleHacker().mockBundleContext(PlatformActivator.class, null);
}
public IStructuredModel createUnManagedModelFor(final IFile file)
throws CoreException, ResourceInUse, IOException
{
IStructuredModel model = createUnManagedEmptyModelFor(file);
final IDocumentLoader loader = model.getModelHandler()
.getDocumentLoader();
final IEncodedDocument document = loader
.createNewStructuredDocument(file);
model.getStructuredDocument().setText(this, document.get());
return model;
}
/**
* @param iFile
* @param result
* @return
* @throws CoreException
* @throws ResourceInUse
*/
protected IStructuredModel createUnManagedEmptyModelFor(final IFile iFile)
throws CoreException, ResourceInUse
{
final ModelHandlerForXML handler = new ModelHandlerForXML()
{
public IDocumentLoader getDocumentLoader()
{
return new TestableXMLModelLoader();
}
};
final String id = iFile.getFullPath().toString();
final URIResolver resolver = calculateURIResolver(iFile);
return _commonCreateModel(id, handler, resolver);
}
/**
*
*/
private URIResolver calculateURIResolver(final IFile file)
{
// Note: see comment in plugin.xml for potentially
// breaking change in behavior.
final IProject project = file.getProject();
final URIResolver resolver = new ProjectResolver(project);
Object location = file.getLocation();
if (location == null)
{
location = file.getLocationURI();
}
if (location != null)
{
resolver.setFileBaseLocation(location.toString());
}
return resolver;
}
private IStructuredModel _commonCreateModel(final String id,
final ModelHandlerForXML handler, final URIResolver resolver)
throws ResourceInUse
{
final IModelLoader loader = new XMLModelLoader()
{
public IDocumentLoader getDocumentLoader()
{
return new TestableXMLModelLoader();
}
};
// handler.getModelLoader();
final IStructuredModel result = loader.createModel();
// in the past, id was null for "unmanaged" case, so we won't
// try and set it
if (id != null)
{
// result.setId(id);
}
result.setModelHandler(handler);
result.setResolver(resolver);
// some obvious redunancy here that maybe could be improved
// in future, but is necessary for now
result.setBaseLocation(id);
if (resolver != null)
{
resolver.setFileBaseLocation(id);
}
// addFactories(result, handler);
return result;
}
public static final String NO_SPEC_DEFAULT = "NoSpecDefault"; //$NON-NLS-1$
/**
* Note: once this instance is created, trace info still needs to be
* appended by caller, depending on the context its created.
*/
public static EncodingMemento createEncodingMemento(
final String detectedCharsetName, final String reason,
final String specDefaultEncoding)
{
EncodingMemento result = new EncodingMemento();
result = new EncodingMemento();
final String javaCharset = "UTF-8";
result.setJavaCharsetName(javaCharset);
result.setDetectedCharsetName(detectedCharsetName);
// TODO: if detectedCharset and spec default is
// null, need to use "work
// bench based" defaults.
if (specDefaultEncoding == null)
{
result.setAppropriateDefault(NO_SPEC_DEFAULT);
}
else
{
result.setAppropriateDefault(specDefaultEncoding);
}
// check if valid
try
{
Charset.isSupported(javaCharset);
}
catch (final IllegalCharsetNameException e)
{
result.setInvalidEncoding(javaCharset);
}
return result;
}
private static final class TestableXMLModelLoader extends XMLDocumentLoader
{
public IEncodedDocument createNewStructuredDocument()
{
final IEncodedDocument structuredDocument = newEncodedDocument();
// Make sure every structuredDocument has an Encoding Memento,
// which is the default one for "empty" structuredDocuments
final String charset = "UTF-8";
final String specDefaultCharset = getDocumentEncodingDetector()
.getSpecDefaultEncoding();
structuredDocument.setEncodingMemento(createEncodingMemento(
charset, EncodingMemento.DEFAULTS_ASSUMED_FOR_EMPTY_INPUT,
specDefaultCharset));
// String lineDelimiter = null;
// if (lineDelimiter != null)
// structuredDocument.setPreferredLineDelimiter(lineDelimiter);
final IDocumentPartitioner defaultPartitioner = getDefaultDocumentPartitioner();
if (structuredDocument instanceof IDocumentExtension3)
{
((IDocumentExtension3) structuredDocument)
.setDocumentPartitioner(
IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING,
defaultPartitioner);
}
else
{
structuredDocument.setDocumentPartitioner(defaultPartitioner);
}
defaultPartitioner.connect(structuredDocument);
return structuredDocument;
}
/**
* This abstract version should handle most cases, but won't if
* contentType is sensitive to encoding, and/or embedded types
*/
public IEncodedDocument createNewStructuredDocument(final IFile iFile)
throws IOException, CoreException
{
final IEncodedDocument structuredDocument = createNewStructuredDocument();
// String lineDelimiter = getPreferredNewLineDelimiter(iFile);
// if (lineDelimiter != null)
// structuredDocument.setPreferredLineDelimiter(lineDelimiter);
try
{
// final CodedReaderCreator creator = getCodedReaderCreator();
// creator.set(iFile);
// fEncodingMemento = new
// EncodingMemento();//creator.getEncodingMemento();
// structuredDocument.setEncodingMemento(fEncodingMemento);
// fFullPreparedReader =
// getCodedReaderCreator().getCodedReader();
InputStream streamToReturn = getResettableStream(iFile);
streamToReturn.reset();
Charset charset = Charset.forName("UTF-8");
CharsetDecoder charsetDecoder = charset.newDecoder();
fFullPreparedReader = new BufferedReader(new InputStreamReader(
streamToReturn, charsetDecoder), CodedIO.MAX_BUF_SIZE);
fFullPreparedReader.mark(CodedIO.MAX_BUF_SIZE);
setDocumentContentsFromReader(structuredDocument,
fFullPreparedReader);
}
finally
{
if (fFullPreparedReader != null)
{
fFullPreparedReader.close();
}
}
return structuredDocument;
}
private InputStream getResettableStream(IFile fIFile)
throws CoreException, IOException
{
InputStream resettableStream = null;
if (fIFile != null)
{
InputStream inputStream = null;
try
{
// note we always get contents, even if out of synch
inputStream = fIFile.getContents(true);
}
catch (CoreException e)
{
// SHOULD actually check for existence of
// fIStorage, but
// for now will just assume core exception
// means it
// doesn't exist on file system, yet.
// and we'll log, just in case its a noteable error
Logger.logException(e);
inputStream = new NullInputStream();
}
resettableStream = new BufferedInputStream(inputStream,
CodedIO.MAX_BUF_SIZE);
}
// else
// {
// if (fInputStream != null)
// {
// if (fInputStream.markSupported())
// {
// resettableStream = fInputStream;
// // try {
// resettableStream.reset();
// // }
// // catch (IOException e) {
// // // assumed just hasn't been marked yet, so ignore
// // }
// }
// else
// {
// resettableStream = new BufferedInputStream(
// fInputStream, CodedIO.MAX_BUF_SIZE);
// }
// }
// }
if (resettableStream == null)
{
resettableStream = new NullInputStream();
}
// mark this once, stream at "zero" position
resettableStream.mark(CodedReaderCreator.MAX_MARK_SIZE);
return resettableStream;
}
}
}