/* * Copyright (C) 2012 Works Applications Co., Ltd. * http://www.worksap.co.jp/ * * Licensed under the MIT License: * http://www.opensource.org/licenses/mit-license.php * */ package jp.co.worksap.message.wrapper; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; import javax.mail.Header; import jp.co.worksap.message.util.CharsetUtility; import jp.co.worksap.message.util.Encoding; public class CharsetGuesser { private static final int SIZE = 1024; public String guessCharset(Enumeration<?> e, InputStream input) { Set<String> charSets = guessCharset(e); for (String charset: charSets) { try { if (!charset.equals(Encoding.GB18030) && canDecode(input, Charset.forName(charset))) { return charset; } } catch (IOException ex) { continue; } } if (charSets.contains(Encoding.GB18030)) { return Encoding.GB18030; } return ""; } private Set<String> guessCharset(Enumeration<?> e) { Set<String> charSets = new HashSet<String>(); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o instanceof Header) { String value = ((Header) o).getValue().toLowerCase(); String charSet = CharsetUtility.getMappingCharSet(value); if (charSet.isEmpty()) { continue; } else { charSets.add(charSet); } } } return charSets; } private boolean canDecode(InputStream input, Charset charset) throws IOException { ReadableByteChannel channel = Channels.newChannel(input); CharsetDecoder decoder = charset.newDecoder(); ByteBuffer byteBuffer = ByteBuffer.allocate(SIZE * 2); CharBuffer charBuffer = CharBuffer.allocate(SIZE); boolean endOfInput = false; while (!endOfInput) { int n = channel.read(byteBuffer); byteBuffer.flip(); endOfInput = (n == -1); CoderResult coderResult = decoder.decode(byteBuffer, charBuffer, endOfInput); if (coderResult.isError()) { return false; } charBuffer.clear(); while (coderResult == CoderResult.OVERFLOW) { coderResult = decoder .decode(byteBuffer, charBuffer, endOfInput); charBuffer.clear(); } byteBuffer.compact(); } CoderResult coderResult; while ((coderResult = decoder.flush(charBuffer)) == CoderResult.OVERFLOW) { charBuffer.clear(); } if (coderResult.isError()) { return false; } return true; } }