public EncodingMemento getCurrentEncodingMemento() throws CoreException, IOException { // Assert.isNotNull(fPreviousEncodingMemento, // "previousEncodingMemento // needs to be set first"); if (!fHasBeenAnalyzed) { analyze(); } // post condition Assert.isNotNull(fCurrentEncodingMemento, "illegal post condition state"); // $NON-NLS-1$ // be sure to carry over appropriate encoding // "state" that may be // relevent. if (fPreviousEncodingMemento != null) { fCurrentEncodingMemento.setUTF83ByteBOMUsed(fPreviousEncodingMemento.isUTF83ByteBOMUsed()); } return fCurrentEncodingMemento; }
private void dump(OutputStream outputStream, EncodingRule encodingRule, boolean use3ByteBOMifUTF8) throws CoreException, IOException { getCurrentEncodingMemento(); String javaEncodingName = null; if (encodingRule == EncodingRule.CONTENT_BASED) { if (fCurrentEncodingMemento.isValid()) { javaEncodingName = fCurrentEncodingMemento.getJavaCharsetName(); } else { throw new UnsupportedCharsetExceptionWithDetail(fCurrentEncodingMemento); } } else if (encodingRule == EncodingRule.IGNORE_CONVERSION_ERROR) javaEncodingName = fCurrentEncodingMemento.getJavaCharsetName(); else if (encodingRule == EncodingRule.FORCE_DEFAULT) javaEncodingName = fCurrentEncodingMemento.getAppropriateDefault(); // write appropriate "header" unicode BOM bytes // Note: Java seems to write appropriate header for // UTF-16, but not // UTF-8 nor UTF-16BE. This // may vary by JRE version, so need to test well. // Note: javaEncodingName can be null in invalid // cases, so we no hard // to skip whole check if that's the case. if (javaEncodingName != null) { if ((javaEncodingName.equals(UTF_8_CHARSET_NAME) && use3ByteBOMifUTF8) || (javaEncodingName.equals(UTF_8_CHARSET_NAME) && fCurrentEncodingMemento.isUTF83ByteBOMUsed())) { outputStream.write(UTF3BYTEBOM); } else if (javaEncodingName.equals(UTF_16LE_CHARSET_NAME)) { outputStream.write(UTF16LEBOM); } else if (javaEncodingName.equals(UTF_16BE_CHARSET_NAME)) { outputStream.write(UTF16BEBOM); } } // TODO add back in line delimiter handling the // "right" way (updating // markers, not requiring string, etc. .. may need // to move to document // level) // allTextBuffer = // handleLineDelimiter(allTextBuffer, document); Reader reader = getResettableReader(); // be sure to test large "readers" ... we'll need // to make sure they all // can reset to initial position (StringReader, // CharArrayReader, and // DocumentReader should all work ok). reader.reset(); // There must be cleaner logic somehow, but the // idea is that // javaEncodingName can be null // if original detected encoding is not valid (and // if FORCE_DEFAULT was // not specified). Hence, we WANT the first // Charset.forName to // throw appropriate exception. Charset charset = null; // this call checks "override" properties file javaEncodingName = CodedIO.getAppropriateJavaCharset(javaEncodingName); if (javaEncodingName == null) { charset = Charset.forName(fCurrentEncodingMemento.getDetectedCharsetName()); } else { charset = Charset.forName(javaEncodingName); } CharsetEncoder charsetEncoder = charset.newEncoder(); if (!(encodingRule == EncodingRule.IGNORE_CONVERSION_ERROR)) { charsetEncoder.onMalformedInput(CodingErrorAction.REPORT); charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPORT); } else { charsetEncoder.onMalformedInput(CodingErrorAction.REPLACE); charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPLACE); } OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, charsetEncoder); // TODO: this may no longer be needed (and is at // least wrong spot for // it). // if (checkConversion && (!(encodingRule == // EncodingRule.IGNORE_CONVERSION_ERROR))) { // checkConversion(fCurrentEncodingMemento, // encodingRule); // } char[] charbuf = new char[CodedIO.MAX_BUF_SIZE]; int nRead = 0; try { while (nRead != -1) { nRead = reader.read(charbuf, 0, MAX_BUF_SIZE); if (nRead > 0) { outputStreamWriter.flush(); outputStreamWriter.write(charbuf, 0, nRead); } } } catch (UnmappableCharacterException e) { checkConversion(fCurrentEncodingMemento, encodingRule); } finally { // since we don't own the original output stream, we // won't close it ours. // the caller who passed it to us must close original one // when appropriate. // (but we do flush to be sure all up-to-date) outputStreamWriter.flush(); } }