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 */ 016 package org.opengion.fukurou.taglet; 017 018 import org.opengion.fukurou.util.LogWriter; 019 020 import java.util.Set; 021 import java.util.HashSet; 022 import java.io.IOException; 023 import java.lang.reflect.Field; 024 025 import com.sun.javadoc.RootDoc; 026 import com.sun.javadoc.ClassDoc; 027 import com.sun.javadoc.MethodDoc; 028 import com.sun.javadoc.FieldDoc; 029 import com.sun.javadoc.Doc; 030 import com.sun.javadoc.ConstructorDoc; 031 import com.sun.javadoc.ExecutableMemberDoc; 032 import com.sun.javadoc.Type; 033 import com.sun.javadoc.Parameter; 034 import com.sun.javadoc.Tag; 035 import com.sun.javadoc.SourcePosition; 036 import com.sun.javadoc.AnnotationDesc; 037 import com.sun.javadoc.AnnotationTypeDoc; 038 039 /** 040 * ソースコメントから?タグ??を取り??Doclet クラスです? 041 * クラスファイルの仕様を表現する為、og.formSample , og.rev , og.group , 042 * version , author , since の?グコメントより?を抽出します? 043 * また??ラスの継承関係?インターフェース、メソ?なども抽出します? 044 * これら?抽出結果をDB化し、EXCELファイルに帳票出力する事で、クラスファイルの 045 * ソースから仕様書を?作?します? 046 * 047 * @version 4.0 048 * @author Kazuhiko Hasegawa 049 * @since JDK5.0, 050 */ 051 public final class DocletSpecific { 052 private static final String SELECT_PACKAGE = "org.opengion" ; 053 private static final boolean NOT_PRIVATE = false ; 054 private static final String ENCODE = "UTF-8"; 055 056 private static final String OG_FOR_SMPL = "og.formSample"; 057 private static final String OG_REV = "og.rev"; 058 private static final String OG_GROUP = "og.group"; 059 private static final String DOC_VERSION = "version"; 060 private static final String DOC_AUTHOR = "author"; 061 private static final String DOC_SINCE = "since"; 062 063 private static final String DOC_PARAM = "param"; // 5.1.9.0 (2010/08/01) チェ?用 064 private static final String DOC_RETURN = "return"; // 5.1.9.0 (2010/08/01) チェ?用 065 066 private static final String CONSTRUCTOR = "コンストラクタ" ; 067 private static final String METHOD = "メソ?" ; 068 private static final Set<String> methodSet = new HashSet<String>(); 069 070 private static int debugLevel = 0; // 0:な? 1:?チェ? 2:日本語化 3:体? 071 072 /** 073 * すべて?staticメソ?なので、コンストラクタを呼び出さなくしておきます? 074 * 075 */ 076 private DocletSpecific() {} 077 078 /** 079 * Doclet のエントリポイントメソ?です? 080 * 081 * @og.rev 5.5.4.1 (2012/07/06) Tag出力時の CR ?BR 変換を行わな?にする? 082 * 083 * @param root エントリポイント?RootDocオブジェク? 084 * 085 * @return 正常実行時 true 086 */ 087 public static boolean start( final RootDoc root ) { 088 String version = DocletUtil.getOption( "-version" , root.options() ); 089 String file = DocletUtil.getOption( "-outfile" , root.options() ); 090 String dbgLvl = DocletUtil.getOption( "-debugLevel" , root.options() ); // 5.5.4.1 (2012/07/06) パラメータ引数 091 if( dbgLvl != null ) { debugLevel = Integer.parseInt( dbgLvl ); } 092 093 DocletTagWriter writer = null; 094 try { 095 // writer = new DocletTagWriter( file,ENCODE,true ); 096 writer = new DocletTagWriter( file,ENCODE ); // 5.5.4.1 (2012/07/06) 097 098 writer.printTag( "<?xml version=\"1.0\" encoding=\"", ENCODE, "\" ?>" ); 099 writer.printTag( "<javadoc>" ); 100 writer.printTag( " <version>",version,"</version>" ); 101 writer.printTag( " <description></description>" ); 102 writeContents( root.classes(),writer ); 103 writer.printTag( "</javadoc>" ); 104 } 105 catch( IOException ex ) { 106 LogWriter.log( ex ); 107 } 108 finally { 109 if( writer != null ) { writer.close(); } 110 } 111 return true; 112 } 113 114 /** 115 * ClassDoc 配?よりコン??作?します? 116 * 117 * @og.rev 5.5.4.1 (2012/07/06) コメント???でなく?Tag配?として処?せる? 118 * @og.rev 5.6.6.0 (2013/07/05) VERSION staticフィールドと、@og.rev コメント?比?ェ? 119 * 120 * @param classes ClassDoc配? 121 * @param writer Tagを書き?すWriterオブジェク? 122 */ 123 private static void writeContents( final ClassDoc[] classes,final DocletTagWriter writer ) { 124 for(int i=0; i< classes.length; i++) { 125 ClassDoc classDoc = classes[i] ; 126 String className = classDoc.name(); 127 String fullName = classDoc.qualifiedName() ; 128 String modifiers = (classDoc.modifiers() 129 + ( classDoc.isClass() ? " class" : "" ) ).trim(); 130 131 Type superType = classDoc.superclassType(); 132 String superClass = ( superType == null ) ? "" : superType.qualifiedTypeName(); 133 134 Type[] interfaceTypes = classDoc.interfaceTypes(); 135 StringBuilder buf = new StringBuilder( 200 ); 136 for( int j=0; j<interfaceTypes.length; j++ ) { 137 buf.append( interfaceTypes[j].qualifiedTypeName() ).append( "," ); 138 } 139 if( interfaceTypes.length > 0 ) { buf.deleteCharAt( buf.length()-1 ); } 140 String intFase = buf.toString(); 141 142 Tag[] desc = classDoc.firstSentenceTags(); 143 // String cmnt = DocletUtil.htmlFilter( classDoc.commentText() ); // 5.5.4.1 (2012/07/06) 144 Tag[] cmnt = classDoc.inlineTags(); // 5.5.4.1 (2012/07/06) 145 Tag[] smplTags = classDoc.tags(OG_FOR_SMPL); 146 Tag[] revTags = classDoc.tags(OG_REV); 147 Tag[] createVer = classDoc.tags(DOC_VERSION); 148 Tag[] author = classDoc.tags(DOC_AUTHOR); 149 Tag[] since = classDoc.tags(DOC_SINCE); 150 Tag[] grpTags = classDoc.tags(OG_GROUP); 151 152 writer.printTag( "<classDoc>" ); 153 writer.printTag( " <fullName>" ,fullName ,"</fullName>" ); 154 writer.printTag( " <modifiers>" ,modifiers ,"</modifiers>" ); 155 writer.printTag( " <className>" ,className ,"</className>" ); 156 writer.printTag( " <superClass>" ,superClass ,"</superClass>" ); 157 writer.printTag( " <interface>" ,intFase ,"</interface>" ); 158 writer.printTag( " <createVer>" ,createVer ,"</createVer>" ); 159 writer.printTag( " <author>" ,author ,"</author>" ); 160 writer.printTag( " <since>" ,since ,"</since>" ); 161 writer.printTag( " <description>" ,desc ,"</description>" ); 162 writer.printTag( " <contents>" ,cmnt ,"</contents>" ); 163 writer.printTag( " <classGroup>" ); 164 writer.printCSVTag( grpTags ); 165 writer.printTag( "</classGroup>" ); 166 writer.printTag( " <formSample>" ,smplTags ,"</formSample>" ); 167 writer.printTag( " <history>" ,revTags ,"</history>" ); 168 169 // 5.1.9.0 (2010/08/01) ソースチェ?用(コメントや概要が無??合?スーパ?クラスは省く) 170 // if( ( cmnt.length() == 0 || desc.length == 0 ) && superClass.length() == 0 ) { 171 if( debugLevel >= 2 && ( cmnt.length == 0 || desc.length == 0 ) && superClass.length() == 0 ) { 172 System.err.println( "警?:コメン?=\t" + classDoc.position() ); 173 } 174 175 // methodSet.clear(); // 5.5.4.1 (2012/07/06) メソ?の重???定?、クラス名も含めて行うので、clear() しな?? 176 int extendFlag = 0; // 0:オリジナル 1:org.opengion関連Extend 2:Java関連Extend 177 // while( fullName.startsWith( SELECT_PACKAGE ) ) { 178 179 // 5.6.6.0 (2013/07/05) VERSION staticフィールドと、@og.rev コメント?比?ェ? 180 // while 以下で、fullName と classDoc を?番に上にさかのぼって?ので、?にチェ?します? 181 checkTag2( fullName,classDoc ); 182 183 while( true ) { 184 // ConstructorDoc[] cnstrctrs = classDoc.constructors(); 185 ConstructorDoc[] cnstrctrs = classDoc.constructors( false ); // 5.1.9.0 (2010/08/01) チェ?用 186 for(int j=0; j < cnstrctrs.length; j++) { 187 if( isAction( cnstrctrs[j],extendFlag ) ) { 188 if( extendFlag < 2 ) { checkTag( cnstrctrs[j] ); } // 5.5.4.1 (2012/07/06) チェ?を?離 189 menberTag( cnstrctrs[j],CONSTRUCTOR,writer,extendFlag ); 190 } 191 } 192 193 // MethodDoc[] methods = classDoc.methods(); 194 MethodDoc[] methods = classDoc.methods( false ); // 5.1.9.0 (2010/08/01) チェ?用 195 for(int j=0; j < methods.length; j++) { 196 if( isAction( methods[j],extendFlag ) ) { 197 if( extendFlag < 2 ) { checkTag( methods[j] ); } // 5.5.4.1 (2012/07/06) チェ?を?離 198 menberTag( methods[j],METHOD,writer,extendFlag ); 199 } 200 } 201 202 // 対象クラス(オリジナル)から、上に上がって?? 203 Type type = classDoc.superclassType(); 204 if( type == null ) { break; } 205 classDoc = type.asClassDoc() ; 206 fullName = classDoc.qualifiedName(); 207 // java.lang.Object クラスは対象が多いため、??ません? 208 if( "java.lang.Object".equals( fullName ) || classDoc.isEnum() ) { 209 break; 210 } 211 else if( fullName.startsWith( SELECT_PACKAGE ) ) { 212 extendFlag = 1; 213 } 214 else { 215 extendFlag = 2; 216 } 217 } 218 219 writer.printTag( " </classDoc>" ); 220 } 221 } 222 223 /** 224 * メンバ?クラスのXML化を行うかど?[true/false]を判定します? 225 * 226 * 以下?条件に合?する場合?、??行いません?false を返します?) 227 * 228 * ?.同?ラスを??にEXTENDで継承?さかのぼる?合?すでに同じシグネチャのメソ?? 229 * 存在して?? 230 * ?.NOT_PRIVATE ?true の時? private メソ? 231 * ?.extendFlag ?0以?1,2)の時? private メソ? 232 * ?.メソ?名におかしな記号(<など)が含まれて?場? 233 * 234 * @og.rev 5.5.4.1 (2012/07/06) メソ?の重???定?、クラス名も含めて行う 235 * 236 * @param menber ExecutableMemberDocオブジェク? 237 * @param extendFlag 0:オリジナル 1:org.opengion関連Extend 2:Java関連Extend 238 * 239 * @return XML化を行うかど?[true/false] 240 */ 241 private static boolean isAction( final ExecutableMemberDoc menber,final int extendFlag ) { 242 String menberName = menber.name() ; 243 // String signature = menberName + menber.signature(); 244 // boolean rtn = ( ! methodSet.add( signature ) ) 245 boolean rtn = ( ! methodSet.add( menber.toString() ) ) // 5.5.4.1 (2012/07/06) メソ?の重???定?、クラス名も含めて行う 246 || ( NOT_PRIVATE && menber.isPrivate() ) 247 || ( extendFlag > 0 && menber.isPrivate() ) 248 || ( menberName.charAt(0) == '<' ) ; 249 250 return ! rtn ; 251 } 252 253 // 5.1.9.0 (2010/08/01) ソースチェ?用(半角文字+空白??み) 254 private static java.util.regex.Pattern PTN = java.util.regex.Pattern.compile("[\\w\\s]+"); 255 256 /** 257 * param,return 等?整合?をチェ?します? 258 * 259 * @og.rev 5.5.4.1 (2012/07/06) 新規作?? 260 * @og.rev 5.6.6.1 (2013/07/12) Deprecated アノテーション のチェ? 261 * 262 * @param menber ExecutableMemberDocオブジェク? 263 */ 264 private static void checkTag( final ExecutableMemberDoc menber ) { 265 266 // 親?Enum クラスの場合?処?ません? 267 Type prntType = menber.containingClass().superclassType(); 268 String prntClass = ( prntType == null ) ? "" : prntType.qualifiedTypeName(); 269 if( "java.lang.Enum".equals( prntClass ) ) { return; } 270 271 SourcePosition posi = menber.position(); 272 String modifiers = null; 273 274 if( menber instanceof MethodDoc ) { 275 // メソ?の処?コンストラクターを省? 276 Type rtnType = ((MethodDoc)menber).returnType(); 277 String typNm = rtnType.typeName(); 278 279 StringBuilder modifyBuf = new StringBuilder( 200 ); 280 modifyBuf.append( menber.modifiers() ).append( " " ).append( typNm ); 281 if( rtnType.dimension() != null ) { modifyBuf.append( rtnType.dimension() ); } 282 modifiers = modifyBuf.toString(); 283 284 String wormMsg = "=\t" + posi + "\t" + modifiers ; 285 286 // 5.1.9.0 (2010/08/01) ソースチェ?用(@return との整合?チェ?) 287 Tag[] docReturn = menber.tags(DOC_RETURN); // 5.1.9.0 (2010/08/01) チェ?用 288 if( docReturn.length > 0 ) { 289 String data = (docReturn[0].text()).trim(); // 5.5.4.1 (2012/07/06) trim でスペ?ス等?削除 290 wormMsg = wormMsg + "\t" + data ; 291 292 // 5.5.4.1 (2012/07/06) ソースチェ?用(@return と引数の個数が異なる?? 293 if( debugLevel >= 1 && "void".equals( typNm ) ) { 294 System.err.println( "警?:RTNコメント不? + wormMsg ); 295 } 296 // ?@return 解説? の形式で、解説に日本語がなければ、警? 297 // if( debugLevel >= 2 && PTN.matcher( data ).matches() && data.indexOf( ' ' ) < 0 && data.indexOf( '\t' ) < 0 ) { 298 if( debugLevel >= 2 && PTN.matcher( data ).matches() ) { 299 System.err.println( "警?:RTN未解説" + wormMsg ); 300 } 301 // ?@return String? の形式?場合?警? 302 if( debugLevel >= 2 && data.equals( typNm ) ) { 303 System.err.println( "警?:RTN??" + wormMsg ); 304 } 305 // ?@return String[]? など??列や?String>などが含まれる場合?警? 306 if( debugLevel >= 2 && ( data.indexOf( "[]" ) >= 0 || data.indexOf( '<' ) >= 0 ) ) { 307 System.err.println( "警?:RTN配?" + wormMsg ); 308 } 309 // ?@return String 解説? の場合?警?後ろにスペ?スか?タブがある場? 310 if( debugLevel >= 3 && (data.indexOf( typNm + " " ) >= 0 || data.indexOf( typNm + "\t" ) >= 0 ) ) { 311 System.err.println( "警?:RTNタイ? + wormMsg ); 312 } 313 // ?@return xxxx 解説? の場合で、最初?スペ?スまでが?すべて英数字?みの場合?警? 314 int adrs1 = data.indexOf( ' ' ); 315 if( debugLevel >= 3 && adrs1 > 0 ) { 316 boolean flag = true; 317 for( int j=0; j<adrs1; j++ ) { 318 char ch = data.charAt( j ); 319 if( ( ch < '0' || ch > '9' ) && ( ch < 'a' || ch > 'z' ) && ( ch < 'A' || ch > 'Z' ) && ch != '[' && ch != ']' ) { 320 flag = false; // 英数字でな?号が現れた場? 321 break; 322 } 323 } 324 if( flag ) { // すべてが英数字?場合?? 325 System.err.println( "警?:RTN値" + wormMsg ); 326 } 327 } 328 } 329 else { // Tag上には、@return 記述が存在しな?? 330 // 5.5.4.1 (2012/07/06) ソースチェ?用(@return と引数の個数が異なる?? 331 if( debugLevel >= 1 && !"void".equals( typNm ) ) { 332 System.err.println( "警?:RTNコメントな? + wormMsg ); 333 } 334 } 335 336 // オーバ?ライドチェ??アノテーションの記述漏れ 337 // そ???、コンパイラが警告してくれる? 338 MethodDoc mdoc= ((MethodDoc)menber).overriddenMethod(); 339 if( debugLevel >= 3 && mdoc != null ) { 340 AnnotationDesc[] annotations = menber.annotations(); 341 // 本来は、Override の有無を調べるべきだが?Deprecated と SuppressWarnings の付いて? 342 // 旧のメソ?に、いち?Overrideを付けな??で、何もなければと条件を緩めます? 343 if( annotations.length == 0 ) { 344 System.err.println( "警?:@Overrideな? + wormMsg ); 345 } 346 } 347 } 348 349 Parameter[] prm = menber.parameters(); 350 351 // 5.1.9.0 (2010/08/01) ソースチェ?用(@param と引数の個数が異なる?? 352 Tag[] docParam = menber.tags(DOC_PARAM); // 5.1.9.0 (2010/08/01) チェ?用 353 if( debugLevel >= 1 && docParam.length != prm.length ) { 354 System.err.println( "警?:PRM個数違い=\t" + posi ); 355 } 356 357 for( int k=0; k<prm.length; k++ ) { 358 String typNm = prm[k].type().typeName(); 359 String prmNm = prm[k].name(); 360 361 // 5.1.9.0 (2010/08/01) ソースチェ?用(@param と引数の個数が異なる?? 362 if( docParam.length > k ) { 363 String data = (docParam[k].text()).trim(); // 5.5.4.1 (2012/07/06) trim でスペ?ス等?削除 364 String data2 = data.replaceAll( prmNm,"" ).trim(); 365 String data3 = data2.replaceAll( typNm,"" ).replaceAll( "\\[\\]","" ).trim(); 366 String wormMsg = "=\t" + posi + "\t" + data ; 367 368 // ?@param aaa 解説?形式で、aaa(引数?がな??? 369 if( debugLevel >= 1 && data.indexOf( prmNm ) < 0 ) { 370 System.err.println( "警?:PRM引数? + wormMsg ); 371 } 372 // 引数の??の長さが?文字?場? 373 if( debugLevel >= 2 && prmNm.length() == 1 ) { 374 System.err.println( "警?:PRM短? + wormMsg ); 375 } 376 // ?@param aaa 解説?形式で、解説に日本語がな??また?、解説がなければ、警? 377 // if( debugLevel >= 2 && PTN.matcher( data ).matches() && data.indexOf( ' ' ) < 0 && data.indexOf( '\t' ) < 0 ) { 378 if( debugLevel >= 2 && ( PTN.matcher( data2 ).matches() || data3.length() == 0 ) ) { 379 System.err.println( "警?:PRM未解説" + wormMsg ); 380 } 381 // ?@param aaa String[]?など??列や?String>などが含まれる場合?警? 382 if( debugLevel >= 2 && ( data.indexOf( "[]" ) >= 0 || data.indexOf( '<' ) >= 0 ) ) { 383 System.err.println( "警?:PRM配?" + wormMsg ); 384 } 385 // ?@param aaa 解説?形式で、String が有って、その後ろにスペ?スか?タブがあれば警? 386 // data2 を使??は、パラメータ?xxxMap)にタイプ名(Map)が含まれて?ケースの対? 387 if( debugLevel >= 3 && (data2.indexOf( typNm + " " ) >= 0 || data2.indexOf( typNm + "\t" ) >= 0 ) ) { 388 System.err.println( "警?:PRMタイ? + wormMsg ); 389 } 390 // ?@param aaa 解説?形式で、解説がな??? 391 // if( debugLevel >= 3 && data3.length() == 0 ) { 392 // System.err.println( "警?:PRM解説な? + wormMsg ); 393 // } 394 } 395 } 396 397 Tag[] desc = menber.firstSentenceTags(); 398 Tag[] cmnt = menber.inlineTags(); // 5.5.4.1 (2012/07/06) 399 // String extClass = ( extendFlag == 0 ) ? "" : menber.containingClass().qualifiedName() ; 400 401 // 5.1.9.0 (2010/08/01) ソースチェ?用 402 if( ( cmnt.length == 0 || desc.length == 0 ) // コメントや概要が無? 403 // && extClass.length() == 0 // 拡張クラスが存在しな? 404 && ( menber instanceof MethodDoc ) // メソ?に限? 405 && !menber.isSynthetic() // コンパイラによって合?されて?? 406 && !menber.isNative() // ネイ?ブメソ?でな? 407 && debugLevel >= 2 ) { // debugLevel ?2 以? 408 409 // さらに、親?Enum クラス以? 410 // Type prntType = menber.containingClass().superclassType(); 411 // String prntClass = ( prntType == null ) ? "" : prntType.qualifiedTypeName(); 412 // if( debugLevel >= 2 && !"java.lang.Enum".equals( prntClass ) ) { 413 System.err.println( "警?:コメン?=" + "\t" + posi + "\t" + menber.name() ); 414 // } 415 } 416 417 // 5.6.6.1 (2013/07/12) Deprecated アノテーション のチェ? 418 AnnotationDesc[] descList = menber.annotations(); 419 for( int i=0; i<descList.length; i++ ) { 420 AnnotationTypeDoc annDoc = descList[i].annotationType(); 421 if( "Deprecated".equalsIgnoreCase( annDoc.name() ) ) { 422 String text = menber.commentText(); 423 if( text != null && text.indexOf( "【?? ) < 0 ) { 424 System.err.println( "警?:【??" + "\t" + posi + "\t" + menber.name() ); 425 } 426 } 427 } 428 } 429 430 /** 431 * VERSION staticフィールドと、@og.rev コメント?比?ェ?を行います? 432 * 433 * @og.rev 5.6.6.0 (2013/07/05) 新規作? 434 * 435 * @param fullName オリジナルのクラス? 436 * @param classDoc ClassDocオブジェク? 437 */ 438 private static void checkTag2( final String fullName, final ClassDoc classDoc ) { 439 String cnstVar = getFieldVERSION( fullName ) ; // VERSION ?? ?5.6.6.0 (2013/07/05) 440 String seriUID = getSerialVersionUID( fullName ) ; // serialVersionUID ?566020130705L 441 442 // VERSION ?? か?serialVersionUID のどちらかがあれ?処?ます? 443 if( cnstVar != null || seriUID != null ) { 444 SourcePosition posi = null; 445 446 String maxRev = ( cnstVar != null ) ? cnstVar : "4.0.0.0 (2005/01/31)" ; // Ver4 の?古? 447 int lenVar = maxRev.length(); // 比?に使用する長? 448 boolean isChange = false; // max が?れ替わったら、true 449 450 // 本体?コンストラクタ、フィールド?メソ??ら??の @og.rev の値を取得します? 451 Doc[][] docs = new Doc[4][] ; 452 453 docs[0] = new Doc[] { classDoc } ; 454 docs[1] = classDoc.constructors( false ) ; 455 docs[2] = classDoc.fields( false ) ; 456 docs[3] = classDoc.methods( false ) ; 457 458 for( int i=0; i<docs.length; i++ ) { 459 for( int j=0; j < docs[i].length; j++ ) { 460 Doc doc = docs[i][j]; 461 462 Tag[] revTags = doc.tags(OG_REV); 463 for( int k=0 ; k<revTags.length; k++ ) { 464 String rev = revTags[k].text(); 465 466 if( rev.length() < lenVar ) { 467 System.err.println( "警?:og.revが短?" + "\t" + rev + "\t" + doc.position() ); 468 continue; 469 } 470 471 rev = rev.substring( 0,lenVar ); 472 if( maxRev.compareTo( rev ) < 0 ) { // revTags の og.rev が大きい場? 473 maxRev = rev ; 474 posi = doc.position(); // ?に入れ替わった位置 = ?のrevの位置 475 isChange = true; 476 } 477 } 478 } 479 } 480 481 // VERSION ?? の定義があり?かつ、max の入れ替えが発生した?合?み、警?:VERSIONが古? 482 if( cnstVar != null && isChange ) { 483 System.err.println( "警?:VERSIONが古?" + "\t" + cnstVar + " ?" + maxRev + "\t" + posi ); 484 } 485 486 // serialVersionUID の定義がある? 487 if( seriUID != null ) { 488 StringBuilder buf = new StringBuilder(); 489 // maxRev は、最大の Revか?初期のVERSION?? ?5.6.6.0 (2013/07/05) 490 for( int i=0; i<maxRev.length(); i++ ) { // 491 char ch = maxRev.charAt( i ); 492 if( ch >= '0' && ch <= '9' ) { buf.append( ch ); } // 数字だけ取り?す? ?566020130705 493 } 494 if( !seriUID.equals( buf.toString() ) ) { 495 // 以下?処??、serialVersionUID のソースの位置(posi)を取り?すためだけに使用して?す? 496 FieldDoc[] fileds = classDoc.fields( false ); 497 for( int i=0; i<fileds.length; i++ ) { 498 FieldDoc filed = fileds[i]; 499 // private static final long serialVersionUID で宣?れて?ので? 500 if( filed.isPrivate() && filed.isStatic() && filed.isFinal() ) { 501 String nm = filed.qualifiedName(); 502 if( nm.endsWith( "serialVersionUID" ) ) { 503 // String val = filed.constantValueExpression(); // これは、serialVersionUID の設定?の取得サンプル 504 posi = filed.position(); 505 } 506 } 507 } 508 System.err.println( "警?:serialVersionUIDが古?" + "\t" + seriUID + " ?" + buf.toString() + "L\t" + posi ); 509 } 510 } 511 } 512 } 513 514 /** 515 * メンバ?クラス(コンストラクタ、メソ?)をXML化します? 516 * 517 * @og.rev 5.5.4.1 (2012/07/06) コメント???でなく?Tag配?として処?せる? 518 * 519 * @param menber ExecutableMemberDocオブジェク? 520 * @param menberType メンバ?タイ?コンストラクタ、メソ?) 521 * @param writer Tagを書き?すWriterオブジェク? 522 * @param extendFlag 0:オリジナル 1::org.opengion関連Extend 2:Java関連Extend 523 */ 524 private static void menberTag( final ExecutableMemberDoc menber, 525 final String menberType, 526 final DocletTagWriter writer, 527 final int extendFlag ) { 528 529 final String modifiers ; 530 if( menber instanceof MethodDoc ) { 531 // メソ?の処? 532 Type rtnType = ((MethodDoc)menber).returnType(); 533 StringBuilder modifyBuf = new StringBuilder( 200 ); 534 modifyBuf.append( menber.modifiers() ); 535 // modifyBuf.append( " " ).append( rtnType.qualifiedTypeName() ); 536 modifyBuf.append( " " ).append( rtnType.typeName() ); 537 if( rtnType.dimension() != null ) { modifyBuf.append( rtnType.dimension() ); } 538 539 modifiers = modifyBuf.toString(); 540 } 541 else { 542 // コンストラクター処? 543 modifiers = menber.modifiers(); 544 } 545 546 String menberName = menber.name(); 547 548 StringBuilder sigBuf = new StringBuilder( 200 ); 549 sigBuf.append( menberName ).append( "(" ) ; 550 Parameter[] prm = menber.parameters(); 551 552 for( int k=0; k<prm.length; k++ ) { 553 // sigBuf.append( prm[k].toString() ).append( "," ); 554 Type ptyp = prm[k].type(); 555 String prmNm =prm[k].name(); 556 557 sigBuf.append( ptyp.typeName() ).append( ptyp.dimension() ).append( " " ) 558 .append( prmNm ).append( "," ); 559 } 560 561 if( prm.length > 0 ) { sigBuf.deleteCharAt( sigBuf.length()-1 ); } 562 sigBuf.append( ")" ); 563 String signature = sigBuf.toString(); 564 565 Tag[] desc = menber.firstSentenceTags(); 566 // String cmnt = DocletUtil.htmlFilter( menber.commentText() ); // 5.5.4.1 (2012/07/06) 567 Tag[] cmnt = menber.inlineTags(); // 5.5.4.1 (2012/07/06) 568 Tag[] tags = menber.tags(); 569 Tag[] revTags = menber.tags(OG_REV); 570 String extend = String.valueOf( extendFlag ); 571 String extClass = ( extendFlag == 0 ) ? "" : menber.containingClass().qualifiedName() ; 572 573 String position = String.valueOf( menber.position().line() ); 574 575 writer.printTag( " <menber>" ); 576 writer.printTag( " <type>" ,menberType ,"</type>" ); 577 writer.printTag( " <name>" ,menberName ,"</name>" ); 578 writer.printTag( " <modifiers>" ,modifiers ,"</modifiers>" ); 579 writer.printTag( " <signature>" ,signature ,"</signature>" ); 580 writer.printTag( " <position>" ,position ,"</position>" ); 581 writer.printTag( " <extendClass>",extClass ,"</extendClass>" ); 582 writer.printTag( " <extendFlag>" ,extend ,"</extendFlag>" ); 583 writer.printTag( " <description>",desc ,"</description>" ); 584 writer.printTag( " <contents>" ,cmnt ,"</contents>" ); 585 writer.printTag( " <tagText>" ); 586 writer.printTagsInfo( tags ); 587 writer.printTag( " </tagText>" ); 588 writer.printTag( " <history>" ,revTags ,"</history>" ); 589 writer.printTag( " </menber>"); 590 } 591 592 /** 593 * ??オブジェクト? VERSION と、serialVersionUID staticフィールド?値を取得します? 594 * 595 * 結果は、文字?配?にして返します? 596 * どちらもなければ、null, どちらかあれば、文字?配?にして、?目は、VERSION。2つめ?、serialVersionUID ? 597 * ??にした値を返します? 598 * 599 * こ?メソ?のオリジナルは、org.opengion.hayabusa.servlet.HybsAdmin の private ?クラス ClassInfo にあります? 600 * 汎用性がな?、ソースのコピ????ーストで持ってきて?す??若干、修正もして?す? 601 * 602 * @og.rev 5.6.6.0 (2013/07/05) 新規作? 603 * 604 * @param clsName ??クラスを表す名称 605 * @return VERSION??( staticフィールド?値 ) と、serialVersionUIDを文字?にした値を含??? 606 */ 607 private static String getFieldVERSION( final String clsName ) { 608 String rtn ; 609 try { 610 Class<?> cls = Class.forName( clsName ) ; 611 Field fld = cls.getDeclaredField( "VERSION" ) ; 612 // privateフィールド?取得には、accessibleフラグ?trueにする?があります? 613 fld.setAccessible( true ); 614 rtn = (String)fld.get( null ); 615 } 616 catch( Throwable ex ) { 617 rtn = null; 618 } 619 return rtn ; 620 } 621 622 /** 623 * ??オブジェクト? VERSION と、serialVersionUID staticフィールド?値を取得します? 624 * 625 * 結果は、文字?配?にして返します? 626 * どちらもなければ、null, どちらかあれば、文字?配?にして、?目は、VERSION。2つめ?、serialVersionUID ? 627 * ??にした値を返します? 628 * 629 * こ?メソ?のオリジナルは、org.opengion.hayabusa.servlet.HybsAdmin の private ?クラス ClassInfo にあります? 630 * 汎用性がな?、ソースのコピ????ーストで持ってきて?す??若干、修正もして?す? 631 * 632 * @og.rev 5.6.6.0 (2013/07/05) 新規作? 633 * 634 * @param clsName ??クラスを表す名称 635 * @return VERSION??( staticフィールド?値 ) と、serialVersionUIDを文字?にした値を含??? 636 */ 637 private static String getSerialVersionUID( final String clsName ) { 638 String rtn ; 639 try { 640 Class<?> cls = Class.forName( clsName ); 641 Field fld = cls.getDeclaredField( "serialVersionUID" ) ; 642 // privateフィールド?取得には、accessibleフラグ?trueにする?があります? 643 fld.setAccessible( true ); 644 rtn = String.valueOf( (Long)fld.get( null ) ); 645 } 646 catch( Throwable ex ) { 647 rtn = null; 648 } 649 return rtn ; 650 } 651 652 /** 653 * カスタ?プションを使用するドックレ?の??メソ? optionLength(String) です? 654 * 655 * ドックレ?に認識させる?スタ?プションに?optionLength がその 656 * オプションを構?する要?(ト?クン) の数を返さなければなりません? 657 * こ?カスタ?プションでは?-tag オプションそ?も?と 658 * そ?値の 2 つの要?構?される?で、作?するドックレ?の 659 * optionLengthメソ?は?-tag オプションに対して 2 を返さなくては 660 * なりません。また?認識できな?プションに対しては? を返します? 661 * 662 * @param option オプション?? 663 * 664 * @return 要?ト?クン) の数 665 */ 666 public static int optionLength( final String option ) { 667 if(option.equalsIgnoreCase("-version")) { 668 return 2; 669 } 670 else if(option.equalsIgnoreCase("-outfile")) { 671 return 2; 672 } 673 else if(option.equalsIgnoreCase("-debugLevel")) { 674 return 2; 675 } 676 return 0; 677 } 678 }