/*
* Copyright (C) 2007 SQL Explorer Development Team http://sourceforge.net/projects/eclipsesql
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package net.sourceforge.sqlexplorer.dbproduct;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import net.sourceforge.sqlexplorer.ExplorerException;
import net.sourceforge.sqlexplorer.plugin.SQLExplorerPlugin;
import org.dom4j.Element;
import org.dom4j.tree.DefaultElement;
/**
* Represents a configured Alias, maintaining a pool of available connections
*
* Note that this superceeds the old net.sourceforge.sqlexplorer.AliasModel and
* net.sourceforge.sqlexplorer.sessiontree.model.* classes.
*
* This is basically a large rewrite of SQLAlias, which was originally taken from SquirrelSQL; it was based on and used
* parts of Squirrel which no longer exist (even in the SquirrelSQL CVS on Sourceforge) and are effectively
* undocumented. Changes needed to fix bugs relating to transactions and multiple logons per alias meant that keeping
* the old code became unmaintainable, hence the sweeping rewrite.
*
* @author John Spackman
*/
public class Alias {
/* package */static final String ALIASES = "aliases";
/* package */static final String ALIAS = "alias";
/* package */static final String AUTO_LOGON = "auto-logon";
/* package */static final String CONNECT_AT_STARTUP = "connect-at-startup";
/* package */static final String DEFAULT_USER = "default-user";
/* package */static final String DRIVER_ID = "driver-id";
/* package */static final String FOLDER_FILTER_EXPRESSION = "folder-filter-expression";
/* package */static final String HAS_NO_USER_NAME = "has-no-user-name";
/* package */static final String NAME = "name";
/* package */static final String NAME_FILTER_EXPRESSION = "name-filter-expression";
/* package */static final String SCHEMA_FILTER_EXPRESSION = "schema-filter-expression";
/* package */static final String URL = "url";
/* package */static final String USERS = "users";
private static int s_serialNo = 0;
// Descriptive name of the Alias
private String name;
// Driver
private String driverId;
// Database URL
private String url;
// Whether to auto-logon the default user
private boolean autoLogon;
// Whether to connect at startup
private boolean connectAtStartup;
// Filters
private String folderFilterExpression = "";
private String nameFilterExpression = "";
private String schemaFilterExpression = "";
// Whether username/password are required
private boolean hasNoUserName;
// Default user
private User defaultUser;
// List of all users (including the default user), indexed by user name
private TreeMap<String, User> users = new TreeMap<String, User>();
/**
* Constructs a new Alias with a given name
*
*/
public Alias(String name) {
this.name = name;
}
/**
* Constructs a new Alias with a unique name
*
*/
public Alias() {
this("new-alias-" + (++s_serialNo));
}
/**
* Constructs an Alias from XML, previously obtained from describeAsXml()
*
* @param root
*/
public Alias(Element root) {
autoLogon = Boolean.parseBoolean(root.attributeValue(AUTO_LOGON));
connectAtStartup = Boolean.parseBoolean(root.attributeValue(CONNECT_AT_STARTUP));
driverId = root.attributeValue(DRIVER_ID);
String str = root.attributeValue(HAS_NO_USER_NAME);
if (str != null) {
hasNoUserName = Boolean.parseBoolean(str);
}
name = root.elementText(NAME);
url = root.elementText(URL);
folderFilterExpression = root.elementText(FOLDER_FILTER_EXPRESSION);
nameFilterExpression = root.elementText(NAME_FILTER_EXPRESSION);
schemaFilterExpression = root.elementText(SCHEMA_FILTER_EXPRESSION);
if (hasNoUserName) {
User user = new User("", "");
addUser(user);
setDefaultUser(user);
} else {
Element usersElem = root.element(USERS);
if (usersElem != null) {
List<Element> list = usersElem.elements(User.USER);
if (list != null) {
for (Element userElem : list) {
User user = new User(userElem);
// if (user.getUserName() != null && user.getUserName().trim().length() > 0) {
addUser(user);
// }
}
}
String defaultUserName = root.elementText(DEFAULT_USER);
if (defaultUserName != null) {
User user = users.get(defaultUserName);
if (user != null) {
defaultUser = user;
}
}
}
}
}
/**
* Describes this alias in XML; the result can be passed to the Alias(Element) constructor to refabricate it
*
* @return
*/
public Element describeAsXml() {
DefaultElement root = new DefaultElement(ALIAS);
root.addAttribute(AUTO_LOGON, Boolean.toString(autoLogon));
root.addAttribute(CONNECT_AT_STARTUP, Boolean.toString(connectAtStartup));
root.addAttribute(DRIVER_ID, driverId);
root.addAttribute(HAS_NO_USER_NAME, Boolean.toString(hasNoUserName));
root.addElement(NAME).setText(name);
root.addElement(URL).setText(url);
root.addElement(FOLDER_FILTER_EXPRESSION).setText(folderFilterExpression);
root.addElement(NAME_FILTER_EXPRESSION).setText(nameFilterExpression);
root.addElement(SCHEMA_FILTER_EXPRESSION).setText(schemaFilterExpression);
Element usersElem = root.addElement(USERS);
for (User user : users.values()) {
// user.setPassword(ALIAS)
usersElem.add(user.describeAsXml());
}
if (defaultUser != null) {
root.addElement(DEFAULT_USER).setText(defaultUser.getUserName());
}
return root;
}
/**
* Constructs an Alias as a duplicate of another, but with a new name
*
* @param copyFrom
*/
public Alias(Alias copyFrom) {
this("Copy of " + copyFrom.getName());
if (copyFrom.defaultUser != null) {
defaultUser = copyFrom.defaultUser.createCopy();
addUser(defaultUser);
}
}
/**
* Closes all connections
*
* @throws ExplorerException
*/
public void closeAllConnections() {
for (User user : users.values()) {
user.closeAllSessions();
}
}
/**
* Removes this Alias (permanently)
*
* @throws ExplorerException
*/
public void remove() {
closeAllConnections();
SQLExplorerPlugin.getDefault().getAliasManager().removeAlias(getName());
}
/**
* Returns the name of the alias
*
* @return
*/
public String getName() {
return name;
}
/**
* Adds or redefines a User; if the user does not exist (IE there is no User object with the same user name) then
* the new user is added, but if a User already exists then the passed in User is used to reconfigure the existing
* User. In both cases addUser() will return the User object which remains in this Alias instance; EG when
* reconfiguring a User, the reconfigured, pre-existing User object is returned.
*
* @param user
* @return the User object which is kept in the list of Users
*/
public User addUser(User user) {
if (user.getAlias() != null) {
if (user.getAlias() != this) {
throw new IllegalArgumentException("User already belongs to a different Alias");
}
return user;
}
// if (user.getUserName() == null || user.getUserName().length() == 0)
// throw new IllegalArgumentException("Illegal user name");
// if (!users.isEmpty() && hasNoUserName)
// throw new IllegalArgumentException("Cannot add users when usernames are not required by the alias");
User existingUser = users.get(user.getUserName());
if (existingUser != null) {
existingUser.mergeWith(user);
return existingUser;
}
users.put(user.getUserName(), user);
user.setAlias(this);
if (defaultUser == null) {
defaultUser = user;
}
SQLExplorerPlugin.getDefault().getAliasManager().modelChanged();
return user;
}
/**
* Removes the User from the list of users
*
* @param user
*/
public void removeUser(User user) {
boolean isDefault = user == defaultUser;
if (user.getAlias() != this) {
throw new IllegalArgumentException("User belongs to a different Alias");
}
user.closeAllSessions();
user.setAlias(null);
users.remove(user.getUserName());
if (isDefault) {
if (!users.isEmpty()) {
defaultUser = users.values().iterator().next();
} else {
defaultUser = null;
}
}
}
/**
* Returns the user with a given name
*
* @param userName
* @return
*/
public User getUser(String userName) {
return users.get(userName);
}
/**
* Returns a list of all users
*
* @return
*/
public Collection<User> getUsers() {
return users.values();
}
/**
* Returns true if the user belongs to this Alias
*
* @param user
* @return
*/
public boolean contains(User user) {
return users.values().contains(user);
}
/**
* Returns the ISQLDriver underlying this alias
*
* @return
*/
public ManagedDriver getDriver() {
return SQLExplorerPlugin.getDefault().getDriverModel().getDriver(driverId);
}
/**
* Sets the underlying driver
*
* @param driver
*/
public void setDriver(ManagedDriver driver) {
driverId = driver.getId();
}
/**
* Returns true if filtering is applied
*
* @return
*/
public boolean isFiltered() {
return (folderFilterExpression != null && folderFilterExpression.trim().length() > 0)
|| (nameFilterExpression != null && nameFilterExpression.trim().length() > 0)
|| (schemaFilterExpression != null && schemaFilterExpression.trim().length() > 0);
}
public boolean isAutoLogon() {
return autoLogon;
}
public void setAutoLogon(boolean autoLogon) {
this.autoLogon = autoLogon;
}
public boolean isConnectAtStartup() {
return connectAtStartup;
}
public void setConnectAtStartup(boolean connectAtStartup) {
this.connectAtStartup = connectAtStartup;
}
public User getDefaultUser() {
return defaultUser;
}
/**
* Sets the default user, adding it to the list of users if necessary; if the defaultUser is a new user and a user
* with the same username already exists then the existing user is updated and returned (see addUser())
*
* @param defaultUser
* @return
*/
public User setDefaultUser(User defaultUser) {
this.defaultUser = addUser(defaultUser);
return this.defaultUser;
}
public String getFolderFilterExpression() {
return folderFilterExpression;
}
public void setFolderFilterExpression(String folderFilterExpression) {
this.folderFilterExpression = folderFilterExpression;
}
public String getNameFilterExpression() {
return nameFilterExpression;
}
public void setNameFilterExpression(String nameFilterExpression) {
this.nameFilterExpression = nameFilterExpression;
}
public String getSchemaFilterExpression() {
return schemaFilterExpression;
}
public void setSchemaFilterExpression(String schemaFilterExpression) {
this.schemaFilterExpression = schemaFilterExpression;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void setName(String name) {
this.name = name;
}
public String getDriverId() {
return driverId;
}
/**
* @return the hasNoUserName
*/
public boolean hasNoUserName() {
return hasNoUserName;
}
/**
* @param hasNoUserName the hasNoUserName to set
*/
public void setHasNoUserName(boolean hasNoUserName) {
if (this.hasNoUserName == hasNoUserName) {
return;
}
this.hasNoUserName = hasNoUserName;
if (hasNoUserName) {
for (User user : users.values()) {
user.setAlias(null);
}
users.clear();
User user = new User("", "");
addUser(user);
setDefaultUser(user);
} else {
for (User user : users.values()) {
user.setAlias(null);
}
users.clear();
}
}
}