/*
Copyright 2011-2016 Google Inc. All Rights Reserved.
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 com.google.security.zynamics.binnavi.Database;
import com.google.common.base.Preconditions;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntDeleteException;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntInitializeDatabaseException;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntLoadDataException;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntSaveDataException;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntUpdateDatabaseException;
import com.google.security.zynamics.binnavi.Database.Exceptions.InvalidDatabaseException;
import com.google.security.zynamics.binnavi.Database.Interfaces.ModuleConverter;
import com.google.security.zynamics.binnavi.Database.Interfaces.SQLProviderListener;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Creators.PostgreSQLProjectCreator;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Creators.PostgreSQLViewCreator;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLCommentFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLDataFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLDatabaseFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLEdgeFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLFunctionFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLInstructionFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLModuleFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLNodeFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLProjectFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLRawModuleFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLSectionFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLTagFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLTagManagerFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLTraceFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Functions.PostgreSQLTypeFunctions;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Loaders.PostgreSQLFunctionsLoader;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.PostgreSQLHelpers;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.PostgreSQLModuleConverter;
import com.google.security.zynamics.binnavi.Database.PostgreSQL.Savers.PostgreSQLViewSaver;
import com.google.security.zynamics.binnavi.Gui.GraphWindows.CommentDialogs.Interfaces.IComment;
import com.google.security.zynamics.binnavi.Gui.Users.Interfaces.IUser;
import com.google.security.zynamics.binnavi.Tagging.CTag;
import com.google.security.zynamics.binnavi.Tagging.CTagManager;
import com.google.security.zynamics.binnavi.Tagging.TagType;
import com.google.security.zynamics.binnavi.debug.models.trace.TraceList;
import com.google.security.zynamics.binnavi.disassembly.AddressSpaces.CAddressSpace;
import com.google.security.zynamics.binnavi.disassembly.CProject;
import com.google.security.zynamics.binnavi.disassembly.INaviCodeNode;
import com.google.security.zynamics.binnavi.disassembly.INaviEdge;
import com.google.security.zynamics.binnavi.disassembly.INaviFunction;
import com.google.security.zynamics.binnavi.disassembly.INaviFunctionNode;
import com.google.security.zynamics.binnavi.disassembly.INaviGroupNode;
import com.google.security.zynamics.binnavi.disassembly.INaviInstruction;
import com.google.security.zynamics.binnavi.disassembly.INaviModule;
import com.google.security.zynamics.binnavi.disassembly.INaviProject;
import com.google.security.zynamics.binnavi.disassembly.INaviRawModule;
import com.google.security.zynamics.binnavi.disassembly.INaviTextNode;
import com.google.security.zynamics.binnavi.disassembly.Modules.CModule;
import com.google.security.zynamics.binnavi.disassembly.Modules.CModuleInitializeReporter;
import com.google.security.zynamics.binnavi.disassembly.types.RawBaseType;
import com.google.security.zynamics.binnavi.disassembly.types.RawTypeInstance;
import com.google.security.zynamics.binnavi.disassembly.types.RawTypeInstanceReference;
import com.google.security.zynamics.binnavi.disassembly.types.RawTypeMember;
import com.google.security.zynamics.binnavi.disassembly.types.RawTypeSubstitution;
import com.google.security.zynamics.binnavi.disassembly.types.Section;
import com.google.security.zynamics.binnavi.disassembly.views.CView;
import com.google.security.zynamics.binnavi.disassembly.views.INaviView;
import com.google.security.zynamics.zylib.disassembly.IAddress;
import com.google.security.zynamics.zylib.general.ListenerProvider;
import com.google.security.zynamics.zylib.types.trees.ITreeNode;
import java.io.IOException;
import java.math.BigInteger;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
/**
* This class provides concrete implementations of all necessary queries to use BinNavi with
* PostgresqlSQL databases.
*/
public class PostgreSQLProvider extends AbstractSQLProvider {
/**
* Used to convert raw modules into BinNavi modules.
*/
protected final PostgreSQLModuleConverter moduleConverter;
public PostgreSQLProvider(final CConnection connection) {
super(connection);
Preconditions.checkNotNull(connection, "IE01210: Database connection can't be null");
moduleConverter = new PostgreSQLModuleConverter(this);
}
/**
* {@link ListenerProvider Listener provider} to keep track of {@link SQLProviderListener
* listeners} which want to get informed about changes in the provider.
*/
private final ListenerProvider<SQLProviderListener> listeners =
new ListenerProvider<SQLProviderListener>();
/**
* Determines whether a column with a given name exists in a given table.
*
* @param tableName Name of the table.
* @param columnname Name of the column.
*
* @return True, if the column exists. False, otherwise.
*
* @throws CouldntLoadDataException Thrown if the existence of the column could not be determined.
*/
private boolean hasColumn(final String tableName, final String columnname)
throws CouldntLoadDataException {
return PostgreSQLHelpers.hasColumn(getConnection(), tableName, columnname);
}
@Override
protected ModuleConverter getModuleConverter() {
return moduleConverter;
}
@Override
protected String getTablesFile() {
return "postgresql_tables.sql";
}
protected int hasAllTables(final List<String> tableNames) throws CouldntLoadDataException {
return PostgreSQLHelpers.getTableCount(getConnection(), tableNames);
}
@Override
protected boolean hasTable(final String tableName) throws CouldntLoadDataException {
return PostgreSQLHelpers.hasTable(getConnection(), tableName);
}
@Override
public IUser addUser(final String userName) throws CouldntSaveDataException {
return CGenericSQLUserFunctions.addUser(this, userName);
}
@Override
public Integer appendFunctionComment(
final INaviFunction function, final String commentText, final Integer userId)
throws CouldntSaveDataException {
return PostgreSQLFunctionFunctions.appendGlobalFunctionComment(
this, function, commentText, userId);
}
@Override
public Integer appendGroupNodeComment(
final INaviGroupNode groupNode, final String commentText, final Integer userId)
throws CouldntSaveDataException {
return PostgreSQLNodeFunctions.appendGroupNodeComment(this, groupNode, commentText, userId);
}
@Override
public Integer appendTextNodeComment(
final INaviTextNode textNode, final String commentText, final Integer userId)
throws CouldntSaveDataException {
return PostgreSQLNodeFunctions.appendTextNodeComment(this, textNode, commentText, userId);
}
@Override
public Integer appendTypeInstanceComment(
final int moduleId, final int instanceId, final String commentText, final Integer userId)
throws CouldntSaveDataException {
return PostgreSQLTypeFunctions.appendTypeInstanceComment(
this, moduleId, instanceId, commentText, userId);
}
@Override
public Integer appendSectionComment(
final int moduleId, final int sectionId, final String commentText, final Integer userId)
throws CouldntSaveDataException {
return PostgreSQLSectionFunctions.appendSectionComment(
this, moduleId, sectionId, commentText, userId);
}
@Override
public CAddressSpace createAddressSpace(final INaviProject project, final String name)
throws CouldntSaveDataException {
return PostgreSQLProjectFunctions.createAddressSpace(this, project, name);
}
@Override
public CModule createModule(final INaviRawModule rawModule)
throws CouldntLoadDataException, CouldntSaveDataException {
final CModule newModule = getModuleConverter().createModule(this, rawModule);
getModules().add(newModule);
return newModule;
}
/**
* Creates the raw modules table.
*
* @throws SQLException Thrown if the raw modules table could not be created.
*/
@Override
public void createModulesTable() throws SQLException {
executeUpdate("CREATE TABLE modules (" + " id serial, "
+ " name text NOT NULL, "
+ " architecture varchar( 32 ) NOT NULL, "
+ " base_address bigint NOT NULL, "
+ " exporter varchar( 256 ) NOT NULL, "
+ " version int NOT NULL, "
+ " md5 char( 32 ) NOT NULL, "
+ " sha1 char( 40 ) NOT NULL, "
+ " comment TEXT, "
+ " import_time timestamp NOT NULL DEFAULT current_timestamp, "
+ " PRIMARY KEY (id));"
);
}
@Override
public CProject createProject(final String name) throws CouldntSaveDataException {
final CProject project = PostgreSQLProjectCreator.createProject(this, name);
projects.add(project);
return project;
}
@Override
public CTag createTag(
final CTag parent, final String name, final String description, final TagType type)
throws CouldntSaveDataException {
return PostgreSQLTagFunctions.createTag(this, parent, name, description, type);
}
@Override
public TraceList createTrace(
final INaviModule module, final String name, final String description)
throws CouldntSaveDataException {
return PostgreSQLTraceFunctions.createTrace(this, module, name, description);
}
@Override
public TraceList createTrace(
final INaviProject project, final String name, final String description)
throws CouldntSaveDataException {
return PostgreSQLTraceFunctions.createTrace(this, project, name, description);
}
@Override
public CView createView(
final INaviModule module, final INaviView view, final String name, final String description)
throws CouldntSaveDataException {
return PostgreSQLViewCreator.createView(this, module, view, name, description);
}
@Override
public CView createView(
final INaviProject project, final INaviView view, final String name, final String description)
throws CouldntSaveDataException {
return PostgreSQLViewCreator.createView(this, project, view, name, description);
}
@Override
public void deleteFunctionComment(
final INaviFunction function, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLFunctionFunctions.deleteGlobalFunctionComment(this, function, commentId, userId);
}
@Override
public void deleteFunctionNodeComment(
final INaviFunctionNode functionNode, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLNodeFunctions.deleteLocalFunctionNodeComment(this, functionNode, commentId, userId);
}
@Override
public void deleteGlobalCodeNodeComment(
final INaviCodeNode codeNode, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLNodeFunctions.deleteGlobalCodeNodeComment(this, codeNode, commentId, userId);
}
@Override
public void deleteGlobalEdgeComment(
final INaviEdge edge, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLEdgeFunctions.deleteGlobalEdgeComment(this, edge, commentId, userId);
}
@Override
public void deleteGlobalInstructionComment(
final INaviInstruction instruction, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLInstructionFunctions.deleteGlobalInstructionComment(
this, instruction, commentId, userId);
}
@Override
public void deleteGroupNodeComment(
final INaviGroupNode groupNode, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLNodeFunctions.deleteGroupNodeComment(this, groupNode, commentId, userId);
}
@Override
public void deleteLocalCodeNodeComment(
final INaviCodeNode codeNode, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLNodeFunctions.deleteLocalCodeNodeComment(this, codeNode, commentId, userId);
}
@Override
public void deleteLocalEdgeComment(
final INaviEdge edge, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLEdgeFunctions.deleteLocalEdgeComment(this, edge, commentId, userId);
}
@Override
public void deleteLocalInstructionComment(final INaviCodeNode codeNode,
final INaviInstruction instruction, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLInstructionFunctions.deleteLocalInstructionComment(
this, codeNode, instruction, commentId, userId);
}
@Override
public void deleteTypeInstanceComment(
final int moduleId, final int instanceId, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLTypeFunctions.deleteTypeInstanceComment(
this, moduleId, instanceId, commentId, userId);
}
@Override
public void deleteSectionComment(
final int moduleId, final int sectionId, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLSectionFunctions.deleteSectionComment(this, moduleId, sectionId, commentId, userId);
}
@Override
public void deleteModule(final INaviModule module) throws CouldntDeleteException {
PostgreSQLModuleFunctions.deleteModule(this, module);
PostgreSQLRawModuleFunctions.deleteRawModule(this, module.getConfiguration().getRawModule());
}
@Override
public void deleteTextNodeComment(
final INaviTextNode textNode, final Integer commentId, final Integer userId)
throws CouldntDeleteException {
PostgreSQLNodeFunctions.deleteTextNodeComment(this, textNode, commentId, userId);
}
@Override
public void deleteUser(final IUser user) throws CouldntDeleteException {
CGenericSQLUserFunctions.deleteUser(this, user);
}
@Override
public void editTypeInstanceComment(
final int moduleId, final Integer commentId, final Integer userId, final String commentText)
throws CouldntSaveDataException {
PostgreSQLTypeFunctions.editTypeInstanceComment(this, moduleId, commentId, userId, commentText);
}
@Override
public void editSectionComment(final int moduleId, final int sectionId, final Integer commentId,
final Integer userId, final String commentText) throws CouldntSaveDataException {
PostgreSQLSectionFunctions.editSectionComment(this, moduleId, commentId, userId, commentText);
}
@Override
public void editFunctionComment(final INaviFunction function, final Integer commentId,
final Integer userId, final String newCommentText) throws CouldntSaveDataException {
PostgreSQLFunctionFunctions.editGlobalFunctionComment(
this, function, commentId, userId, newCommentText);
}
@Override
public void editFunctionNodeComment(final INaviFunctionNode functionNode, final Integer commentId,
final Integer userId, final String newCommentText) throws CouldntSaveDataException {
PostgreSQLNodeFunctions.editLocalFunctionNodeComment(
this, functionNode, commentId, userId, newCommentText);
}
@Override
public void editGlobalCodeNodeComment(final INaviCodeNode codeNode, final Integer commentId,
final Integer userId, final String newCommentText) throws CouldntSaveDataException {
PostgreSQLNodeFunctions.editGlobalCodeNodeComment(
this, codeNode, commentId, userId, newCommentText);
}
@Override
public void editGlobalEdgeComment(final INaviEdge edge, final Integer commentId,
final Integer userId, final String newCommentText) throws CouldntSaveDataException {
PostgreSQLEdgeFunctions.editGlobalEdgeComment(this, edge, commentId, userId, newCommentText);
}
@Override
public void editGlobalInstructionComment(final INaviInstruction instruction,
final Integer commentId, final Integer userId, final String newCommentText)
throws CouldntSaveDataException {
PostgreSQLInstructionFunctions.editGlobalInstructionComment(
this, commentId, userId, newCommentText);
}
@Override
public void editGroupNodeComment(final INaviGroupNode groupNode, final Integer commentId,
final Integer userId, final String newComment) throws CouldntSaveDataException {
PostgreSQLNodeFunctions.editGroupNodeComment(this, groupNode, commentId, userId, newComment);
}
@Override
public void editLocalCodeNodeComment(final INaviCodeNode codeNode, final Integer commentId,
final Integer userId, final String newCommentText) throws CouldntSaveDataException {
PostgreSQLNodeFunctions.editLocalCodeNodeComment(
this, codeNode, commentId, userId, newCommentText);
}
@Override
public void editLocalEdgeComment(final INaviEdge edge, final Integer commentId,
final Integer userId, final String newCommentText) throws CouldntSaveDataException {
PostgreSQLEdgeFunctions.editLocalEdgeComment(this, edge, commentId, userId, newCommentText);
}
@Override
public void editLocalInstructionComment(final INaviCodeNode codeNode,
final INaviInstruction instruction, final Integer commentId, final Integer userId,
final String newCommentText) throws CouldntSaveDataException {
PostgreSQLInstructionFunctions.editLocalInstructionComment(
this, commentId, userId, newCommentText);
}
@Override
public void editTextNodeComment(final INaviTextNode textNode, final Integer commentId,
final Integer userId, final String newComment) throws CouldntSaveDataException {
PostgreSQLNodeFunctions.editTextNodeComment(this, textNode, commentId, userId, newComment);
}
@Override
public IUser editUserName(final IUser user, final String userName)
throws CouldntSaveDataException {
return CGenericSQLUserFunctions.editUserName(this, user, userName);
}
@Override
public DatabaseVersion getDatabaseVersion() throws CouldntLoadDataException {
try {
return PostgreSQLDatabaseFunctions.getDatabaseVersion(connection);
} catch (final SQLException exception) {
throw new CouldntLoadDataException(exception);
}
}
@Override
public void initializeDatabase()
throws CouldntInitializeDatabaseException, CouldntLoadDataException {
try {
createEmptyTables();
} catch (final IOException exception) {
throw new CouldntInitializeDatabaseException(exception);
}
}
@Override
public void initializeModule(final CModule module, final CModuleInitializeReporter reporter)
throws CouldntSaveDataException {
getModuleConverter().initializeModule(this, module, reporter);
}
@Override
public CTag insertTag(
final ITreeNode<CTag> parent, final String name, final String description, final TagType type)
throws CouldntSaveDataException {
return PostgreSQLTagFunctions.insertTag(this, parent, name, description, type);
}
@Override
public boolean isExporterDatabaseFormatValid() throws CouldntLoadDataException {
return !hasTable("modules") || hasColumn("modules", "version");
}
@Override
public boolean isInitialized() throws CouldntLoadDataException, InvalidDatabaseException {
return hasAllTables();
}
@Override
public ArrayList<IComment> loadCommentById(final Integer commentId)
throws CouldntLoadDataException {
return PostgreSQLCommentFunctions.loadCommentByCommentId(this, commentId);
}
@Override
public INaviFunction loadFunction(final INaviModule module, final IAddress functionAddress)
throws CouldntLoadDataException {
return PostgreSQLFunctionsLoader.loadFunction(this, module, functionAddress);
}
@Override
public List<INaviModule> loadModules() throws CouldntLoadDataException {
if (getDebuggerManager() == null) {
throw new CouldntLoadDataException("Error: Debugger manager must be loaded first");
}
setModules(
PostgreSQLDatabaseFunctions.loadModules(this, getRawModules(), getDebuggerManager()));
return new ArrayList<INaviModule>(getModules());
}
@Override
public HashMap<Integer, ArrayList<IComment>> loadMultipleCommentsById(
final Collection<Integer> commentIds) throws CouldntLoadDataException {
return PostgreSQLCommentFunctions.loadMultipleCommentsById(this, commentIds);
}
@Override
public List<INaviProject> loadProjects() throws CouldntLoadDataException {
projects = PostgreSQLDatabaseFunctions.loadProjects(this, getDebuggerManager());
return new ArrayList<INaviProject>(projects);
}
@Override
public List<INaviRawModule> loadRawModules() throws CouldntLoadDataException {
setRawModules(PostgreSQLDatabaseFunctions.loadRawModules(this));
return getRawModules();
}
@Override
public CTagManager loadTagManager(final TagType type) throws CouldntLoadDataException {
final CTagManager manager = PostgreSQLTagManagerFunctions.loadTagManager(this, type);
if (type == TagType.NODE_TAG) {
nodeTagManager = manager;
} else {
setViewTagManager(manager);
}
return manager;
}
@Override
public List<IUser> loadUsers() throws CouldntLoadDataException {
return CGenericSQLUserFunctions.loadUsers(this);
}
@Override
public void save(final TraceList traces) throws CouldntSaveDataException {
PostgreSQLTraceFunctions.save(this, traces);
}
@Override
public void save(final CView view) throws CouldntSaveDataException {
PostgreSQLViewSaver.save(this, view);
}
@Override
public void saveData(final INaviModule module, final byte[] data)
throws CouldntSaveDataException {
PostgreSQLDataFunctions.saveData(this, module, data);
}
@Override
public void updateDatabase() throws CouldntUpdateDatabaseException {
PostgreSQLDatabaseFunctions.updateDatabase(this);
}
@Override
public void deleteSection(final Section section) throws CouldntLoadDataException {
PostgreSQLSectionFunctions.deleteSection(this, section);
}
@Override
public void deleteTypeInstance(final int moduleId, final int typeInstanceId)
throws CouldntDeleteException {
PostgreSQLTypeFunctions.deleteTypeInstance(this, moduleId, typeInstanceId);
}
@Override
public void deleteTypeInstanceReference(
final int moduleId, final BigInteger address, final int position, final int expressionId)
throws CouldntDeleteException {
PostgreSQLTypeFunctions.deleteTypeInstanceReference(
this, moduleId, address, position, expressionId);
}
@Override
public void setTypeInstanceName(final int moduleId, final int id, final String name)
throws CouldntSaveDataException {
PostgreSQLTypeFunctions.setTypeInstanceName(this, moduleId, id, name);
}
@Override
public List<RawTypeInstanceReference> loadTypeInstanceReferences(final INaviModule module)
throws CouldntLoadDataException {
return PostgreSQLTypeFunctions.loadRawTypeInstanceReferences(
this.getConnection().getConnection(), module);
}
@Override
public RawTypeInstance loadTypeInstance(final INaviModule module, final Integer typeInstanceId)
throws CouldntLoadDataException {
return PostgreSQLTypeFunctions.loadRawTypeInstance(this, module, typeInstanceId);
}
@Override
public RawTypeInstanceReference loadTypeInstanceReference(final INaviModule module,
final Integer typeInstanceId, final BigInteger address, final Integer position,
final Integer expressionId) throws CouldntLoadDataException {
return PostgreSQLTypeFunctions.loadRawTypeInstanceReference(this,
module,
typeInstanceId,
address,
position,
expressionId);
}
@Override
public RawTypeMember loadTypeMember(final INaviModule module, final int typeMemberId)
throws CouldntLoadDataException {
return PostgreSQLTypeFunctions.loadRawTypeMember(this, module, typeMemberId);
}
@Override
public RawBaseType loadType(final INaviModule module, final int baseTypeId)
throws CouldntLoadDataException {
return PostgreSQLTypeFunctions.loadRawBaseType(this, module, baseTypeId);
}
@Override
public RawTypeSubstitution loadTypeSubstitution(final INaviModule module,
final BigInteger address, final int position, final int expressionId)
throws CouldntLoadDataException {
return PostgreSQLTypeFunctions.loadRawTypeSubstitution(
this, module, address, position, expressionId);
}
@Override
public void close() {
for (SQLProviderListener listener : listeners) {
listener.providerClosing(this);
}
this.connection.closeConnection();
}
@Override
public void addListener(SQLProviderListener listener) {
listeners.addListener(listener);
}
@Override
public void removeListener(SQLProviderListener listener) {
listeners.removeListener(listener);
}
}