/*
 * Copyright 2002-2008 the original author or authors.
 *
 * 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 anyframe.sample.struts.services.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import javax.security.auth.Subject;
import javax.security.auth.login.FailedLoginException;
import javax.sql.DataSource;

import org.apache.commons.dbcp.SQLNestedException;

import anyframe.common.exception.BaseException;
import anyframe.sample.struts.services.AuthenticationService;

import com.tagish.auth.TypedPrincipal;

public class DBAuthenticationServiceImpl implements AuthenticationService{

	private String sqlQuery = null;

	private DataSource dataSource = null;

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	
	 public void setSqlQuery(String sqlQuery) {
		this.sqlQuery = sqlQuery;
	}
	 
	public Subject authenticate(anyframe.sample.struts.services.UserVO userVO)
			throws Exception {

		Subject subject = null;
		ResultSet rsu = null;
		PreparedStatement pstmt = null;
		Connection conn = null;

		String userId = userVO.getUserId();
		String password = userVO.getPassword();

		try {
			conn = dataSource.getConnection();

			pstmt = conn.prepareStatement(sqlQuery);

			pstmt.setString(1, userId);
			pstmt.setString(2, password);

			rsu = pstmt.executeQuery();

			if (rsu.next()) {

				userId = rsu.getString(1);
				String userName = rsu.getString(2);
				rsu.getString(3);
				String grade = rsu.getString(5);

				Set principals = new HashSet();
				Set credentials = new HashSet();

				principals
						.add(new TypedPrincipal(userName, TypedPrincipal.USER));

				StringTokenizer tokens = new StringTokenizer(grade, ",");
				while (tokens.hasMoreTokens()) {
					principals.add(new TypedPrincipal(tokens.nextToken(),
							TypedPrincipal.GROUP));
				}

				subject = new Subject(false, principals, credentials,
						credentials);
			} else {
				throw new FailedLoginException();
			}
		} catch (Exception e) {
			if (e instanceof FailedLoginException) {
				throw new FailedLoginException();
			}else if(e instanceof SQLNestedException){
				throw new BaseException("Plase Start HSQLDB.");
			}else{
				throw new BaseException("Sorry, Login Fail.");
			}
		} finally {
			try {
				if (rsu != null) {
					rsu.close();
				}
				if (pstmt != null) {
					pstmt.close();
				}
				if (conn != null) {
					conn.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return subject;
	}
}
