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.process;
017    
018    import org.opengion.fukurou.util.Argument;
019    
020    import org.opengion.fukurou.util.StringUtil;
021    import org.opengion.fukurou.util.HybsEntry ;
022    import org.opengion.fukurou.util.LogWriter;
023    
024    import java.util.Hashtable;
025    import java.util.List;
026    import java.util.ArrayList;
027    import java.util.Map ;
028    import java.util.LinkedHashMap ;
029    
030    import javax.naming.Context;
031    import javax.naming.NamingEnumeration;
032    import javax.naming.NamingException;
033    import javax.naming.directory.DirContext;
034    import javax.naming.directory.InitialDirContext;
035    import javax.naming.directory.SearchControls;
036    import javax.naming.directory.SearchResult;
037    import javax.naming.directory.Attribute;
038    import javax.naming.directory.Attributes;
039    
040    /**
041     * Process_LDAPReaderは、LDAPから読み取ったå?容をã?LineModel に設定後ã?
042     * 下流に渡すã?FirstProcess インターフェースの実è£?‚¯ラスですã?
043     *
044     * LDAPから読み取ったå?容より、LineModelを作æ?しã?下æµ?プロセスチェインはã€?
045     * チェインしてã�?‚‹ため、データは上流から下流へと渡されますã?)に渡しますã?
046     *
047     * 引数æ–?­—å?中にスペã?スを含ã‚??合ã?、ダブルコーãƒ??ション("") で括って下さã�??
048     * 引数æ–?­—å?の ã€?』ã?前後には、スペã?スは挟めません。å¿?�šã€?key=value の様に
049     * 繋げてくださいã€?
050     *
051     * @og.formSample
052     *  Process_LDAPReader -attrs=uid,cn,officeName,ou,mail,belongOUID -orderBy=uid -filter=(&(objectClass=person)(|(belongOUID=61200)(belongOUID=61100)))
053     *
054     *   [ -initctx=コンãƒ?‚­ストファクトリ   ] ?šå?期コンãƒ?‚­ストファクトリ (初期値:com.sun.jndi.ldap.LdapCtxFactory)
055     *   [ -providerURL=サービスプロバイãƒ?ƒª ] ?šサービスプロバイãƒ?ƒª       (初期値:ldap://ldap.opengion.org:389)
056     *   [ -entrydn=取得å?の名前             ] ?š属æ?の取得å?のオブジェクトã?名前 (初期値:cn=inquiry-sys,o=opengion,c=JP)
057     *   [ -password=取得å?のパスワーãƒ?     ] ?š属æ?の取得å?のパスワーãƒ?  (初期値:******)
058     *   [ -searchbase=コンãƒ?‚­ストã?ースå�? ] ?š検索するコンãƒ?‚­ストã?ベã?スå�?(初期値:soouid=employeeuser,o=opengion,c=JP)
059     *   [ -searchScope=検索ç¯?›²             ] ?š検索ç¯?›²。ã?OBJECT』ã?ONELEVEL』ã?SUBTREE』ã?どれか(初期値:SUBTREE)
060     *   [ -timeLimit=検索制限時é–?          ] ?š結果が返されるまでのミリ秒数ã€? の場合無制é™?初期値:0)
061     *   [ -attrs=属æ?の識別å­?              ] ?šエントリとä¸?·’に返される属æ?の識別子ã?null の場合すべての属æ?
062     *   [ -columns=属æ?のカラãƒ?��           ] ?š属æ?の識別子に対する別名ã?識別子と同じ場合ã?ã€?』ã?みで区åˆ?‚‹ã€?
063     *   [ -maxRowCount=æœ?¤§検索数           ] ?š最大検索数(初期値:0[無制限])
064     *   [ -match_XXXX=正規表現              ] ?š指定ã?カラãƒ?�¨正規表現でä¸??時ã?み処ç�? -match_LANG=ABC=[a-zA-Z]* などã€?
065     *   [ -filter=検索条件                  ] ?š検索する LDAP にæŒ?®šする条件
066     *   [ -referral=REFERAL                 ] ?šignore/follow/throw
067     *   [ -display=false|true               ] ?š結果を標準å?力に表示する(true)かしなã�?false)ã�?初期値:false[表示しない])
068     *
069     * @version  4.0
070     * @author   Kazuhiko Hasegawa
071     * @since    JDK5.0,
072     */
073    public class Process_LDAPReader extends AbstractProcess implements FirstProcess {
074            private static final String             INITCTX                 = "com.sun.jndi.ldap.LdapCtxFactory";
075            private static final String             PROVIDER                = "ldap://ldap.opengion.org:389";
076            private static final String             PASSWORD                = "password";
077            private static final String             SEARCH_BASE             = "soouid=employeeuser,o=opengion,c=JP";
078            private static final String             ENTRYDN                 = "cn=inquiry-sys,o=opengion,c=JP";     // 4.2.2.0 (2008/05/10)
079            private static final String             REFERRAL                = ""; // 5.6.7.0 (2013/07/27)
080    
081            // 検索ç¯?›²。OBJECT_SCOPE、ONELEVEL_SCOPE、SUBTREE_SCOPE のどれか 1 つ
082            private static final String[]   SCOPE_LIST              = new String[] { "OBJECT","ONELEVEL","SUBTREE" };
083            private static final String             SEARCH_SCOPE    = "SUBTREE";
084    
085            private static final long       COUNT_LIMIT             = 0;                    // 返すエントリのæœ?¤§数ã€? の場合ã?フィルタをæº?�Ÿすエントリをすべて返す
086    
087            private String                  filter                          = null;         // "employeeNumber=87019";
088            private int                             timeLimit                       = 0;                    // 結果が返されるまでのミリ秒数ã€? の場合ã?無制é™?
089            private String[]                attrs                           = null;                 // エントリとä¸?·’に返される属æ?の識別子ã?null の場合ã?すべての属æ?を返す。空の場合ã?属æ?を返さなã�?
090            private String[]                columns                         = null;                 // 属æ?の識別子に対する、別名ã?識別子と同じ場合ã?、ã?,』ã?みで区åˆ?‚‹ã€?
091            private static final boolean    RETURN_OBJ_FLAG         = false;                // true の場合ã?エントリの名前にバインドされたオブジェクトを返す。false 場合ã?オブジェクトを返さなã�?
092            private static final boolean    DEREF_LINK_FLAG         = false;                // true の場合ã?検索中にリンクを間接参ç?する
093    
094            private int                             executeCount            = 0;                    // 検索/実行件数
095            private int                     maxRowCount                     = 0;                    // æœ?¤§検索数(0は無制é™?
096    
097            // 3.8.0.9 (2005/10/17) 正規表現マッãƒ?
098            private String[]                matchKey                        = null;                 // 正規表現
099            private boolean                 display                         = false;                // 表示しなã�?
100    
101            private static final Map<String,String> mustProparty   ;          // ?»プロパティ?½å¿??チェãƒ?‚¯用 Map
102            private static final Map<String,String> usableProparty ;          // ?»プロパティ?½整合æ?チェãƒ?‚¯ Map
103    
104            private NamingEnumeration<SearchResult> nameEnum  = null;         // 4.3.3.6 (2008/11/15) Generics警告対å¿?
105            private LineModel                                               newData         = null;
106            private int                                                             count           = 0;
107    
108            static {
109                    mustProparty = new LinkedHashMap<String,String>();
110                    mustProparty.put( "filter",     "検索条件(å¿??) ä¾? (&(objectClass=person)(|(belongOUID=61200)(belongOUID=61100)))" );
111    
112                    usableProparty = new LinkedHashMap<String,String>();
113                    usableProparty.put( "initctx",          "初期コンãƒ?‚­ストファクトリã€?
114                                                                                            + CR + " (初期値:com.sun.jndi.ldap.LdapCtxFactory)" );
115                    usableProparty.put( "providerURL",      "サービスプロバイãƒ?ƒª (初期値:ldap://ldap.opengion.org:389)" );
116                    usableProparty.put( "entrydn",          "属æ?の取得å?のオブジェクトã?名前ã€?
117                                                                                            + CR + " (初期値:cn=inquiry-sys,o=opengion,c=JP)" );
118                    usableProparty.put( "password",         "属æ?の取得å?のパスワーãƒ?初期値:******)" );
119                    usableProparty.put( "searchbase",       "検索するコンãƒ?‚­ストã?ベã?ス名ã?"
120                                                                                            + CR + " (初期値:soouid=employeeuser,o=opengion,c=JP)" );
121                    usableProparty.put( "searchScope",      "検索ç¯?›²。ã?OBJECT』ã?ONELEVEL』ã?SUBTREE』ã?どれかã€?
122                                                                                            + CR + " (初期値:SUBTREE)" );
123                    usableProparty.put( "timeLimit",        "結果が返されるまでのミリ秒数ã€? の場合無制é™?初期値:0)" );
124                    usableProparty.put( "attrs",            "エントリとä¸?·’に返される属æ?の識別子ã?null の場合すべての属æ?" );
125                    usableProparty.put( "columns",          "属æ?の識別子に対する別名ã?識別子と同じ場合ã?ã€?』ã?みで区åˆ?‚‹ã€? );
126                    usableProparty.put( "maxRowCount",      "æœ?¤§検索数(0は無制é™?  (初期値:0)" );
127                    usableProparty.put( "match_",           "æŒ?®šã?カラãƒ?�¨正規表現でä¸??時ã?み処ç�?
128                                                                                            + CR + " ( -match_LANG=ABC=[a-zA-Z]* などã€?" );
129                    usableProparty.put( "display",          "結果を標準å?力に表示する(true)かしなã�?false)ã�?
130                                                                                            + CR + "(初期値:false:表示しなã�?" );
131            }
132    
133            /**
134             * ãƒ?ƒ•ォルトコンストラクターã€?
135             * こã?クラスは、動çš?½œæ?されますã?ãƒ?ƒ•ォルトコンストラクターでã€?
136             * super クラスに対して、å¿?¦�な初期化を行っておきますã?
137             *
138             */
139            public Process_LDAPReader() {
140                    super( "org.opengion.fukurou.process.Process_LDAPReader",mustProparty,usableProparty );
141            }
142    
143            /**
144             * プロセスの初期化を行いますã?初めにä¸?º¦ã�?�‘、呼び出されますã?
145             * 初期処ç�?ファイルオープンã€?¼¤?¢オープンç­?に使用しますã?
146             *
147             * @og.rev 4.2.2.0 (2008/05/10) LDAP パスワード取得対å¿?
148             * @og.rev 5.3.4.0 (2011/04/01) StringUtil.nval ではなくã?getProparty の 初期値機è?を使ã�?
149             * @og.rev 5.6.7.0 (2013/07/27) REFERRAL対å¿?
150             *
151             * @param   paramProcess ãƒ??タベã?スの接続å?æƒ??などを持ってã�?‚‹オブジェクãƒ?
152             */
153            public void init( final ParamProcess paramProcess ) {
154                    Argument arg = getArgument();
155    
156                    String  initctx         = arg.getProparty("initctx "    ,INITCTX         );
157                    String  providerURL = arg.getProparty("providerURL"     ,PROVIDER        );
158                    String  entrydn         = arg.getProparty("entrydn"             ,ENTRYDN         );     // 4.2.2.0 (2008/05/10)
159                    String  password        = arg.getProparty("password"    ,PASSWORD        );
160                    String  searchbase      = arg.getProparty("searchbase"  ,SEARCH_BASE );
161    
162                    String  searchScope = arg.getProparty("searchScope"     ,SEARCH_SCOPE , SCOPE_LIST );
163    //              timeLimit       = StringUtil.nval( arg.getProparty("timeLimit")         ,timeLimit );
164    //              maxRowCount     = StringUtil.nval( arg.getProparty("maxRowCount")       ,maxRowCount );
165                    timeLimit       = arg.getProparty("timeLimit",timeLimit );                      // 5.3.4.0 (2011/04/01)
166                    maxRowCount     = arg.getProparty("maxRowCount",maxRowCount );          // 5.3.4.0 (2011/04/01)
167                    display         = arg.getProparty("display",display);
168                    
169                    String referral         = arg.getProparty("referral",REFERRAL);  // 5.6.7.0 (2013/07/27)
170    
171                    // 属æ?配å?を取得ã?なければゼロ配å?
172                    attrs           = StringUtil.csv2Array( arg.getProparty("attrs") );
173                    if( attrs.length == 0 ) { attrs = null; }
174    
175                    // 別名定義配å?を取得ã?なければ属æ?配å?をセãƒ?ƒˆ
176                    columns         = StringUtil.csv2Array( arg.getProparty("columns") );
177                    if( columns.length == 0 ) { columns = attrs; }
178    
179                    // 属æ?配å?が存在しã?属æ?定義数と別名é?列数が異なれã?エラー
180                    // 以降ã?、attrs == null かã?属æ?定義数と別名é?列数が同じã?ずã?
181                    if( attrs != null && attrs.length != columns.length ) {
182                            String errMsg = "attrs と columns でæŒ?®šã?引数の数が異なりますã?" +
183                                                    " attrs=[" + arg.getProparty("attrs") + "] , columns=[" +
184                                                    arg.getProparty("columns") + "]" ;
185                            throw new RuntimeException( errMsg );
186                    }
187    
188                    // 3.8.0.9 (2005/10/17) 正規表現マッãƒ?
189                    HybsEntry[] entry = arg.getEntrys( "match_" );
190                    int len = entry.length;
191                    matchKey        = new String[columns.length];           // 正規表現
192                    for( int clm=0; clm<columns.length; clm++ ) {
193                            matchKey[clm] = null;   // 判定チェãƒ?‚¯有無の初期åŒ?
194                            for( int i=0; i<len; i++ ) {
195                                    if( columns[clm].equalsIgnoreCase( entry[i].getKey() ) ) {
196                                            matchKey[clm] = entry[i].getValue();
197                                    }
198                            }
199                    }
200    
201                    filter = arg.getProparty( "filter" ,filter );
202    
203                    Hashtable<String,String> env = new Hashtable<String,String>();
204                    env.put(Context.INITIAL_CONTEXT_FACTORY, initctx);
205                    env.put(Context.PROVIDER_URL, providerURL);
206                    // 3.7.1.1 (2005/05/31)
207            //      if( password != null && password.length() > 0 ) {
208                            env.put(Context.SECURITY_CREDENTIALS, password);
209            //      }
210    
211                    // 4.2.2.0 (2008/05/10) entrydn 属æ?の追åŠ?
212            //      if( entrydn != null && entrydn.length() > 0 ) {
213                            env.put(Context.SECURITY_PRINCIPAL  , entrydn);
214            //      }
215                            
216                    env.put( Context.REFERRAL, referral ); // 5.6.7.0 (2013/07/27)
217    
218                    try {
219                            DirContext ctx = new InitialDirContext(env);
220                            SearchControls constraints = new SearchControls(
221                                                                            changeScopeString( searchScope ),
222                                                                            COUNT_LIMIT                     ,
223                                                                            timeLimit                       ,
224                                                                            attrs                           ,
225                                                                            RETURN_OBJ_FLAG         ,
226                                                                            DEREF_LINK_FLAG
227                                                                                    );
228    
229                            nameEnum = ctx.search(searchbase, filter, constraints);
230    
231                    } catch ( NamingException ex ) {
232                            String errMsg = "NamingException !"
233                                            + ex.getMessage();                              // 5.1.8.0 (2010/07/01) errMsg 修正
234                            throw new RuntimeException( errMsg,ex );
235                    }
236            }
237    
238            /**
239             * プロセスの終äº?‚’行いますã?æœ?¾Œにä¸?º¦ã�?�‘、呼び出されますã?
240             * 終äº??ç�?ファイルクローズã€?¼¤?¢クローズç­?に使用しますã?
241             *
242             * @param   isOK トã?タルで、OKã�?�£たかどã�?�‹[true:成功/false:失敗]
243             */
244            public void end( final boolean isOK ) {
245                    try {
246                            if( nameEnum  != null ) { nameEnum.close() ;  nameEnum  = null; }
247                    }
248                    catch ( NamingException ex ) {
249                            String errMsg = "ãƒ?‚£スコネクトすることがå?来ませんã€?;
250                            throw new RuntimeException( errMsg,ex );
251                    }
252            }
253    
254            /**
255             * こã?ãƒ??タの処ç�?�«おいて、次の処ç�?�Œ出来るかどã�?�‹を問ã�?�ˆわせますã?
256             * こã?呼び出し1回毎に、次のãƒ??タを取得する準備を行いますã?
257             *
258             * @return      処ç�?�§きる:true / 処ç�?�§きなã�?false
259             */
260            public boolean next() {
261                    try {
262                            return nameEnum != null && nameEnum.hasMore() ;
263                    }
264                    catch ( NamingException ex ) {
265                            String errMsg = "ネクストすることがå?来ませんã€?;
266                            throw new RuntimeException( errMsg,ex );
267                    }
268            }
269    
270            /**
271             * æœ??にã€?行データである LineModel を作æ?しまã�?
272             * FirstProcess は、次ã€?�¨処ç�?‚’チェインしてã�?��æœ??の行データã‚?
273             * 作æ?して、後続ã? ChainProcess クラスに処ç�?ƒ‡ータを渡しますã?
274             *
275             * @og.rev 4.2.2.0 (2008/05/10) LDAP パスワード取得対å¿?
276             *
277             * @param       rowNo   処ç�?¸­の行番号
278             *
279             * @return      処ç�?¤‰換後ã?LineModel
280             */
281            public LineModel makeLineModel( final int rowNo ) {
282                    count++ ;
283                    try {
284                            if( maxRowCount > 0 && maxRowCount <= executeCount ) { return null ; }
285                            SearchResult sRslt = nameEnum.next();           // 4.3.3.6 (2008/11/15) Generics警告対å¿?
286                            Attributes att = sRslt.getAttributes();
287    
288                            if( newData == null ) {
289                                    newData = createLineModel( att );
290    //                              if( display ) { println( newData.nameLine() ); }
291                            }
292    
293                            for( int i=0; i<attrs.length; i++ ) {
294                                    Attribute attr = att.get(attrs[i]);
295                                    if( attr != null ) {
296                                            NamingEnumeration<?> vals = attr.getAll();                // 4.3.3.6 (2008/11/15) Generics警告対å¿?
297                                            StringBuilder buf = new StringBuilder();
298    //                                      if( vals.hasMore() ) { buf.append( vals.next() ) ;}
299                                            if( vals.hasMore() ) { getDataChange( vals.next(),buf ) ;}      // 4.2.2.0 (2008/05/10)
300                                            while ( vals.hasMore() ) {
301                                                    buf.append( "," ) ;
302    //                                              buf.append( vals.next() ) ;
303                                                    getDataChange( vals.next(),buf ) ;      // 4.2.2.0 (2008/05/10)
304                                            }
305                                            // 3.8.0.9 (2005/10/17) 正規表現マッチしなければ、スルーするã€?
306                                            String value = buf.toString();
307                                            String key = matchKey[i];
308                                            if( key != null && value != null && !value.matches( key ) ) {
309                                                    return null;
310                                            }
311                                            newData.setValue( i, value );
312                                            executeCount++ ;
313                                    }
314                            }
315    
316                            newData.setRowNo( rowNo );
317                            if( display ) { println( newData.dataLine() ); }
318                    }
319                    catch ( NamingException ex ) {
320                            String errMsg = "ãƒ??タをå?ç�?�§きませんでしたã€?" + rowNo + "]件目";
321                            if( newData != null ) { errMsg += newData.toString() ; }
322                            throw new RuntimeException( errMsg,ex );
323                    }
324                    return newData;
325            }
326    
327            /**
328             * LDAPから取得したデータの変換を行いますã?
329             *
330             * 主に、バイトé?åˆ?byte[]) オブジェクトã?場合ã?æ–?­—å?に戻しますã?
331             *
332             * @og.rev 4.2.2.0 (2008/05/10) 新規追åŠ?
333             *
334             * @param       obj     主にバイトé?列オブジェクãƒ?
335             * @param       buf     å…??StringBuilder
336             *
337             * @return      ãƒ??タを追åŠ?�—ã�?StringBuilder
338             */
339            private StringBuilder getDataChange( final Object obj, final StringBuilder buf ) {
340                    if( obj == null ) { return buf; }
341                    else if( obj instanceof byte[] ) {
342            //              buf.append( new String( (byte[])obj,"ISO-8859-1" ) );
343                            byte[] bb = (byte[])obj ;
344                            char[] chs = new char[bb.length];
345                            for( int i=0; i<bb.length; i++ ) {
346                                    chs[i] = (char)bb[i];
347                            }
348                            buf.append( chs );
349                    }
350                    else {
351                            buf.append( obj ) ;
352                    }
353    
354                    return buf ;
355            }
356    
357            /**
358             * å†?ƒ¨で使用する LineModel を作æ?しますã?
359             * こã?クラスは、ã?ロセスチェインの基点となりますã?で、新è¦?LineModel を返しますã?
360             * Exception 以外では、å¿?�š LineModel オブジェクトを返しますã?
361             *
362             * @param   att Attributesオブジェクãƒ?
363             *
364             * @return      ãƒ??タベã?スから取り出して変換した LineModel
365             * @throws RuntimeException カラãƒ?��を取得できなかったå?合ã?
366             */
367            private LineModel createLineModel( final Attributes att ) {
368                    LineModel model = new LineModel();
369    
370                    try {
371                            // init() でチェãƒ?‚¯済み。attrs == null かã?属æ?定義数と別名é?列数が同じã?ずã?
372                            // attrs ã�?null の場合ã?、å?キーæƒ??を取得しますã?
373                            if( attrs == null ) {
374                                    NamingEnumeration<String> nmEnum = att.getIDs();  // 4.3.3.6 (2008/11/15) Generics警告対å¿?
375                                    List<String> lst = new ArrayList<String>();
376                                    try {
377                                            while( nmEnum.hasMore() ) {
378                                                    lst.add( nmEnum.next() );               // 4.3.3.6 (2008/11/15) Generics警告対å¿?
379                                            }
380                                    }
381                                    finally {
382                                            nmEnum.close();
383                                    }
384                                    attrs = lst.toArray( new String[lst.size()] );
385                                    columns = attrs;
386                            }
387    
388                            int size = columns.length;
389                            model.init( size );
390                            for(int clm = 0; clm < size; clm++) {
391                                    model.setName( clm,StringUtil.nval( columns[clm],attrs[clm] ) );
392                            }
393                    }
394                    catch ( NamingException ex ) {
395                            String errMsg = "ResultSetMetaData から、カラãƒ?��を取得できませんでしたã€?;
396                            throw new RuntimeException( errMsg,ex );
397                    }
398                    return model;
399            }
400    
401            /**
402             * スコープを表す文字å?ã‚?SearchControls の定数に変換しますã?
403             * 入力文字å?は、OBJECT、ONELEVEL、SUBTREEですã?変換する定数はã€?
404             * SearchControls クラスの static 定数ですã?
405             *
406             * @param    scope スコープを表す文字å?(OBJECT、ONELEVEL、SUBTREE)
407             *
408             * @return   SearchControlsの定数(OBJECT_SCOPE、ONELEVEL_SCOPE、SUBTREE_SCOPE)
409             * @see      javax.naming.directory.SearchControls#OBJECT_SCOPE
410             * @see      javax.naming.directory.SearchControls#ONELEVEL_SCOPE
411             * @see      javax.naming.directory.SearchControls#SUBTREE_SCOPE
412             */
413            private int changeScopeString( final String scope ) {
414                    int rtnScope ;
415                    if( "OBJECT".equals( scope ) )        { rtnScope = SearchControls.OBJECT_SCOPE ; }
416                    else if( "ONELEVEL".equals( scope ) ) { rtnScope = SearchControls.ONELEVEL_SCOPE ; }
417                    else if( "SUBTREE".equals( scope ) )  { rtnScope = SearchControls.SUBTREE_SCOPE ; }
418                    else {
419                            String errMsg = "Search Scope in 『OBJECT』ã?ONELEVEL』ã?SUBTREE』Selected"
420                                                            + "[" + scope + "]" ;
421                            throw new RuntimeException( errMsg );
422                    }
423                    return rtnScope ;
424            }
425    
426            /**
427             * プロセスの処ç�?µ�果のレポã?ト表現を返しますã?
428             * 処ç�??ログラãƒ?��、å?力件数、å?力件数などのæƒ??ですã?
429             * こã?æ–?­—å?をそのまま、標準å?力に出すことで、結果レポã?トと出来るよã�?�ª
430             * 形式で出してくださいã€?
431             *
432             * @return   処ç�?µ�果のレポã?ãƒ?
433             */
434            public String report() {
435                    String report = "[" + getClass().getName() + "]" + CR
436                                    + TAB + "Search Filter : " + filter + CR
437                                    + TAB + "Input Count   : " + count ;
438    
439                    return report ;
440            }
441    
442            /**
443             * こã?クラスの使用方法を返しますã?
444             *
445             * @return      こã?クラスの使用方æ³?
446             */
447            public String usage() {
448                    StringBuilder buf = new StringBuilder();
449    
450                    buf.append( "Process_LDAPReaderは、LDAPから読み取ったå?容をã?LineModel に設定後ã?"                    ).append( CR );
451                    buf.append( "下流に渡すã?FirstProcess インターフェースの実è£?‚¯ラスですã?"                                    ).append( CR );
452                    buf.append( CR );
453                    buf.append( "LDAPから読み取ったå?容より、LineModelを作æ?しã?下æµ?プロセスチェインはã€?             ).append( CR );
454                    buf.append( "チェインしてã�?‚‹ため、データは上流から下流へと渡されますã?)に渡しますã?"              ).append( CR );
455                    buf.append( CR );
456                    buf.append( "引数æ–?­—å?中に空白を含ã‚??合ã?、ダブルコーãƒ??ション(\"\") で括って下さã�??" ).append( CR );
457                    buf.append( "引数æ–?­—å?の ã€?』ã?前後には、空白は挟めません。å¿?�šã€?key=value の様に"             ).append( CR );
458                    buf.append( "繋げてくださいã€?                                                                                                                              ).append( CR );
459                    buf.append( CR ).append( CR );
460    
461                    buf.append( getArgument().usage() ).append( CR );
462    
463                    return buf.toString();
464            }
465    
466            /**
467             * こã?クラスは、main メソãƒ?ƒ‰から実行できませんã€?
468             *
469             * @param       args    コマンド引数配å?
470             */
471            public static void main( final String[] args ) {
472                    LogWriter.log( new Process_LDAPReader().usage() );
473            }
474    }