/*
 * 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.fukurou.queue;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * MQサーバへのメッセージキュー送信用クラス
 * 
 * MQサーバへのメッセージキュー送信用のクラスです。
 * Apache ActiveMQとAmazonMQへの送信が可能です。
 * tomcatからの送信(JNDI利用)と、
 * バッチ処理(urlを指定し接続)の２通りが可能です。
 * 
 * ※Apache ActiveMQとAmazonMQの切り替えは、
 * jmsServerの接続先URLを変更するのみで接続の変更が可能です。
 * (proxy環境からAmazonMqへの接続は行えない場合があります)
 * 
 * @og.group メッセージ連携
 * 
 * @og.rev 5.10.14.0 (2019/08/01) 新規作成
 * 
 * @version 5
 * @author oota
 * @since JDK7
 *
 */
public class QueueSend_MQ implements QueueSend {
	private Connection connection = null;
	private  Session session = null;
	private  MessageProducer sender = null;
	private Context ctx = null;
	// バッチ用フィールド
	private  boolean batch = false;
	private String mqUserId = "";
	private String mqPassword = "";

	/**
	 * 接続処理
	 * MQサーバに接続を行います。
	 * 
	 * @param jmsServer jmsサーバ接続名(バッチの場合はurl)
	 */
	public void connect(final String jmsServer) {
		try {
			ctx = new InitialContext();
			// 1. Connectionの作成s
			QueueConnectionFactory factory = null;
			if (batch) {
				// バッチ処理の場合。URL指定で、ユーザIDとパスワードを指定して接続。
				mqUserId = System.getProperty("mqUserId");
				mqPassword = System.getProperty("mqPassword");
				factory = new ActiveMQConnectionFactory(jmsServer);
				connection = (ActiveMQConnection)factory.createConnection(mqUserId, mqPassword);
			} else {
				// tomcat接続の場合。JNDIを利用して接続。
				factory = (QueueConnectionFactory) ctx.lookup("java:comp/env/" + jmsServer);
				connection = (ActiveMQConnection)factory.createConnection();
			}

			// 2. Connectioの開始
			connection.start();

		} catch (JMSException jmse) {
			throwErrMsg("MQサーバーの接続に失敗しました。" + jmse.getMessage());
		} catch (NamingException ne) {
			throwErrMsg("名前解決に失敗しました。" + ne.getMessage());
		}
	}

	/**
	 * 接続処理
	 * MQサーバに接続します。
	 * connect(String jmsServer)と同じ処理になります。
	 *
	 * @og.rev 5.10.15.0 (2019/08/30) 引数追加対応
	 * 
	 * @param jmsServer jmsサーバ情報
	 * @param sqsAccessKey アクセスキー(MQサーバでは未使用)
	 * @param sqsSecretKey シークレットキー(MQサーバでは未使用)
	 */
	@Override
	public void connect(String jmsServer, String sqsAccessKey, String sqsSecretKey) {
		// MQではsqsAccessKeyとsqsSecretKeyは利用しません。
		connect(jmsServer);
	}


	/**
	 * エラーメッセージ送信
	 * 
	 * @og.rev 5.10.15.0 (2019/08/30) Hybs除外
	 * 
	 * @param errMsg エラーメッセージ
	 */
	public void throwErrMsg(final String errMsg) {
			throw new RuntimeException( errMsg );
	}

	/**
	 * メッセージ送信
	 * MQサーバにメッセージを送信します。
	 * 
	 * @param queueInfo 送信キュー情報
	 */
	@Override
	public void sendMessage(final QueueInfo queueInfo) {
		try {
			// 初期チェック
			if (connection == null) {
				throwErrMsg("MQサーバに接続されていません。");
			}

			// 1. QueueSessionの作成
			session = connection.createSession(queueInfo.isMqTransacted(), queueInfo.getMqAcknowledgeMode());
			if (session == null) {
				throwErrMsg("キューセッションの生成に失敗しました。");
			}

			// 2. Queueの作成
			Queue queue = null;
			queue = session.createQueue(queueInfo.getMqQueueName());
			sender = session.createProducer(queue);

			// 3. テキストメッセージの作成
			TextMessage msg = session.createTextMessage(queueInfo.getMessage());

			// 4. 送信処理
			sender.send(msg);

		} catch (JMSException e) {
			throwErrMsg("キューの送信処理に失敗しました。" + e.getMessage());
		}
	}

	/**
	 * クローズ処理
	 * MQサーバとの接続をクローズします。
	 */
	@Override
	public void close() {
		if (ctx != null) {
			try {
				ctx.close();
			} catch (Exception e) {
				System.out.println("ctxのクローズに失敗しました。");
			}
		}
		// 1. sender,session,connectionのクローズ処理
		if (sender != null) {
			try {
				sender.close();
			} catch (Exception e) {
				System.out.println("senderのクローズに失敗しました。");
			}
		}
		if (session != null) {
			try {
				session.close();
			} catch (Exception e) {
				System.out.println("sessionのクローズに失敗しました。");
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (Exception e) {
				System.out.println("connectionのクローズに失敗しました。");
			}
		}
	}

	/**
	 * バッチ処理判定フラグを設定します。
	 * バッチ処理の場合は引数で接続先情報を与えます。
	 * それ以外の場合(Tomcat)ではJNDIより情報を取得します。
	 * 
	 * @param batchFlg バッチ処理判定フラグ
	 */
	@Override
	public void setBatchFlg(final Boolean batchFlg) {
		batch = batchFlg;
	}

	/**
	 * テスト用メソッド
	 * テスト実行用です。
	 * 
	 * @param args 引数
	 */
	public static void main(String[] args) {
		System.out.println("main start");
		// 送信情報の設定
		String url = "tcp://localhost:61616";
		String queueName = "test01";
		String msg = "送信メッセージ";
		
		QueueInfo queueInfo = new QueueInfo();
		queueInfo.setMqQueueName(queueName);
		queueInfo.setMqTransacted(false);
		queueInfo.setMqAcknowledgeMode(QueueSession.AUTO_ACKNOWLEDGE);
		queueInfo.setMessage(msg);

		QueueSend queueSend = new QueueSend_MQ();
		queueSend.setBatchFlg(true);

		try {
			queueSend.connect(url,null,null);
			queueSend.sendMessage(queueInfo);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		} finally {
			queueSend.close();
		}

		System.out.println("main end");
	}
}
