/*


 ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


 */

package com.sap.dbtech.jdbcext;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.naming.Reference;
import javax.naming.StringRefAddr;

import com.sap.dbtech.jdbc.DriverSapDB;
import com.sap.dbtech.jdbc.exceptions.SQLExceptionSapDB;
import com.sap.dbtech.util.MessageKey;
import com.sap.dbtech.util.MessageTranslator;

/**
 * This class collects all properties and flags that may be set on a SAP DB data
 * source.
 */
public class DataSourceSapDBBase {
	public static final int DEFAULT_LOGINTIMEOUT = 30;

	protected Properties connectProperties;

	protected PrintWriter logWriter;

	public DataSourceSapDBBase() {
		connectProperties = new Properties();
		connectProperties.setProperty("serverName", "localhost");
		connectProperties.setProperty("port", "7210");
	}

	public String getUser() {
		return connectProperties.getProperty("user");
	}

	public void setLoginTimeout(int timeout) {
		connectProperties
				.setProperty("logintimeout", Integer.toString(timeout));
	}

	public int getLoginTimeout() {
		String s = connectProperties.getProperty("logintimeout");
		if (s == null) {
			return DEFAULT_LOGINTIMEOUT;
		}
		try {
			return Integer.parseInt(s);
		} catch (NumberFormatException numberFormatEx) {
			return DEFAULT_LOGINTIMEOUT;
		}
	}

	public void setTimeout(int timeout) {
		connectProperties.setProperty("timeout", Integer.toString(timeout));
	}

	public int getTimeout() {
		String s = connectProperties.getProperty("timeout");
		if (s == null) {
			return 0;
		}
		try {
			return Integer.parseInt(s);
		} catch (NumberFormatException numberFormatEx) {
			return 0;
		}
	}

	public String getPassword() {
		return connectProperties.getProperty("password");
	}

	public String getDescription() {
		return connectProperties.getProperty("description");
	}

	public String getDatabaseName() {
		return connectProperties.getProperty("databaseName");
	}

	public String getServerName() {
		return connectProperties.getProperty("serverName");
	}

	public String getSqlMode() {
		return connectProperties.getProperty("sqlmode", "INTERNAL");
	}

	public void setUser(String user) {
		connectProperties.setProperty("user", user);
	}

	public void setPassword(String password) {
		connectProperties.setProperty("password", password);
	}

	public void setDatabaseName(String databaseName) {
		connectProperties.setProperty("databaseName", databaseName
				.toUpperCase());
	}

	public void setServerName(String serverName) {
		connectProperties.setProperty("serverName", serverName);
	}

	public void setPort(int port) {
		connectProperties.setProperty("port", Integer.toString(port));
	}

	public int getPort() {
		try {
			return Integer.parseInt(connectProperties.getProperty("port",
					"7210"));
		} catch (NumberFormatException nfex) {
			return 7210;
		}
	}

	public void setUrl(String url) {
		setServerName(serverNameFromUrl(url));
		setDatabaseName(databaseNameFromUrl(url));
		setPort(portFromUrl(url));
	}

	public String getURL() {
		return "jdbc:sapdb://" + getServerName() + ":" + getPort() + "/"
				+ getDatabaseName();
	}

	private int portFromUrl(String url) {
		int slashPos;
		int closingSlashPos;
		String host;
		String dbname;
		String dburl;
		int urlLength = url.length();
		int port = 7210;

		slashPos = "jdbc:sapdb:".length();
		if ((urlLength >= slashPos + 3)
				&& url.substring(slashPos, slashPos + 2).equals("//")) {
			closingSlashPos = url.indexOf('/', slashPos + 2);
			host = url.substring(slashPos + 2, closingSlashPos);
			if (host.indexOf(":") != -1) {
				try {
					port = Integer.parseInt(host
							.substring(host.indexOf(":") + 1));
				} catch (NumberFormatException nfex) {
				}
			}
		}
		return port;
	}

	private String serverNameFromUrl(String url) {
		int slashPos;
		int closingSlashPos;
		String host;
		String dbname;
		String dburl;
		int urlLength = url.length();

		slashPos = "jdbc:sapdb:".length();
		if ((urlLength >= slashPos + 3)
				&& url.substring(slashPos, slashPos + 2).equals("//")) {
			closingSlashPos = url.indexOf('/', slashPos + 2);
			host = url.substring(slashPos + 2, closingSlashPos);
			if (host.length() == 0) {
				host = "localhost";
			}
			if (host.indexOf(":") != -1) {
				host = host.substring(0, host.indexOf(":"));
			}
		} else {
			host = "localhost";
		}
		return host;
	}

	private String databaseNameFromUrl(String url) {
		int slashPos;
		int closingSlashPos;
		String host;
		String dbname;
		String dburl;
		int urlLength = url.length();

		slashPos = "jdbc:sapdb:".length();
		if ((urlLength >= slashPos + 3)
				&& url.substring(slashPos, slashPos + 2).equals("//")) {
			closingSlashPos = url.indexOf('/', slashPos + 2);
			dbname = url.substring(closingSlashPos + 1, urlLength);
		} else {
			dbname = url.substring(slashPos, urlLength);
		}
		return dbname.toUpperCase();
	}

	public void setSqlMode(String sqlMode) {
		connectProperties.setProperty("sqlmode", sqlMode);
	}

	public PrintWriter getLogWriter() {
		return this.logWriter;
	}

	public void setLogWriter(PrintWriter logWriter) {
		this.logWriter = logWriter;
	}

	public void setTransport(String transport) {
		connectProperties.setProperty("transport", transport);
	}

	public String getTransport() {
		return connectProperties.getProperty("transport", "socket");
	}

	public String getCache() {
		return connectProperties.getProperty("cache");
	}

	public void setCache(String cache) {
		connectProperties.setProperty("cache", cache);
	}

	public void setCacheSize(String cacheSize) {
		connectProperties.setProperty("cachesize", cacheSize);
	}

	public String getCacheSize() {
		return connectProperties.getProperty("cachesize");
	}

	public void setUnicode(String unicode) {
		connectProperties.setProperty("unicode", unicode);
	}

	public String getUnicode() {
		return connectProperties.getProperty("unicode", "false");
	}

	public void setSpaceOption(String option) {
		connectProperties.setProperty("spaceoption", option);
	}

	public String getSpaceOption() {
		return connectProperties.getProperty("spaceoption", "false");
	}

	public void setReconnect(String reconnect) {
		connectProperties.setProperty("reconnect", reconnect);
	}

	public String getReconnect() {
		return connectProperties.getProperty("reconnect");
	}

	public void setTrace(String trace) {
		connectProperties.setProperty("trace", trace);
	}

	public String getTrace() {
		return connectProperties.getProperty("trace");
	}

	public void setTraceSize(String tracesize) {
		connectProperties.setProperty("tracesize", tracesize);
	}

	public String getTraceSize() {
		return connectProperties.getProperty("tracesize");
	}

	public void setXATrace(String xatrace) {
		connectProperties.setProperty("xatrace", xatrace);
	}

	public String getXATrace() {
		return connectProperties.getProperty("xatrace");
	}

	public void setProperties(Properties p) {
		this.connectProperties = (Properties) p.clone();
		// fixup if url is only given ...
		if (connectProperties.getProperty("url") != null
				&& connectProperties.getProperty("databaseName") == null) {
			this.setUrl(connectProperties.getProperty("url"));
		}
	}

	public Connection openPhysicalConnection() throws SQLException {
		Properties p = (Properties) connectProperties.clone();
		String serverName = p.getProperty("serverName", "localhost");
		String databaseName = p.getProperty("databaseName");

		if (databaseName == null) {
			throw new SQLExceptionSapDB(MessageTranslator
					.translate(MessageKey.ERROR_DATABASE_NOT_SET));
		}
		String url = "jdbc:sapdb://" + serverName + ":" + getPort() + "/"
				+ databaseName;
		return DriverSapDB.singleton().connect(url, p);
	}

	public Connection openPhysicalConnection(String username, String password)
			throws SQLException {
		Properties p = (Properties) connectProperties.clone();
		p.setProperty("user", username);
		p.setProperty("password", password);
		String serverName = p.getProperty("serverName", "localhost");
		String databaseName = p.getProperty("databaseName");

		if (databaseName == null) {
			throw new SQLExceptionSapDB(MessageTranslator
					.translate(MessageKey.ERROR_DATABASE_NOT_SET));
		}
		String url = "jdbc:sapdb://" + serverName + ":" + getPort() + "/"
				+ databaseName;
		return DriverSapDB.singleton().connect(url, p);
	}

	public Connection openPhysicalConnection(Properties p) throws SQLException {
		String serverName = p.getProperty("serverName", "localhost");
		String databaseName = p.getProperty("databaseName");

		if (databaseName == null) {
			throw new SQLExceptionSapDB(MessageTranslator
					.translate(MessageKey.ERROR_DATABASE_NOT_SET));
		}
		String url = "jdbc:sapdb://" + serverName + ":"
				+ p.getProperty("port", "7210") + "/" + databaseName;
		return DriverSapDB.singleton().connect(url, p);
	}

	protected Reference createReference(String classname) {
		Reference result = new Reference(classname,
				"com.sap.dbtech.jdbcext.DataSourceSapDBFactory", null);
		if (getUser() != null) {
			result.add(new StringRefAddr("user", getUser()));
		}
		result.add(new StringRefAddr("logintimeout", Integer
				.toString(getLoginTimeout())));

		if (connectProperties.getProperty("timeout") != null) {
			result.add(new StringRefAddr("timeout", Integer
					.toString(getTimeout())));
		}
		if (getPassword() != null) {
			result.add(new StringRefAddr("password", getPassword()));
		}
		if (getDescription() != null) {
			result.add(new StringRefAddr("description", getDescription()));
		}
		if (getDatabaseName() != null) {
			result.add(new StringRefAddr("databaseName", getDatabaseName()));
		}
		if (getServerName() != null) {
			result.add(new StringRefAddr("serverName", getServerName()));
		}
		if (getSqlMode() != null) {
			result.add(new StringRefAddr("sqlmode", getSqlMode()));
		}
		result.add(new StringRefAddr("port", Integer.toString(getPort())));
		if (getTransport() != null) {
			result.add(new StringRefAddr("transport", getTransport()));
		}
		if (getCache() != null) {
			result.add(new StringRefAddr("cache", getCache()));
		}
		if (getCacheSize() != null) {
			result.add(new StringRefAddr("cachesize", getCacheSize()));
		}
		if (getUnicode() != null) {
			result.add(new StringRefAddr("unicode", getUnicode()));
		}
		if (getReconnect() != null) {
			result.add(new StringRefAddr("reconnect", getReconnect()));
		}
		if (getTrace() != null) {
			result.add(new StringRefAddr("trace", getTrace()));
		}
		if (getTraceSize() != null) {
			result.add(new StringRefAddr("tracesize", getTraceSize()));
		}
		if (getXATrace() != null) {
			result.add(new StringRefAddr("xatrace", getXATrace()));
		}

		return result;
	}
}
