/*
* Copyright 2004-2012 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.mayaa.impl.engine;
import org.seasar.mayaa.impl.CONST_IMPL;
import org.seasar.mayaa.impl.util.StringUtil;
/**
* テンプレート上のmetaタグでのcharset表記、およびHTTPレスポンスのcharset表記を
* テンプレートで指定したcharset、およびmayaaファイルのm:contentTypeで指定した
* charsetから異なるcharset表記にするためのクラス。
*
* 用途はWindows-31JとShift_JISの組み合わせ以外ないと想定しているため、現在は
* 最低限の実装。もし汎用性が必要ならばこのクラスをAPIに昇格し、ServiceProvider
* で取得できるようにする。
*
* @author Koji Suga (Gluegent Inc.)
* @version 1.1.12
*/
public class CharsetConverter {
/** 変換が有効か */
private static volatile boolean _enabled = false;
/**
* 変換の有効/無効を設定します。
*
* @param enabled 有効にするならtrue
*/
public static void setEnabled(boolean enabled) {
_enabled = enabled;
}
/**
* contentType中のcharsetの値を探し、前後のindexを返します。
* 戻り値をindexとすると、contentType.substring(index[0], index[1])で
* charsetの値 (UTF-8など) を取り出せます。
* 見つからない場合はnullを返します。
*
* @param contentType charsetを探すcontent-type
* @return charsetの前後のindex。見つからない場合はnull
*/
private static int[] getCharsetIndex(String contentType) {
if (StringUtil.hasValue(contentType)) {
String lower = contentType.toLowerCase();
int startIndex = lower.indexOf("charset");
if (startIndex > 0) {
startIndex += 7; /*7 = "charset".length()*/
final int eqIndex = contentType.indexOf("=", startIndex);
if (eqIndex > 0) {
int endIndex = contentType.indexOf(";", eqIndex);
if (endIndex < 0) {
endIndex = contentType.length();
}
return new int[] { eqIndex + 1, endIndex };
}
}
}
return null;
}
/**
* contentTypeからcharsetを抽出して返します。
* charsetが存在しない場合はデフォルトのUTF-8を返します。
* また、必要ならばcharsetをencoding用に変換して返します。
*
* @param contentType charset表記を含むcontentType
* @return 抽出したcharsetをencodingとして使うための名前。
*/
public static String extractEncoding(String contentType) {
int[] index = getCharsetIndex(contentType);
if (index != null) {
String charset = contentType.substring(index[0], index[1]).trim();
return charsetToEncoding(charset);
}
return CONST_IMPL.TEMPLATE_DEFAULT_CHARSET;
}
/**
* contentTypeのcharsetをencodingと見なし、charsetに変換したものを返します。
* また、charsetを含まない場合はutf-8のcharsetを付与して返します。
* 特に変換する必要がない場合は引数をそのまま返します。
*
* @param contentType 変換するcharset表記を含むcontentType
* @return 変換後のcontentType。
*/
public static String convertContentType(String contentType) {
int[] index = getCharsetIndex(contentType);
if (index == null) {
if (StringUtil.hasValue(contentType)) {
if (contentType.charAt(contentType.length() - 1) == ';') {
return contentType + " charset=UTF-8";
}
return contentType + "; charset=UTF-8";
}
return contentType;
}
if (_enabled) {
String charset = contentType.substring(index[0], index[1]).trim();
return contentType.substring(0, index[0]) +
encodingToCharset(charset) + contentType.substring(index[1]);
}
return contentType;
}
/**
* charset表記に対応するencoding名を取得します。
* 特に変換する必要がない場合は引数をそのまま返します。
*
* @param charset 変換するcharset表記
* @return 引数に対応するencoding名、または引数そのもの。
*/
public static String charsetToEncoding(String charset) {
if (_enabled && "Shift_JIS".equalsIgnoreCase(charset)) {
return "Windows-31J";
}
return charset;
}
/**
* encoding名に対応するcharset表記を取得します。
* 特に変換する必要がない場合は引数をそのまま返します。
*
* @param encoding 変換するencoding名
* @return 引数に対応するcharset表記、または引数そのもの。
*/
public static String encodingToCharset(String encoding) {
if (_enabled && "Windows-31J".equalsIgnoreCase(encoding)) {
return "Shift_JIS";
}
return encoding;
}
}