/******************************************************************************* * Copyright (c) 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 * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.core.documentModel.loader; import java.io.*; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.jface.text.IDocumentPartitioner; import org.eclipse.php.internal.core.documentModel.parser.PHPSourceParser; import org.eclipse.php.internal.core.documentModel.parser.PHPStructuredDocumentReParser; import org.eclipse.php.internal.core.documentModel.partitioner.PHPStructuredTextPartitioner; import org.eclipse.wst.html.core.internal.encoding.HTMLDocumentLoader; import org.eclipse.wst.sse.core.internal.document.IDocumentLoader; import org.eclipse.wst.sse.core.internal.encoding.*; 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.exceptions.UnsupportedCharsetExceptionWithDetail; import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser; import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument; import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument; public class PHPDocumentLoader extends HTMLDocumentLoader { private static final boolean DEBUG = false; private CodedReaderCreator fCodedReaderCreator; protected IEncodedDocument newEncodedDocument() { IEncodedDocument doc = super.newEncodedDocument(); assert doc instanceof BasicStructuredDocument; ((BasicStructuredDocument) doc).setReParser(new PHPStructuredDocumentReParser()); // doc.setPreferredLineDelimiter( "\n" ); return doc; } public RegionParser getParser() { PHPSourceParser parser = new PHPSourceParser(); // for the "static HTML" case, we need to initialize // Blocktags here. addHTMLishTag(parser, "script"); //$NON-NLS-1$ addHTMLishTag(parser, "style"); //$NON-NLS-1$ return parser; } public IDocumentLoader newInstance() { return new PHPDocumentLoader(); } public IDocumentPartitioner getDefaultDocumentPartitioner() { return new PHPStructuredTextPartitioner(); } protected CodedReaderCreator getCodedReaderCreator() { if (fCodedReaderCreator == null) { fCodedReaderCreator = new PHPCodedReaderCreator(); } return fCodedReaderCreator; } class PHPCodedReaderCreator extends CodedReaderCreator { private EncodingRule fEncodingRule; private String fFilename; private IFile fIFile; private InputStream fInputStream; private static final String CHARSET_UTF_16 = "UTF-16"; //$NON-NLS-1$ private static final String CHARSET_UTF_16LE = "UTF-16LE"; //$NON-NLS-1$ public void set(IFile iFile) throws CoreException, IOException { super.set(iFile); fIFile = iFile; } public void set(String filename, InputStream inputStream) { super.set(filename, inputStream); fFilename = filename; fInputStream = inputStream; } protected EncodingMemento createMemento(IContentDescription contentDescription) { EncodingMemento result; String appropriateDefault = contentDescription.getContentType().getDefaultCharset(); String detectedCharset = (String) contentDescription .getProperty(IContentDescriptionExtended.DETECTED_CHARSET); String unSupportedCharset = (String) contentDescription .getProperty(IContentDescriptionExtended.UNSUPPORTED_CHARSET); String javaCharset = contentDescription.getCharset(); // Set default workbench encoding: if (detectedCharset == null && appropriateDefault == null) { detectedCharset = javaCharset = appropriateDefault = ResourcesPlugin.getEncoding(); } // integrity checks for debugging if (javaCharset == null) { Logger.log(Logger.INFO_DEBUG, "charset equaled null!"); //$NON-NLS-1$ } else if (javaCharset.length() == 0) { Logger.log(Logger.INFO_DEBUG, "charset equaled emptyString!"); //$NON-NLS-1$ } byte[] BOM = (byte[]) contentDescription.getProperty(IContentDescription.BYTE_ORDER_MARK); // result = (EncodingMemento) // contentDescription.getProperty(IContentDescriptionExtended.ENCODING_MEMENTO); result = createEncodingMemento(BOM, javaCharset, detectedCharset, unSupportedCharset, appropriateDefault, null); if (!result.isValid()) { result.setAppropriateDefault(appropriateDefault); // integrity check for debugging "invalid" cases. // the apprriate default we have, should equal what's in the // detected field. (not sure this is always required) if (DEBUG) { if (appropriateDefault != null && !appropriateDefault.equals(detectedCharset)) { Logger.log(Logger.INFO_DEBUG, "appropriate did not equal detected, as expected for invalid charset case"); //$NON-NLS-1$ } } } return result; } @Override public Reader getCodedReader() throws CoreException, IOException { Reader reader = super.getCodedReader(); try { char tBuff[] = new char[CodedIO.MAX_BUF_SIZE]; reader.read(tBuff, 0, tBuff.length); reader.reset(); return reader; } catch (Exception e) { } InputStream is = getResettableStream(); EncodingMemento encodingMemento = getEncodingMemento(); String charsetName = encodingMemento.getJavaCharsetName(); if (charsetName == null) { charsetName = encodingMemento.getDetectedCharsetName(); } if (!encodingMemento.isValid() && !forceDefault()) { throw new UnsupportedCharsetExceptionWithDetail(encodingMemento); } if (fEncodingRule == EncodingRule.FORCE_DEFAULT) { charsetName = encodingMemento.getAppropriateDefault(); } // [228366] For files that have a unicode BOM, and a charset name of // UTF-16, the charset decoder needs "UTF-16LE" if (CHARSET_UTF_16.equals(charsetName) && encodingMemento.getUnicodeBOM() == IContentDescription.BOM_UTF_16LE) charsetName = CHARSET_UTF_16LE; reader = new BufferedReader(new InputStreamReader(is, charsetName), CodedIO.MAX_BUF_SIZE); return reader; } private boolean forceDefault() { boolean result = false; if (fEncodingRule != null && fEncodingRule == EncodingRule.FORCE_DEFAULT) result = true; return result; } private InputStream getResettableStream() 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(MAX_MARK_SIZE); return resettableStream; } public void setEncodingRule(EncodingRule encodingRule) { super.setEncodingRule(encodingRule); fEncodingRule = encodingRule; } } }