001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.hayabusa.db; 017 018import org.opengion.fukurou.system.HybsConst ; // 6.1.0.0 (2014/12/26) 019import org.opengion.fukurou.util.ErrorMessage; 020import org.opengion.fukurou.util.StringUtil; 021import org.opengion.fukurou.model.NativeType; 022 023/** 024 * 一般的な半角文字列を扱う為の、カラム属性を定義します。 025 * 026 * 半角文字列とは、「 c < 0x20 || c > 0x7e 以外」でのみ 027 * 構成された文字列のことです。 028 * 029 * タイプチェックとして、以下の条件を判定します。 030 * ・文字列長は、Byte換算での文字数との比較 031 * ・半角文字列チェック「 c < 0x20 || c > 0x7e 以外」エラー 032 * ・文字パラメータの 正規表現チェック 033 * ・クロスサイトスクリプティングチェック 034 * 035 * @og.group データ属性 036 * 037 * @version 4.0 038 * @author Kazuhiko Hasegawa 039 * @since JDK5.0, 040 */ 041public abstract class AbstractDBType implements DBType { 042 private final String defValue ; // データのデフォルト値 043 044 /** システムの改行コードを設定します。*/ 045 protected static final String CR = HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 046 /** StringBilderなどの初期値を設定します。 {@value} */ 047 protected static final int BUFFER_MIDDLE = HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 048 049 /** 050 * デフォルトコンストラクター 051 * 052 * @og.rev 4.0.0.0 (2005/01/31) type 廃止 053 */ 054 public AbstractDBType() { 055 this( "" ); // データのデフォルト値 056 } 057 058 /** 059 * コンストラクター 060 * 061 * 各サブクラスのタイプ値とデフォルト値を設定して、オブジェクトを構築します。 062 * 063 * @og.rev 4.0.0.0 (2005/01/31) type 廃止 064 * 065 * @param defValue データのデフォルト値 066 */ 067 public AbstractDBType( final String defValue ) { 068 this.defValue = defValue; 069 } 070 071 /** 072 * NATIVEの型の識別コードを返します。 073 * 074 * @og.rev 3.5.4.7 (2004/02/06) 新規作成 075 * @og.rev 4.1.1.2 (2008/02/28) Enum型(fukurou.model.NativeType)に変更 076 * 077 * @return NATIVEの型の識別コード(DBType で規定) 078 * @og.rtnNotNull 079 * @see org.opengion.fukurou.model.NativeType 080 */ 081 public NativeType getNativeType() { 082 return NativeType.STRING; 083 } 084 085 /** 086 * 半角スペースで固定長(半角換算の数)に変換した文字列を返します。 087 * 088 * 半角スペース埋めは、文字が半角、全角混在でもかまいません。 089 * なお、エラーチェックは行われません。 090 * 実行前に、必ず valueCheck( String value ,int len ) を行う必要があります。 091 * 092 * @og.rev 3.5.4.5 (2004/01/23) エンコード指定に変更します。 093 * 094 * @param value FILL埋めする文字列 095 * @param sizeX 整数部分の文字列の長さ 096 * @param sizeY 小数部分の文字列の長さ 097 * @param encode 固定長で変換する文字エンコード 098 * 099 * @return FILL埋めした新しい文字列 100 * @og.rtnNotNull 101 */ 102 public String valueFill( final String value ,final int sizeX ,final int sizeY,final String encode ) { 103 final int len = (sizeY == 0) ? sizeX : sizeX + sizeY + 1; 104 105 return StringUtil.stringFill( value,len,encode ); 106 } 107 108 /** 109 * そのDBTypeの,デフォルトの値(物理的初期設定値)を返します。 110 * 111 * 一般に、文字列の場合は,ゼロストリング"" 数字の場合は "0" です。 112 * 113 * @return 物理的初期設定値 114 */ 115 public String getDefault() { 116 return defValue; 117 } 118 119 /** 120 * String引数の文字列を+1した文字列を返します。 121 * 122 * これは、英字の場合(A,B,C など)は、B,C,D のように,最終桁の文字コードを 123 * +1 します。 124 * 文字列が数字タイプの場合は, 数字に変換して、+1 します。 125 * 最終桁が、"9","z","Z" および、その全角文字の場合、"0","a","Z" および、その全角文字に 126 * 変換後、ひとつ上の桁で、同様の +1 操作を行います。 127 * 最も上位の桁が、これらの繰り上がり桁の場合は、すべての桁が初期化された状態に戻ります。 128 * 例:123 ⇒ 124 , ABC ⇒ ABD , 789 ⇒ 790 , XYZ ⇒ XXZ , 129 * ABC123 ⇒ ABC124 , AB99 ⇒ AC00 , 12ZZ99 ⇒ 13AA00 , ZZZZ ⇒ AAAA 130 * 引数が null の場合と、ゼロ文字列("")の場合は,物理的初期設定値(String getDefault()) 131 * の値を返します。 132 * 133 * @og.rev 4.0.0.0 (2005/01/31) Addの方法を変更(汎用的なAdd) 134 * 135 * @param value String引数 136 * 137 * @return 引数の文字列を+1した文字列。 138 */ 139 public String valueAdd( final String value ) { 140 if( value == null || value.isEmpty() ) { return getDefault(); } 141 142 char[] chs = value.toCharArray() ; 143 144 for( int i=chs.length-1; i>=0; i-- ) { 145 boolean over = true; 146 switch( chs[i] ) { 147 case '9' : chs[i] = '0' ; break; 148 case 'z' : chs[i] = 'a' ; break; 149 case 'Z' : chs[i] = 'A' ; break; 150 case '9' : chs[i] = '0'; break; 151 case 'z' : chs[i] = 'a'; break; 152 case 'Z' : chs[i] = 'A'; break; 153 default : chs[i]++; over=false; break; 154 } 155 if( !over ) { break; } // キャリーオーバーしていなければ、終了 156 } 157 158 return new String( chs ); 159 } 160 161 /** 162 * String引数の文字列に、第2引数に指定の文字列(数字、日付等)を加算して返します。 163 * 164 * これは、valueAdd( String ) と本質的には同じ動きをしますが、任意の文字列を加算する 165 * ため、主として、数字系や日付系の DBType にのみ実装します。 166 * 実装がない場合は、UnsupportedOperationException を throw します。 167 * 168 * 第2引数 が、null の場合は、+1 する valueAdd( String )が呼ばれます。 169 * これは、将来的には、valueAdd( String ) を無くすことを意味します。 170 * 171 * @og.rev 5.6.0.3 (2012/01/24) ADD に、引数の値を加算する機能を追加します。 172 * 173 * @param value String引数 174 * @param add 加算する文字列(null の場合は、従来と同じ、+1 します。) 175 * 176 * @return 引数の文字列第2引数に指定の文字列(数字、日付等)を加算した文字列。 177 * @throws UnsupportedOperationException 実装が存在しない場合 178 */ 179 public String valueAdd( final String value,final String add ) { 180 if( add == null || add.isEmpty() ) { return valueAdd( value ); } 181 182 final String errMsg = "このクラスでは、引数付の任意の加算は実装されていません。" 183 + getClass().getName() + " Action=[ADD]" 184 + " oldValue=[" + value + "] newValue=[" + add + "]" ; 185 throw new UnsupportedOperationException( errMsg ); 186 } 187 188 /** 189 * エディターで編集されたデータを登録する場合に、データそのものを変換して、実登録データを作成します。 190 * 191 * 例えば,大文字のみのフィールドなら、大文字化します。 192 * 実登録データの作成は、DBType オブジェクトを利用しますので, 193 * これと CellEditor とがアンマッチの場合は、うまくデータ変換 194 * されない可能性がありますので、注意願います。 195 * 196 * @og.rev 3.3.3.0 (2003/07/09) 前後のスペースを取り除いておく。 197 * @og.rev 3.3.3.1 (2003/07/18) 後ろスペースを取り除く。(StringUtil#rTrim) 198 * 199 * @param value (一般に編集データとして登録されたデータ) 200 * 201 * @return 修正後の文字列(一般にデータベースに登録するデータ) 202 */ 203 public String valueSet( final String value ) { 204 return StringUtil.rTrim( value ); 205 } 206 207 /** 208 * action で指定されたコマンドを実行して、値の変換を行います。 209 * 210 * oldValue(旧データ)は、元のDBTableModelに設定されていた値です。通常は、 211 * この値を使用してカラム毎に変換を行います。newValue(新データ)は、引数で 212 * 指定された新しい値です。この値には、パラメータを指定して変換方法を 213 * 制御することも可能です。 214 * 指定のアクションがカラムで処理できない場合は、エラーになります。 215 * 216 * @param action アクションコマンド 217 * @param oldValue 入力データ(旧データ) 218 * @param newValue 入力データ(新データ) 219 * 220 * @return 実行後のデータ 221 */ 222 public String valueAction( final String action,final String oldValue,final String newValue ) { 223 final String errMsg = "このクラスでは、このアクションは実装されていません。" 224 + getClass().getName() + " Action=[" + action + "]" 225 + " oldValue=[" + oldValue + "] newValue=[" + newValue + "]" ; 226 throw new UnsupportedOperationException( errMsg ); 227 } 228 229 /** 230 * データが登録可能かどうか[true/false]をチェックします。 231 * 232 * データがエラーの場合は、そのエラー内容を返します。 233 * 234 * @og.rev 2.1.1.1 (2002/11/15) HTMLタグチェックのメソッドの共有化。 235 * @og.rev 3.0.1.3 (2003/03/11) DBTypeCheckUtilクラスを利用するように修正 236 * @og.rev 3.6.0.0 (2004/09/22) dbType パラメータを引数に追加 237 * @og.rev 5.2.2.0 (2010/11/01) 厳密にチェック(isStrict=true)するフラグを追加 238 * 239 * @param key キー 240 * @param value 値 241 * @param sizeX 整数部分の文字列の長さ 242 * @param sizeY 小数部分の文字列の長さ 243 * @param typeParam dbType パラメータ 244 * @param isStrict 厳密にチェックするかどうか [true:する/false:標準的] 245 * 246 * @return エラー内容 247 */ 248 public ErrorMessage valueCheck( final String key ,final String value , 249 final int sizeX ,final int sizeY ,final String typeParam ,final boolean isStrict) { 250 251 ErrorMessage msg = new ErrorMessage(); 252 if( value == null || value.isEmpty() ) { return msg; } 253 254 final int len = (sizeY == 0) ? sizeX : sizeX + sizeY + 1; 255 if( len < value.length() ) { 256 // 文字列の長さが指定の長さよりも長いです。 257 msg.addMessage( 0,ErrorMessage.NG,"ERR0006",key,value, 258 String.valueOf( value.length() ),String.valueOf( len ) ); 259 } 260 261 final StringBuilder val = new StringBuilder( BUFFER_MIDDLE ); 262 boolean isError = false; 263 for( int i=0; i<value.length(); i++ ) { 264 final char ch = value.charAt( i ); 265 if( ch < 0x20 || ch > 0x7e ) { 266 val.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 267 isError = true; 268 } 269 else { 270 val.append( ch ); 271 } 272 } 273 if( isError ) { 274 // 指定の文字以外の文字が使われています。 275 msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,val.toString() ); 276 } 277 278 // 3.6.0.0 (2004/09/22) dbType パラメータを使用したマッチチェック 279 final String check = DBTypeCheckUtil.matcheCheck( value,typeParam ); 280 if( check != null ) { 281 // 指定の文字以外の文字が使われています。 282 msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,check ); 283 } 284 285 // クロスサイトスクリプティング対策:'<', '>' は登録させない。 286 msg = xssCheck( key ,value, msg ); 287 return msg; 288 } 289 290 /** 291 * HTMLタグかどうかをチェックします。 292 * 293 * クロスサイトスクリプティング対策として、'<', '>' は登録させない。 294 * 295 * @og.rev 2.1.1.1 (2002/11/15) HTMLタグチェックのメソッドの共有化。 296 * @og.rev 6.2.0.0 (2015/02/27) ERR0010 の引数が、変更されているので、修正します。 297 * 298 * @param key タグのキー 299 * @param value 対象の値 300 * @param msg ErrorMessageオブジェクト 301 * 302 * @return エラー内容(エラーを追加した、ErrorMessageオブジェクト) 303 */ 304 protected ErrorMessage xssCheck( final String key ,final String value, final ErrorMessage msg ) { 305 final StringBuilder val = new StringBuilder( BUFFER_MIDDLE ); 306 boolean isError = false; 307 for( int i=0; i<value.length(); i++ ) { 308 final char ch = value.charAt( i ); 309 if( ch == '<' || ch == '>' ) { 310 val.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" ); 311 isError = true; 312 } 313 else { 314 val.append( ch ); 315 } 316 } 317 if( isError ) { 318 // 6.2.0.0 (2015/02/27) ERR0010:HTMLタグは登録できません。key={0} value={1}({2}) char={3} 319 // {2} が何を想定していたのか不明ですが、エラー発生元のクラス名を設定しておきます。 320 final String clsName = this.getClass().getSimpleName(); 321 322 // HTMLタグは登録できません。 323 msg.addMessage( 0,ErrorMessage.NG,"ERR0010", key,val.toString(),clsName,"<,>" ); 324 } 325 return msg; 326 } 327}