All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nablarch.common.util.ParamsConvertor Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
package nablarch.common.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nablarch.common.web.hiddenencryption.TamperingDetectedException;

/**
 * パラメータマップとパラメータ文字列の変換を行うクラス。
* パラメータ文字列の作成時は、コンストラクタで指定されたセパレータを使用し、 * パラメータに含まれるセパレータはエスケープ処理する。 * @author Kiyohito Itoh */ public class ParamsConvertor { /** パラメータセパレータ */ private final char paramSeparator; /** name/valueセパレータ */ private final char nameValueSeparator; /** セパレータのエスケープ文字 */ private final char escapeChar; /** * コンストラクタ。 * @param paramSeparator パラメータセパレータ * @param nameValueSeparator name/valueセパレータ * @param escapeChar セパレータのエスケープ文字 */ public ParamsConvertor(char paramSeparator, char nameValueSeparator, char escapeChar) { this.paramSeparator = paramSeparator; this.nameValueSeparator = nameValueSeparator; this.escapeChar = escapeChar; } /** * パラメータマップからパラメータ文字列に変換する。
* パラメータ文字列は、コンストラクタで指定されたセパレータを使用して作成する。 * @param params パラメータマップ * @return パラメータ文字列 */ public String convert(Map> params) { StringBuilder sb = new StringBuilder(); for (Map.Entry> param : params.entrySet()) { for (String value : param.getValue()) { if (sb.length() != 0) { sb.append(paramSeparator); } escape(sb, param.getKey()); sb.append(nameValueSeparator); escape(sb, value); } } return sb.toString(); } /** * セパレータをエスケープした文字列を文字列バッファに追加する。 * @param sb 文字列バッファ * @param target ターゲット */ private void escape(StringBuilder sb, String target) { char[] str = target.toCharArray(); for (char c : str) { if (c == escapeChar) { sb.append(escapeChar).append(escapeChar); } else if (c == paramSeparator) { sb.append(escapeChar).append(paramSeparator); } else if (c == nameValueSeparator) { sb.append(escapeChar).append(nameValueSeparator); } else { sb.append(c); } } } /** * パラメータ文字列からパラメータマップに変換する。
* パラメータ文字列は、コンストラクタで指定されたセパレータを使用して作成されていることを想定する。 * @param params パラメータ文字列 * @return パラメータマップ */ public Map> convert(String params) { Map> paramsMap = new HashMap>(); StringBuilder param = new StringBuilder(); char[] paramStr = params.toCharArray(); try { for (int i = 0; i < paramStr.length; i++) { if (isParamSeparator(paramStr, i)) { unescapeNameValue(paramsMap, param); param = new StringBuilder(); continue; } param.append(paramStr[i]); } // 最後のパラメータセパレータ以降のアンエスケープ unescapeNameValue(paramsMap, param); return paramsMap; } catch (RuntimeException e) { throw new TamperingDetectedException(String.format("failed to convert. params = [%s], param = [%s]", params, param), e); } } /** * パラメータをアンエスケープし、パラメータを保持するマップに設定する。
* ただし、想定していないエスケープ文字が見つかった場合、name/valueセパレータが見つからない場合は不正なエスケープのため、 * {@link IllegalArgumentException}をスローする。 * @param listParams パラメータを保持するマップ * @param param パラメータ文字列 */ private void unescapeNameValue(Map> listParams, StringBuilder param) { StringBuilder name = new StringBuilder(); StringBuilder value = new StringBuilder(); boolean separatorFound = false; char[] nameValueStr = param.toString().toCharArray(); for (int i = 0; i < nameValueStr.length; i++) { char nameValueChar = nameValueStr[i]; // エスケープ文字 if (nameValueChar == escapeChar) { // エスケープ文字を捨てて、次の文字のみ使用 char next = nameValueStr[i + 1]; if (next == escapeChar) { nameValueChar = escapeChar; } else if (next == paramSeparator) { nameValueChar = paramSeparator; } else if (next == nameValueSeparator) { nameValueChar = nameValueSeparator; } else { throw new IllegalArgumentException( String.format("invalid escape sequence was found. nameValueStr = [%s]", String.valueOf(nameValueStr))); } i++; // name/valueセパレータ } else if (nameValueChar == nameValueSeparator) { // セパレータの出現有無を切り替え separatorFound = true; continue; } // セパレータの出現有無によりname又はvalueに追加 if (separatorFound) { value.append(nameValueChar); } else { name.append(nameValueChar); } } if (!separatorFound) { throw new IllegalArgumentException( String.format("invalid escape sequence was found. nameValueStr = [%s]", String.valueOf(nameValueStr))); } String key = name.toString(); if (!listParams.containsKey(key)) { listParams.put(key, new ArrayList()); } listParams.get(key).add(value.toString()); } /** * 文字列中のインデックス位置の文字がパラメータ間のセパレータかを判定する。
* ただし、先頭又は末尾がセパレータの場合は不正なエスケープのため、{@link IllegalArgumentException}をスローする。 * @param str 文字列 * @param index 現在のインデックス位置 * @return パラメータ間のセパレータの場合はtrue */ private boolean isParamSeparator(char[] str, final int index) { // インデックス位置の文字がセパレータでない if (str[index] != paramSeparator) { return false; } // インデックス位置の文字がセパレータ boolean isParamSeparator; // 先頭がセパレータの場合は不正なエスケープ if (index == 0) { throw new IllegalArgumentException( String.format("invalid escape sequence was found. str = [%s]", String.valueOf(str))); } // 1つ前の文字がエスケープ文字 if (str[index - 1] == escapeChar) { // 先頭に向かってエスケープ文字がどこまで連続するかカウント int escapeCount = 0; for (int i = index - 1; i >= 0; i--) { if (str[i] == escapeChar) { escapeCount++; } else { break; } } // カウント値が偶数の場合はセパレータ(エスケープされていないため) isParamSeparator = escapeCount % 2 == 0; // 1つ前の文字がエスケープ文字でない } else { isParamSeparator = true; } // 末尾がセパレータの場合は不正なエスケープ if (isParamSeparator && index == (str.length - 1)) { throw new IllegalArgumentException( String.format("invalid escape sequence was found. str = [%s]", String.valueOf(str))); } return isParamSeparator; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy