/*
 * Copyright (c) 2009 The openGion Project.
 *
 * 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.opengion.hayabusa.taglib;

import static org.opengion.fukurou.util.StringUtil.nval;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Map;

import org.opengion.fukurou.util.Closer;
import org.opengion.fukurou.util.FileString;
import org.opengion.fukurou.util.FileUtil;
import org.opengion.fukurou.util.LogWriter;
import org.opengion.fukurou.util.SOAPConnect;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.util.URLConnect;
import org.opengion.fukurou.util.XHTMLTag;
import org.opengion.fukurou.xml.XML2TableParser;
import org.opengion.fukurou.xml.XSLT;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.hayabusa.db.DBTableModelUtil;

/**
 * 指定のURLに接続します。
 *
 * エンジンでは、URL にアクセスすることで、デーモンを起動したり、
 * コマンドを実行(adminメニュー)することが出来ます。
 * もちろん、検索条件を指定して、結果を取得することも可能です。
 * このタグでは、URLにアクセスして、コマンドを実行したり結果を取得できます。
 * さらに、ファイルを POST で転送したり、処理結果を XSLT変換したり出来ます。
 *
 * @og.formSample
 * ●形式：
 *     &lt;og:urlConnect
 *         url           = "http://･･･ "    必須
 *         proxyHost     = "proxy.opengion.org"
 *         proxyPort     = "8080"
 *         keys          = "command,SYSTEM_ID"
 *         vals          = "NEW,GE"
 *         useSystemUser = "true/false"     初期値:true
 *         authUserPass  = "admin:******"   初期値:admin:******
 *         display       = "false/true"     初期値:false
 *         xslFile       = "filter.xsl"
 *         saveFile      = "outdata.xml"
 *         soapNameSpace = "MyWebService"
 *         soapMethodName= "test"
 *         tableId       = "DEFAULT"
 *         rowKey        = "item"
 *         colKeys       = "person_id,person_name"
 *         rtnKeys       = "version,summary"
 *         encode        = "UTF-8"
 *     /&gt;
 *
 * url           : 接続するURLを指定します。必須属性です。
 * proxyHost     : proxy が存在する場合は、そのホスト名(例：proxy.opengion.org)
 * proxyPort     : proxy が存在する場合は、そのポート番号(例：8080)
 * keys,vals     : URLの指定時に、パラメータ(引数)を追加します。URLに含めても構いません。
 *               : SOAPによる呼び出しの場合の詳細については、keysの属性定義を参照して下さい。
 * postKey       : POST を使って、postFile属性のファイル内容を送信する時のキーです。
 * postFile      : POST を使って、postFile属性のファイル内容を送信します。
 *                 postFile を指定せず、postKey のみ指定して、BODY部に何か書き込めば、
 *                 そのBODY部の文字列を POSTの内容として送信します。
 * authUserPass  : Basic認証を使用する場合の接続ユーザー：パスワードを指定します。
 *                 接続時のユーザーとパスワードを、USER:PASSWD 形式 で指定します。
 *                 useSystemUser="false" で何も指定しない場合は、Basic認証を使用しません。
 * useSystemUser : Basic認証の接続ユーザー：パスワードに、システムユーザーを使用
 *                 するかどうかを指定します(初期値:true)。
 *                 true の場合は、SYSTEM:***** を使用します。
 * xslFile       : 接続先データを取得し、そのデータを XSLT変換する場合のXSLファイルを指定します。
 * display       : 接続した結果のレスポンスを画面に表示するかどうかを指定します(初期値:false)。
 *                 エンジンの場合、コマンドを投げるだけであれば、結果を取得する必要は
 *                 ありません。イメージ的には、取得データが、このタグの位置に置き換わります。
 *                 xslFile が指定されている場合、XSLT変換してセーブします。
 * saveFile      : 接続先データを取得した結果を、ファイル出力します。
 *                 display="true" と、saveFile を併用することはできません。
 *                 xslFile が指定されている場合、XSLT変換してセーブします。
 * soapNameSpace : SOAPによるWebサービスの呼び出しで、メソッド名及びパラメーターの名前空間を指定します。
 *                 この名前空間は、通常WSDLファイルのdescriptionsタグのtargetNamespace属性の値により
 *                 定義されます。
 * soapMethodName: SOAPによるWebサービスの呼び出しで、メソッド名を指定します。
 *                 WSDLファイルで定義されるoperationタグのname属性の値に相当します。
 * tableId       : 結果のXMLファイルをDBTableModelに変換した際に、登録するTableIdを指定します。
 * rowKey        : XMLをDBTableModelに変換する際の、行を表すタグキーを指定します。
 * colKeys       : XMLをDBTableModelに変換する際の、項目を表すタグキーの一覧を指定します。
 *                 キーにPARENT_TAG、PARENT_FULL_TAGを指定することで、rowKeyで指定されたタグの
 *                 直近の親タグ、及びフルの親タグ名(親タグの階層を">[タグA]>[タグB]>[タグC]>"で表現)を
 *                 取得することができます。
 * rtnKeys       : XMLのタグキーを指定して値を取り出します。取り出した値は、{&#064;XX}形式で処理することが可能です。
 * encode        : データの入出力を行うエンコードを指定します。
 *
 * ●body：POSTデータ
 *
 * ●Tag定義：
 *   &lt;og:urlConnect
 *       url              ○【TAG】アクセスする ＵＲＬ を指定します(必須)。(必須)
 *       proxyHost          【TAG】プロキシ経由で接続する場合の、プロキシホスト名を指定します
 *       proxyPort          【TAG】プロキシ経由で接続する場合の、プロキシポート番号を指定します
 *       keys               【TAG】アクセスパラメータキーをCSV形式で複数指定します
 *       vals               【TAG】keys属性に対応する値をCSV形式で複数指定します
 *       useSystemUser      【TAG】Basic認証で接続するユーザーにSYSTEMユーザーを使用するかどうか[true/false]を指定します(初期値:true)
 *       authUserPass       【TAG】Basic認証を使用して接続する場合のユーザー:パスワードを指定します(初期値:null)
 *       display            【TAG】接続の結果を表示するかどうかを指定します(初期値:false)
 *       xslFile            【TAG】接続の結果を表示する場合にXSLT変換する場合のファイルを指定します
 *       saveFile           【TAG】接続の結果をファイルに保存します
 *       postKey            【TAG】POST を使って、postFile属性のファイル内容を送信する時のキーを指定します
 *       postFile           【TAG】POST を使って、postFile属性のファイル内容を送信します
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *       method             【TAG】送信メソッドを指定します(GET/POST/SOAP)
 *       errNeglect         【TAG】(通常は使いません) 接続エラーを無視する場合にtrueとします(初期値false)
 *       soapNameSpace      【TAG】SOAPによるWebサービスの呼び出しで、メソッド名及びパラメーターの名前空間を指定します
 *       soapMethodName     【TAG】SOAPによるWebサービスの呼び出しで、メソッド名を指定します
 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
 *       rowKey             【TAG】結果のXMLをDBTableModelに変換する際に、行のキーとなるタグ名を指定します
 *       colKeys            【TAG】結果のXMLをDBTableModelに変換する際に、項目のキーとなるタグ名の一覧を指定します
 *       rtnKeys            【TAG】結果のXMLを変換する際に、パラメータ(Attributes)として取り込むキーの一覧を指定します
 *       encode             【TAG】データの入出力のエンコードを指定します
 *       mainTrans          【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:urlConnect&gt;
 *
 * ●例：
 * アドミン関連
 * http://localhost:8823/gf/jsp/admin?COMMAND=infomation     [状況表示]
 * http://localhost:8823/gf/jsp/admin?COMMAND=close          [プール削除]
 * http://localhost:8823/gf/jsp/admin?COMMAND=loginUser      [ログインユーザー]
 * http://localhost:8823/gf/jsp/admin?COMMAND=システムパラメータ [システムパラメータ]
 *
 * 帳票デーモン
 * http://localhost:8823/gf/jsp/REP08/result.jsp?cmd=SET&period=5000&command=NEW&timerTask=org.opengion.hayabusa.report.ReportDaemon&name=ReportDaemon  デーモン起動
 * http://localhost:8823/gf/jsp/REP08/result.jsp?cmd=CANCEL&period=5000&command=NEW&timerTask=org.opengion.hayabusa.report.ReportDaemon&name=ReportDaemon  デーモン停止
 *
 *Tomcat Manager 画面
 * http://localhost:8823/manager/reload?path=/ver4 アプリケーションを再ロード
 *
 * @og.rev 3.6.0.0 (2004/09/17) 新規作成
 * @og.rev 4.1.0.0 (2007/12/22) POSTメソッドで複数キーを登録できるように属性追加
 * @og.rev 5.1.5.0 (2010/04/01) SOAP対応
 * @og.group その他部品
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class URLConnectTag extends CommonTagSupport {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "4.0.0 (2005/08/31)" ;

	private static final long serialVersionUID = 4000 ;	// 4.0.0 (2005/01/31)

	private static final String DEFAULT_USER = "SYSTEM:MANAGER" ;

	private String		urlStr			= null;
	private String[]	keys			= null;
	private String[]	vals			= null;
	private String		xslFile			= null;
	private String		saveFile		= null;
	private String		postKey			= null;
	private String		postData		= null;		// postFile ファイルか、BODY部
	private boolean 	useSystemUser	= true;
	private String		authUserPass	= null;
	private boolean 	display			= false;
	private String		proxyHost		= null;		// 4.0.0 (2007/07/25)
	private int 		proxyPort		= -1;		// 4.0.0 (2007/07/25)
	private String		method			= "GET";	// 4.1.0.0 (2007/12/22) POSTorGETorSOAP
	private boolean		errNglctFlag	= false;	// 4.1.1.0 (2008/01/22) エラー無視フラグ
	private String		soapNameSpace	= null;		// 5.1.5.0 (2010/04/01) SOAP対応
	private String		soapMethodName	= null;		// 5.1.5.0 (2010/04/01) SOAP対応
	private transient DBTableModel table			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
	private String		tableId			= HybsSystem.TBL_MDL_KEY; // 5.1.5.0 (2010/04/01) DBTableModel出力対応
	private String		rowKey			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
	private String[]	colKeys			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
	private String[]	rtnKeys			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
	private String		encode			= "UTF-8";	// 5.1.6.0 (2010/05/01) エンコード指定対応

	private boolean		isTableOut		= false;	// 5.1.5.0 (2010/04/01) DBTableModel出力対応
	private boolean		isOutParse		= false;	// 5.1.5.0 (2010/04/01) DBTableModel出力対応
	private boolean		isMainTrans		= true;		// 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 5.1.5.0 (2010/04/01) SOAP・DBTableModel出力対応
	 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doStartTag() {

		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		if( rowKey != null || colKeys != null || rtnKeys != null ) {
			isOutParse = true;
			if( rowKey != null || colKeys != null ) {
				isTableOut = true;
				useMainTrans( isMainTrans );			// 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
				startQueryTransaction( tableId );
			}
		}

		// 5.1.5.0 (2010/04/01) SOAPの場合は、postKeyが指定されない。
//		if( postKey == null || postData != null ) {
		if( postData != null ) {
			return( SKIP_BODY );			// Body を評価しない
		}
		else {
			return( EVAL_BODY_BUFFERED );	// Body を評価する。( extends BodyTagSupport 時)
		}
	}

	/**
	 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
	 *
	 * @return	後続処理の指示(SKIP_BODY)
	 */
	@Override
	public int doAfterBody() {
		postData = getBodyString();

		return(SKIP_BODY);
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 4.0.1.0 (2007/12/12) PostKeys,PostVals処理を追加
	 * @og.rev 5.1.5.0 (2010/04/01) SOAP・DBTableModel出力対応
	 * @og.rev 5.2.0.0 (2010/09/01) エラー処理でNullPointerExceptionが発生するバグを修正
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();		// 4.0.0 (2005/02/28)

		URLConnect conn = null;
		ByteArrayOutputStream pipeOut = null;
		try {
			conn = connect();

//			String data = conn.readData();

			// 出力先が、画面かファイルかを判断します。
			Writer outWriter = null;
			// 5.1.5.0 (2010/04/01) DBTableModel出力対応
			if( isOutParse ) {
		        pipeOut = new ByteArrayOutputStream();
				try {
					outWriter = new BufferedWriter( new OutputStreamWriter( pipeOut, "UTF-8" ) );
				}
				catch( UnsupportedEncodingException ex ) {
					throw new HybsSystemException( "不正なエンコードが指定されました。[UTF-8]",ex );
				}
			}
			else if( display ) {
//				outWriter = pageContext.getOut() ;		// JspWriter の取得
				outWriter = FileUtil.getNonFlushPrintWriter( pageContext.getOut() ) ;		// JspWriter の取得
			}
			else if( saveFile != null ) {
				outWriter = FileUtil.getPrintWriter( new File( saveFile ),"UTF-8" );
			}

			// 出力先が存在する場合。
			if( outWriter != null ) {
				if( xslFile != null ) {
					XSLT xslt = new XSLT();
					xslt.setXslFile( xslFile );
					xslt.setOutFile( outWriter );
//					xslt.transform( data );
					xslt.transform( conn.getReader() );
					xslt.close();
				}
				else {
//					outWriter.write( data );
					outWriter.write( conn.readData() );
				}
				Closer.ioClose( outWriter );
			}
		}
		catch( IOException ex ) {
			String errMsg = "データ取得中にエラーが発生しました。" + HybsSystem.CR
						+ " url=[" + urlStr + "]"
						// 5.2.0.0 (2010/09/01) エラー処理でNullPointerExceptionが発生するバグを修正
//						+ " message=[" + conn.getMessage() + "]";
						+ " message=[" + ( conn == null ? "NO_CONNECTION" : conn.getMessage() ) + "]";
			if( errNglctFlag ) { // 4.1.1.0 (2008/01/22) エラーを無視(標準エラー出力のみ)
				LogWriter.log( errMsg );
			}
			else { // 通常は無視しない
				throw new HybsSystemException( errMsg,ex );
			}
		}
		finally {
			if( conn != null ) { conn.disconnect(); }
		}

		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		if( isOutParse ) {
			parse( new BufferedInputStream( new ByteArrayInputStream( pipeOut.toByteArray() ) ) );
			if( isTableOut && table != null && !commitTableObject( tableId, table ) ) {
				jspPrint( "URLConnectTag Query処理が割り込まれました。DBTableModel は登録しません。" );
				return(SKIP_PAGE);
			}
		}

		return(EVAL_PAGE);
	}

	/**
	 * URLに対して接続を行います。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) エンコード指定対応
	 *
	 * @return 接続オブジェクト
	 * @throws IOException
	 */
	private URLConnect connect() throws IOException {
		if( useSystemUser ) { authUserPass = DEFAULT_USER; }

		// 5.1.5.0 (2010/04/01) SOAP対応
		// SOAPの場合、PostDataは、SOAPConnectタグの中で生成します。
		URLConnect conn = null;
		if( "SOAP".equalsIgnoreCase( method ) ) {
			if( soapNameSpace == null || soapNameSpace.length() == 0
					|| soapMethodName == null || soapMethodName.length() == 0 ) {
				String errMsg = "SOAP接続の場合、soapNameSpace及びsoapMethodNameは必ず指定して下さい。";
				throw new HybsSystemException( errMsg );
			}

			if( postData != null && postData.length() > 0 ) {
				conn = new SOAPConnect( urlStr,authUserPass, soapNameSpace, soapMethodName, postData );
			}
			else {
				conn = new SOAPConnect( urlStr,authUserPass, soapNameSpace, soapMethodName, keys, vals );
			}
		}
		else {
			String urlEnc = XHTMLTag.urlEncode( keys,vals );
			if( postKey != null ) { // 4.1.0.0 (2007/12/22)
				method = "POST";
				String addEnc = postKey + "=" + postData;
				urlEnc = urlEnc + "&" + addEnc; // &連結
			}

			if( ! "POST".equals( method ) ) { // 4.1.0.0 (2007/12/22)
				// String urlEnc = XHTMLTag.urlEncode( keys,vals );
				urlStr = XHTMLTag.addUrlEncode( urlStr,urlEnc );
			}
			conn = new URLConnect( urlStr,authUserPass );

			// if( postKey != null ) {
			//	conn.setPostData( postKey,postData );
			// }
			if( "POST".equals( method ) && keys != null && vals != null ) { // 4.1.0.0 (2007/12/22)
				conn.setPostData( urlEnc );
			}
		}

		// 4.0.0 (2007/07/25) プロキシの設定追加
		if( proxyHost != null ) {
			conn.setProxy( proxyHost,proxyPort );
		}

		// 5.1.6.0 (2010/05/01) エンコード指定対応
		if( encode != null && encode.length() > 0 ) {
			conn.setCharset( encode );
		}
		conn.connect();

		return conn;
	}

	/**
	 * 出力データをパースし、DBTableModel及び属性パラメーターに分解します。
	 * 現時点では、XMLデータのみパースすることが可能です。
	 *
	 * @param input インプットストリーム
	 */
	private void parse( final InputStream input ) {
		XML2TableParser parser = new XML2TableParser( input );
		parser.setTableCols( rowKey, colKeys );
		parser.setReturnCols( rtnKeys );
		parser.parse();

		// DBTableModelを生成します。
		if( isTableOut ) {
			table = DBTableModelUtil.makeDBTable( parser.getCols(), parser.getData(), getResource() );
		}

		// 戻り値を取得し、Attributeに登録します。
		if( rtnKeys != null ) {
			Map<String,String> rtn = parser.getRtn();
			for( Map.Entry<String, String> entry : rtn.entrySet() ) {
				setRequestAttribute( entry.getKey(), entry.getValue() );
			}
		}
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		urlStr			= null;
		proxyHost		= null;		// 4.0.0 (2007/07/25)
		proxyPort		= -1;		// 4.0.0 (2007/07/25)
		keys			= null;
		vals			= null;
		xslFile			= null;
		saveFile		= null;
		postKey			= null;
		postData		= null;
		useSystemUser	= true;
		authUserPass	= null;
		display			= false;
		method			= "GET";	// 4.1.0.0 (2007/12/22)
		errNglctFlag	= false;	// 4.1.1.0 (2008/01/22)
		soapNameSpace	= null;		// 5.1.5.0 (2010/04/01) SOAP対応
		soapMethodName	= null;		// 5.1.5.0 (2010/04/01) SOAP対応
		table			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		tableId			= HybsSystem.TBL_MDL_KEY; // 5.1.5.0 (2010/04/01) DBTableModel出力対応
		rowKey			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		colKeys			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		rtnKeys			= null;		// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		isTableOut		= false;	// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		isOutParse		= false;	// 5.1.5.0 (2010/04/01) DBTableModel出力対応
		encode			= "UTF-8";	// 5.1.6.0 (2010/05/01) エンコード指定対応
		isMainTrans		= true;		// 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
	}

	/**
	 * 【TAG】アクセスする ＵＲＬ を指定します(必須)。
	 *
	 * @og.tag
	 * 接続するＵＲＬを指定します。(例：http:// ･･････)
	 * ?以降のパラメータが含まれていても構いません。
	 * このURL に、keys,vals で指定されたパラメータも追加されます。
	 *
	 * @param	url	アクセスする ＵＲＬ
	 */
	public void setUrl( final String url ) {
		urlStr = nval( getRequestParameter( url ),urlStr );
	}

	/**
	 * 【TAG】プロキシ経由で接続する場合の、プロキシホスト名を指定します。
	 *
	 * @og.tag
	 * 接続先が、プロキシ経由の場合、プロキシのホスト名を指定します。
	 * 例：proxy.opengion.org
	 *
	 * @param	host	プロキシホスト名
	 */
	public void setProxyHost( final String host ) {
		proxyHost = nval( getRequestParameter( host ),proxyHost );
		useSystemUser = false;	// プロキシ接続時は、システムユーザーは使えません。
	}

	/**
	 * 【TAG】プロキシ経由で接続する場合の、プロキシポート番号を指定します。
	 *
	 * @og.tag
	 * 接続先が、プロキシ経由の場合、プロキシのポート番号を指定します。
	 * 例：8080
	 *
	 * @param	port	プロキシポート番号
	 */
	public void setProxyPort( final String port ) {
		proxyPort = nval( getRequestParameter( port ),proxyPort );
	}

	/**
	 * 【TAG】アクセスパラメータキーをCSV形式で複数指定します。
	 *
	 * @og.tag
	 * アクセスする ＵＲＬに追加するパラメータのキーを指定します。
	 * カンマ区切りで複数指定できます。
	 * vals 属性には、キーに対応する値を、設定してください。
	 * 例:<b>keys="command,SYSTEM_ID"</b> vals="NEW,GE"
	 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。
	 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。
	 *
	 * [SOAP対応]
	 * SOAPによるWebサービスの呼び出しの場合、keys,valsに指定された値より、env:Envelopタグを
	 * rootタグとするXMLデータを生成します。
	 * (BODY部分に直接XMLデータを出力することも可能です。)
	 * この際、項目名に'>'を含めることで、階層的なXMLデータを表現することができます。
	 * 例)
	 *   [属性定義]
	 *   keys="param0>AAA,param0>BBB,param1>CCC,DDD"
	 *   vals="v1,v2,v3,v4"
	 *   [XMLデータ(※データ部のみ)]
	 *   &lt;param0&gt;
	 *     &lt;AAA&gt;v1&lt;/AAA&gt;
	 *     &lt;BBB&gt;v2&lt;/BBB&gt;
	 *   &lt;/param0&gt;
	 *   &lt;param1&gt;
	 *     &lt;CCC&gt;v3&lt;/CCC&gt;
	 *   &lt;/param1&gt;
	 *   &lt;DDD&gt;v4&lt;/DDD&gt;
	 * 項目の値を"null"とすることで、XMLで言うところの「xsi:nil=\"true\"」のデータを表現すること
	 * もできます。
	 * また、キー名の先頭を'&#064;'にすることで、項目名に名前空間のPREFIXを付加することができます。
	 * 一般的には、JavaやRubyで実装されたWebサービスを呼び出しする場合は、必要ありませんが、
	 * .NETで実装されたWebサービスを呼び出しする場合は、各項目にPREFIXを付与しないと、正しく
	 * パラメーターを渡すことができません。
	 * ※現時点では、keysの階層定義は、2階層まで対応しています。
	 *   3階層以上のXML構造を定義する場合は、postFile属性によるファイル指定又は、Body部分で直接
	 *   XMLデータを記述して下さい。
	 *
	 * @param	key リンク先に渡すキー
	 * @see		#setVals( String )
	 */
	public void setKeys( final String key ) {
		keys = getCSVParameter( key );
	}

	/**
	 * 【TAG】keys属性に対応する値をCSV形式で複数指定します。
	 *
	 * @og.tag
	 * キーに設定した値を、カンマ区切り文字で複数して出来ます。
	 * 指定順序は、キーと同じにしておいて下さい。
	 * 例:<b>keys="command,SYSTEM_ID"</b> vals="NEW,GE"
	 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。
	 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。
	 *
	 * @param	val names属性に対応する値
	 * @see		#setKeys( String )
	 */
	public void setVals( final String val ) {
		vals = getCSVParameter( val );
	}

	/**
	 * 【TAG】送信メソッドを指定します(GET/POST/SOAP)。
	 *
	 * @og.tag
	 * URLConnectTagのメソッドの初期設定はGETです。
	 * ここで"POST"(大文字)を指定するとkyes,valsの値セットをPOSTで送信します。
	 * (postKeyが設定されている場合はこの値に関係なくPOSTです)
	 *
	 * @og.rev 4.1.0.0 (2007/12/22) 新規作成
	 *
	 * @param	post_get	送信メソッド(GET/POST/SOAP)
	 */
	public void setMethod ( final String post_get ) {
		method = nval( getRequestParameter( post_get ), method );
	}

	/**
	 * 【TAG】Basic認証で接続するユーザーにSYSTEMユーザーを使用するかどうか[true/false]を指定します(初期値:true)。
	 *
	 * @og.tag
	 * useSystemUser="true"(初期値) の場合、URL接続時のコネクションに、Basic認証を
	 * 使用しますが、その時のユーザーにシステムユーザー(SYSTEM)を使用します。
	 * useSystemUser="false"の場合は、authUserPass で指定したユーザー：パスワードを
	 * 使用します。authUserPass で、何も指定されなかった場合は、Basic認証を使用しません。
	 * 初期値は、true(SYSTEMユーザー認証する) です。
	 *
	 * @param   flag [true:SYSTEMユーザー認証する/false:この接続のユーザーで認証する]
	 * @see #setAuthUserPass( String )
	 */
	public void setUseSystemUser( final String flag ) {
		useSystemUser = nval( getRequestParameter( flag ),useSystemUser );
	}

	/**
	 * 【TAG】Basic認証を使用して接続する場合のユーザー:パスワードを指定します(初期値:null)。
	 *
	 * @og.tag
	 * 接続時のユーザーとパスワードを、USER:PASSWD 形式で指定します。
	 * useSystemUser="false"の場合は、ここで指定したユーザーとパスワードを使用します。
	 * その場合に、何も指定しない場合は、Basic認証を使用しません。
	 *
	 * @param	userPass	接続のユーザーとパスワード(USER:PASSWD 形式)
	 * @see #setUseSystemUser( String )
	 */
	public void setAuthUserPass( final String userPass ) {
		authUserPass = nval( getRequestParameter( userPass ),authUserPass );
	}

	/**
	 * 【TAG】接続の結果を表示する場合にXSLT変換する場合のファイルを指定します。
	 *
	 * @og.tag
	 *
	 * 接続先のデータが、XML形式の場合、そのままでは、画面出力できない場合が
	 * あります。通常は、HTML形式に変換しますが、その変換に、 XSL ファイルを
	 * 指定することが可能です。
	 * display="true" の場合や、saveFile を指定した場合に、適用されます。
	 *
	 * @param	file	接続の結果を表示する場合にXSLT変換する場合のファイル
	 * @see #setSaveFile( String )
	 * @see #setDisplay( String )
	 */
	public void setXslFile( final String file ) {
		xslFile = HybsSystem.url2dir( nval( getRequestParameter( file ),xslFile ) );
	}

	/**
	 * 【TAG】接続の結果を表示するかどうかを指定します(初期値:false)。
	 *
	 * @og.tag
	 * true で、接続結果を表示します。 false では、何も表示しません(初期値:false)
	 * 接続結果を表示する使い方より、admin 画面に接続して、キャッシュクリアするような
	 * 使い方が多いと考え、初期値は、false になっています。
	 * xslFile が指定されている場合、XSLT変換して画面表示します。
	 * display="true" と、saveFile を併用することはできません。
	 *
	 * @param	flag	接続の結果を表示するかどうか(初期値:false)
	 * @see #setSaveFile( String )
	 * @see #setXslFile( String )
	 */
	public void setDisplay( final String flag ) {
		display = nval( getRequestParameter( flag ),display );

		if( display && saveFile != null ) {
			String errMsg = "display=\"true\" と、saveFile を併用することはできません。";
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】接続の結果をファイルに保存します。
	 *
	 * @og.tag
	 * 接続先のデータを受け取って、ファイルに保存します。その場合、
	 * xslFile が指定されている場合、XSLT変換してセーブします。
	 * display="true" と、saveFile を併用することはできません。
	 *
	 * @param	file	接続の結果を表示する場合にXSLT変換する場合のファイル
	 * @see #setXslFile( String )
	 * @see #setDisplay( String )
	 */
	public void setSaveFile( final String file ) {
		saveFile = HybsSystem.url2dir( nval( getRequestParameter( file ),saveFile ) );

		if( display ) {
			String errMsg = "display=\"true\" と、saveFile を併用することはできません。";
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】POST を使って、postFile属性のファイル内容を送信する時のキーを指定します。
	 *
	 * @og.tag
	 * 接続先にパラメータ(引数)を投げる場合に、POST を使用できます。
	 * そのときの キーをここで指定します。
	 * POSTするデータは、postFileで指定されたファイルか、BODY部に記述された文字列です。
	 *
	 * @param	key	POST を使って、postFile属性のファイル内容を送信する時のキー
	 * @see  #setPostFile( String )
	 */
	public void setPostKey( final String key ) {
		postKey = nval( getRequestParameter( key ),postKey );
	}

	/**
	 * 【TAG】POST を使って、postFile属性のファイル内容を送信します。
	 *
	 * @og.tag
	 * 接続先にパラメータ(引数)を投げる場合に、POST を使用できます。
	 * そのときの 送信データのファイルをここで指定します。
	 * postKey のみ指定されて、postFile が指定されない場合は、BODY部を送信します。
	 * SOAPによる呼び出しの場合は、ここ(BODY部での定義を含む)で、送信するXMLデータを
	 * 定義することができます。
	 *
	 * @param	file	接続の結果を表示する場合にXSLT変換する場合のファイル
	 * @see  #setPostKey( String )
	 */
	public void setPostFile( final String file ) {
		String postFile = nval( getRequestParameter( file ),null );

		if( postFile != null ) {
			FileString fileStr = new FileString();
			fileStr.setFilename( HybsSystem.url2dir( postFile ) );
			postData = fileStr.getValue();
		}
	}

	/**
	 * 【TAG】(通常は使いません) 接続エラーを無視する場合にtrueとします(初期値false)。
	 *
	 * @og.tag
	 * trueにするとConnectで発生したエラーを投げずに処理を続行します。
	 * (標準エラー出力にエラー内容は出力されます)
	 * 接続エラーが発生しても処理を中断したくない場合に設定します。
	 *
	 * @og.rev 4.1.1.0 (2008/01/22) 新規追加
	 *
	 * @param	flag	エラーを無視する場合にtrue
	 */
	public void setErrNeglect( final String flag ) {
		errNglctFlag = nval( getRequestParameter( flag ), errNglctFlag );
	}

	/**
	 * 【TAG】SOAPによるWebサービスの呼び出しで、メソッド名及びパラメーターの名前空間を指定します。
	 *
	 * @og.tag
	 * SOAPによるWebサービスの呼び出しで、メソッド名及びパラメーターの名前空間を指定します。
	 * この名前空間は、通常WSDLファイルのdescriptionsタグのtargetNamespace属性の値により
	 * 定義されます。
	 *
	 * @og.rev 5.1.5.0 (2010/04/01) 新規追加
	 *
	 * @param	ns	名前空間
	 */
	public void setSoapNameSpace( final String ns ) {
		soapNameSpace = nval( getRequestParameter( ns ), soapNameSpace );
	}

	/**
	 * 【TAG】SOAPによるWebサービスの呼び出しで、メソッド名を指定します。
	 *
	 * @og.tag
	 * SOAPによるWebサービスの呼び出しで、メソッド名を指定します。
	 * WSDLファイルで定義されるoperationタグのname属性の値に相当します。
	 *
	 * @og.rev 5.1.5.0 (2010/04/01) 新規追加
	 *
	 * @param	method	メソッド名
	 */
	public void setSoapMethodName( final String method ) {
		soapMethodName = nval( getRequestParameter( method ), soapMethodName );
	}

	/**
	 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します。
	 *
	 * @og.tag
	 * 検索結果より、DBTableModelオブジェクトを作成します。これを、以下のview 等のタグに
	 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
	 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
	 * この tableId 属性を利用して、メモリ空間を分けます。
	 * 初期値は、HybsSystem.TBL_MDL_KEY です。
	 *
	 * @param	id sessionに登録する時の ID
	 */
	public void setTableId( final String id ) {
		tableId   = nval( getRequestParameter( id ),tableId );
	}

	/**
	 * 【TAG】結果のXMLをDBTableModelに変換する際に、行のキーとなるタグ名を指定します。
	 *
	 * @og.tag
	 * 結果のXMLを表形式に変換する際に、行のキーとなるタグ名を指定します。
	 * このキーのタグを基点として、colKeysで指定されたタグの値を各項目の値として取り込みます。
	 * (詳細は、colKeysのタグリブ属性マニュアルを参照して下さい。)
	 *
	 * @param	key 行のキーとなるタグ名
	 * @see #setColKeys( String )
	 */
	public void setRowKey( final String key ) {
		rowKey = nval( getRequestParameter( key ),rowKey );
	}

	/**
	 * 【TAG】結果のXMLをDBTableModelに変換する際に、項目のキーとなるタグ名の一覧を指定します。
	 *
	 * @og.tag
	 * 結果のXMLをDBTableModelに変換する際に、項目のキーとなるタグ名の一覧を指定します。
	 * rowKeyで行を、colKeysで項目を表現し、rowKeyのタグで囲われた固まりを1つの行とみなします。
	 * このため、colKeysに指定されたキーのタグでも、rowKeyの外にある場合は、取り込み対象となりません。
	 *
	 * また、キーにPARENT_TAG、PARENT_FULL_TAGを指定することで、rowKeyで指定されたタグの
	 * 直近の親タグ、及びフルの親タグ名(親タグの階層を">[タグA]>[タグB]>[タグC]>"で表現)を
	 * 取得することができます。
	 *
	 * @param	keys 項目のキーとなるタグ名の一覧
	 */
	public void setColKeys( final String keys ) {
		colKeys = StringUtil.csv2Array( getRequestParameter( keys ) );
	}

	/**
	 * 【TAG】結果のXMLを変換する際に、パラメータ(Attributes)として取り込むキーの一覧を指定します。
	 *
	 * @og.tag
	 * 結果のXMLを変換する際に、パラメータ(Attributes)として取り込むキーの一覧を指定します。
	 * ここで指定されたキーのタグの値を取り出し、{&#064;XX}形式(Attributes)として処理できるようにします。
	 *
	 * @param	keys パラメーター(Attributes)のキーとなるタグ名の一覧
	 */
	public void setRtnKeys( final String keys ) {
		rtnKeys = StringUtil.csv2Array( getRequestParameter( keys ) );
	}

	/**
	 * 【TAG】データの入出力のエンコードを指定します。
	 *
	 * @og.tag
	 * データの入出力のエンコードを指定します。
	 * 初期値は、"UTF-8"です。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) 新規作成
	 * @param	enc	エンコード
	 */
	public void setEncode( final String enc ) {
		encode = nval( getRequestParameter( enc ), encode );
	}

	/**
	 * タグの名称を、返します。
	 * 自分自身のクラス名より、自動的に取り出せないため、このメソッドをオーバーライドします。
	 *
	 * @og.rev 4.0.0 (2005/01/31) 新規追加
	 *
	 * @return  タグの名称
	 */
	@Override
	protected String getTagName() {
		return "urlConnect" ;
	}

	/**
	 * 【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:false)。
	 *
	 * @og.tag
	 * (通常使いません)タグで処理される処理が、メインとなるトランザクション処理かどうかを指定します。(初期値:false)
	 * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが
	 * ファイルダウンロードの対象の表になります。
	 *
	 * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。
	 * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい
	 * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から
	 * 除外することができます。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) 新規作成
	 *
	 * @param  flag メイントランザクションかどうか
	 */
	public void setMainTrans( final String flag ) {
		isMainTrans = nval( getRequestParameter( flag ),isMainTrans );
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 */
	@Override
	public String toString() {
		return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
				.println( "VERSION"			,VERSION		)
				.println( "method"			,method			)
				.println( "urlStr"			,urlStr			)
				.println( "keys"			,StringUtil.array2csv( keys ) )
				.println( "vals"			,StringUtil.array2csv( vals ) )
				.println( "proxyHost"		,proxyHost		)
				.println( "proxyPort"		,proxyPort		)
				.println( "useSystemUser"	,useSystemUser	)
				.println( "authUserPass"	,authUserPass	)
				.println( "display"			,display		)
				.println( "postData"		,postData		)
				.println( "xslFile"			,xslFile		)
				.println( "saveFile"		,saveFile		)
				.println( "errNglctFlag"	,errNglctFlag	)
				.println( "soapNameSpace"	,soapNameSpace	)
				.println( "soapMethodName"	,soapMethodName	)
				.println( "tableId"			,tableId		)
				.println( "rowKey"			,rowKey			)
				.println( "colKeys"			,StringUtil.array2csv( colKeys ) )
				.println( "rtnKeys"			,StringUtil.array2csv( rtnKeys ) )
				.println( "Other..."		,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
