From b7c22b2b007f9fa1b7e1bfc614ed609a9e543090 Mon Sep 17 00:00:00 2001 From: Niels Spruit Date: Mon, 12 Jan 2015 12:59:50 +0100 Subject: [PATCH] Refactoring of Alitheia-Core Changed testCreate call to testExecute in testShow to make sure succesid is initialized Updated AdminServiceImplTest Added first tests for DB Working on DB tests Finished DB transaction tests Added in-memory database tests Added tests for findObjectById* methods Added tests for findObjectsByProperties method Added tests for findObjectsByPropertiesForUpdate method Added dependency to H2 database (required for testing) Fixed testRegisterAdminAction test Added tests for find* methods when there is no active session Added some tests for adding and deleting records Added HQL test cases Added test for attachObjectToDBSession Added test for executeUpdate Introducing consistency to tests Cleaned up DBHQLQueryTest Moved DBObject Wrote tests for ConfigurationOption Added integration tests for the DB calls in Metric Introduced new interfaces for DB Created basic implementation for DBSessionManager Further refactored the transaction management Fixed DB transaction tests Fixed DB HQL tests Now, all tests are changed according to the refactoring Copied log methods from DBServiceImpl to DBSessionManagerImpl for now Updated all calls to session management functions Updated all calls to the session manager Implementing (HQL)QueryInterface Removed HQL from DBSession(Impl) API Restructured query interface tests Refactored QueryInterace usage in tests Refactored QueryInterface access Updated all query interface calls Reverted the changes to the path Implemented SQLQueryInterface Working on refactoring the exception handling of the DB services Finished extraction of DB log functions Fixed small bugs with log functions Added and deleted some comments Created QueryInterfaceFactory to facilitate runtime plugging of new interfaces Cleaned up factory registration Added more documentation Added tests for query interface retrieval/registration --- alitheia/core/pom.xml | 88 +++ .../java/eu/sqooss/core/AlitheiaCore.java | 4 + .../impl/service/admin/AdminServiceImpl.java | 10 +- .../cluster/ClusterNodeServiceImpl.java | 45 +- .../sqooss/impl/service/db/DBServiceImpl.java | 622 +++--------------- .../impl/service/db/DBSessionManagerImpl.java | 226 +++++++ .../service/db/HQLQueryInterfaceImpl.java | 273 ++++++++ .../service/db/SQLQueryInterfaceImpl.java | 181 +++++ .../impl/service/fds/FDSServiceImpl.java | 2 +- .../impl/service/fds/OnDiskCheckoutImpl.java | 2 +- .../sqooss/impl/service/fds/TimelineImpl.java | 7 +- .../metricactivator/MetricActivatorImpl.java | 8 +- .../metricactivator/MetricActivatorJob.java | 10 +- .../sqooss/impl/service/pa/PAServiceImpl.java | 8 +- .../impl/service/rest/ResteasyServlet.java | 8 +- .../impl/service/tds/TDSServiceImpl.java | 4 +- .../impl/service/updater/OhlohUpdater.java | 6 +- .../service/updater/UpdaterServiceImpl.java | 6 +- .../impl/service/webadmin/AdminServlet.java | 16 +- .../service/webadmin/ProjectDeleteJob.java | 17 +- .../impl/service/webadmin/ProjectsView.java | 2 +- .../eu/sqooss/rest/api/MetricsResource.java | 5 +- .../rest/api/StoredProjectResource.java | 3 +- .../abstractmetric/AbstractMetric.java | 23 +- .../service/admin/actions/AddProject.java | 7 +- .../java/eu/sqooss/service/db/Branch.java | 10 +- .../main/java/eu/sqooss/service/db/Bug.java | 6 +- .../eu/sqooss/service/db/BugPriority.java | 6 +- .../eu/sqooss/service/db/BugResolution.java | 6 +- .../eu/sqooss/service/db/BugSeverity.java | 6 +- .../java/eu/sqooss/service/db/BugStatus.java | 6 +- .../eu/sqooss/service/db/ClusterNode.java | 4 +- .../service/db/ConfigurationOption.java | 16 +- .../java/eu/sqooss/service/db/DAObject.java | 4 +- .../java/eu/sqooss/service/db/DBService.java | 445 ++----------- .../sqooss/service/db/DBSessionManager.java | 84 +++ .../service/db/DBSessionValidation.java | 32 + .../java/eu/sqooss/service/db/Developer.java | 20 +- .../java/eu/sqooss/service/db/Directory.java | 6 +- .../sqooss/service/db/HQLQueryInterface.java | 165 +++++ .../eu/sqooss/service/db/MailMessage.java | 10 +- .../eu/sqooss/service/db/MailingList.java | 6 +- .../sqooss/service/db/MailingListThread.java | 10 +- .../java/eu/sqooss/service/db/Metric.java | 8 +- .../java/eu/sqooss/service/db/MetricType.java | 4 +- .../java/eu/sqooss/service/db/NameSpace.java | 2 +- .../eu/sqooss/service/db/OhlohDeveloper.java | 8 +- .../java/eu/sqooss/service/db/Plugin.java | 8 +- .../service/db/PluginConfiguration.java | 8 +- .../eu/sqooss/service/db/ProjectFile.java | 16 +- .../sqooss/service/db/ProjectFileState.java | 9 +- .../eu/sqooss/service/db/ProjectVersion.java | 28 +- .../eu/sqooss/service/db/QueryInterface.java | 118 ++++ .../service/db/QueryInterfaceFactory.java | 18 + .../sqooss/service/db/SQLQueryInterface.java | 73 ++ .../eu/sqooss/service/db/StoredProject.java | 18 +- .../service/db/StoredProjectConfig.java | 4 +- .../main/java/eu/sqooss/service/db/Tag.java | 4 +- .../java/eu/sqooss/service/pa/PluginInfo.java | 10 +- .../java/eu/sqooss/service/scheduler/Job.java | 20 +- .../admin/test/AdminServiceImplTest.java | 55 +- .../eu/sqooss/test/service/db/DBObject.java | 63 ++ .../test/service/db/DBServiceImplTest.java | 89 +++ .../test/service/db/DBTransactionTest.java | 392 +++++++++++ .../service/db/HQLQueryInterfaceImplTest.java | 12 + .../service/db/HQLQueryInterfaceTest.java | 267 ++++++++ .../test/service/db/InMemoryDatabase.java | 125 ++++ .../test/service/db/QueryInterfaceTest.java | 362 ++++++++++ .../db/objects/ConfigurationOptionTest.java | 240 +++++++ .../test/service/db/objects/MetricTest.java | 196 ++++++ .../contrib/ContributionMetricImpl.java | 21 +- .../metrics/contrib/db/ContribAction.java | 15 +- .../metrics/contrib/db/ContribActionType.java | 7 +- .../developermetrics/Developermetrics.java | 13 +- .../discussionheat/DiscussionHeat.java | 13 +- .../metrics/findbugs/FindbugsMetrics.java | 6 +- .../eu/sqooss/metrics/java/JavaMetrics.java | 22 +- .../main/java/eu/sqooss/metrics/mi/Mi.java | 9 +- .../ModuleMetricsImplementation.java | 11 +- .../sqooss/metrics/structural/Structural.java | 4 +- .../TestabilityImplementation.java | 2 +- .../sqooss/metrics/wc/WcImplementation.java | 17 +- .../plugins/bugzilla/BugzillaUpdater.java | 8 +- .../plugins/bugzilla/BugzillaXMLJob.java | 12 +- .../plugins/devmatcher/DeveloperMatcher.java | 13 +- .../plugins/updater/git/GitUpdater.java | 20 +- .../plugins/git/test/TestGitUpdater.java | 16 +- .../plugins/javaparser/JavaUpdater.java | 7 +- .../plugins/javaparser/JavaUpdaterJob.java | 14 +- .../plugins/maildir/MailDirUpdater.java | 8 +- .../plugins/maildir/MailMessageJob.java | 8 +- .../MailThreadResolver.java | 31 +- .../moduleresolver/ModuleResolver.java | 11 +- .../plugins/updater/svn/SVNUpdaterImpl.java | 34 +- pom.xml | 2 + 95 files changed, 3584 insertions(+), 1322 deletions(-) create mode 100644 alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBSessionManagerImpl.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/impl/service/db/HQLQueryInterfaceImpl.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/impl/service/db/SQLQueryInterfaceImpl.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionManager.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionValidation.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/service/db/HQLQueryInterface.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterface.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterfaceFactory.java create mode 100644 alitheia/core/src/main/java/eu/sqooss/service/db/SQLQueryInterface.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/DBObject.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/DBServiceImplTest.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/DBTransactionTest.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceImplTest.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceTest.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/InMemoryDatabase.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/QueryInterfaceTest.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/ConfigurationOptionTest.java create mode 100644 alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/MetricTest.java diff --git a/alitheia/core/pom.xml b/alitheia/core/pom.xml index 4203d2dda..74600386a 100644 --- a/alitheia/core/pom.xml +++ b/alitheia/core/pom.xml @@ -63,7 +63,83 @@ + + org.jacoco + jacoco-maven-plugin + 0.7.2.201409121644 + + + + pre-unit-test + + prepare-agent + + + + ${project.build.directory}/coverage-reports/jacoco-ut.exec + + surefireArgLine + + + + + post-unit-test + test + + report + + + + ${project.build.directory}/coverage-reports/jacoco-ut.exec + + ${project.reporting.outputDirectory}/jacoco-ut + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.jacoco + + jacoco-maven-plugin + + + [0.7.2.201409121644,) + + + prepare-agent + + + + + + + + + + + + @@ -176,6 +252,18 @@ 1.9.5 test + + com.h2database + h2 + 1.4.184 + test + + + org.hamcrest + hamcrest-all + 1.3 + test + diff --git a/alitheia/core/src/main/java/eu/sqooss/core/AlitheiaCore.java b/alitheia/core/src/main/java/eu/sqooss/core/AlitheiaCore.java index 63610d55f..d55d062a7 100644 --- a/alitheia/core/src/main/java/eu/sqooss/core/AlitheiaCore.java +++ b/alitheia/core/src/main/java/eu/sqooss/core/AlitheiaCore.java @@ -162,6 +162,10 @@ public static AlitheiaCore testInstance() { return instance; } + public static void setTestInstance(AlitheiaCore testInstance) { + instance = testInstance; + } + /** * Register an external implementation of an AlitheiaCore service. It * will override any internally defined implementation. diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/admin/AdminServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/admin/AdminServiceImpl.java index bcd0f6556..88de58f37 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/admin/AdminServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/admin/AdminServiceImpl.java @@ -100,9 +100,9 @@ public void execute(AdminAction a) { DBService db = null; if (AlitheiaCore.getInstance() != null) { db = AlitheiaCore.getInstance().getDBService(); - if (db.isDBSessionActive() != true) { + if (db.getSessionManager().isDBSessionActive() != true) { commitDB = true; - db.startDBSession(); + db.getSessionManager().startDBSession(); } } @@ -111,14 +111,14 @@ public void execute(AdminAction a) { a.execute(); } catch (Exception e) { if ((db != null) && commitDB) - db.rollbackDBSession(); + db.getSessionManager().rollbackDBSession(); err("Error executing action " + a.mnemonic() + ", id " + a.id() + "\nCause:" + e.getMessage(), e); } finally { ActionContainer ac = liveactions.get(a.id()); if (db != null) - if (db.isDBSessionActive() && commitDB) - db.commitDBSession(); + if (db.getSessionManager().isDBSessionActive() && commitDB) + db.getSessionManager().commitDBSession(); ac.end = System.currentTimeMillis(); debug("Action " + a.id() + " finished in " + (ac.end - ac.start) + " msec" ); } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/cluster/ClusterNodeServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/cluster/ClusterNodeServiceImpl.java index 5f8f77478..ba590cc59 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/cluster/ClusterNodeServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/cluster/ClusterNodeServiceImpl.java @@ -55,6 +55,7 @@ import eu.sqooss.service.cluster.ClusterNodeService; import eu.sqooss.service.db.ClusterNode; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.StoredProject; import eu.sqooss.service.logging.Logger; import eu.sqooss.service.updater.UpdaterService; @@ -160,9 +161,9 @@ public boolean assignProject(StoredProject project) throws ClusterNodeActionExce * @param projectname project's name to assign */ public boolean assignProject(String projectname) throws ClusterNodeActionException { - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); StoredProject project = StoredProject.getProjectByName(projectname); - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); if (project == null) { //the project was not found, can't be assign String errorMessage = "The project [" + projectname + "] was not found"; @@ -275,9 +276,9 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) // If empty, assign it to this clusternode // Example: http://localhost:8088/clusternode?action=assign_project&projectname=iTALC&clusternode=sqoserver1 - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); project = StoredProject.getProjectByName(projectname); - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); if (project==null) { if (projectid!=null) { long id = 0; @@ -288,9 +289,9 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) sendXMLResponse(response, HttpServletResponse.SC_BAD_REQUEST, content); break; } - dbs.startDBSession(); - project = dbs.findObjectById(StoredProject.class, id); - dbs.rollbackDBSession(); + dbs.getSessionManager().startDBSession(); + project = dbs.getQueryInterface().findObjectById(StoredProject.class, id); + dbs.getSessionManager().rollbackDBSession(); if (project==null) { content = createXMLResponse(null,"Project with id:" + projectid + " not found", HttpServletResponse.SC_NOT_FOUND); sendXMLResponse(response, HttpServletResponse.SC_NOT_FOUND, content); @@ -306,9 +307,9 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) if (clusternode==null) { node = thisNode; } else { - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); node = ClusterNode.getClusteNodeByName(clusternode); - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); if (node==null) { content = createXMLResponse(null,"ClusterNode " + clusternode + " not found", HttpServletResponse.SC_NOT_FOUND); sendXMLResponse(response, HttpServletResponse.SC_NOT_FOUND, content); @@ -335,9 +336,9 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) if (clusternode==null) { node = thisNode; } else { - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); node = ClusterNode.getClusteNodeByName(clusternode); - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); } if (node==null){ content = createXMLResponse(null, "ClusterNode "+clusternode+" not found", HttpServletResponse.SC_NOT_FOUND); @@ -346,7 +347,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) } bcontent = new StringBuilder(); - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); Set assignments = ClusterNode.thisNode().getProjects(); if ((assignments!=null) && (assignments.size()>0) ){ bcontent.append("\n"); @@ -357,7 +358,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) bcontent.append(">" + sp.getName() + "\n"); } } - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); content = createXMLResponse(bcontent.toString(), "Project list processed succesfuly", HttpServletResponse.SC_OK); sendXMLResponse(response, HttpServletResponse.SC_OK, content); break; @@ -365,15 +366,15 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) // valid parameters: No need for parameters! // Example: http://localhost:8088/clusternode?action=get_known_servers bcontent = new StringBuilder(); - dbs.startDBSession(); - List nodes = (List) dbs.doHQL("FROM ClusterNode",null); + dbs.getSessionManager().startDBSession(); + List nodes = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL("FROM ClusterNode",null); if ((nodes!=null) && (nodes.size()>0) ){ bcontent.append("\n"); for (ClusterNode cn : nodes) { bcontent.append("" + cn.getName() + "\n"); } } - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); content = createXMLResponse(bcontent.toString(), "Clusternode list processed succesfuly", HttpServletResponse.SC_OK); sendXMLResponse(response, HttpServletResponse.SC_OK, content); break; @@ -429,31 +430,31 @@ public boolean startUp() { // At this point, this ClusterNode has not been registered to the // database yet, so do it! if (thisNode == null) { // paranoia check - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); // Check if previously registered in DB Map serverProps = new HashMap(1); serverProps.put("name", localServerName); - List s = dbs.findObjectsByProperties( + List s = dbs.getQueryInterface().findObjectsByProperties( ClusterNode.class, serverProps); if (s.isEmpty()) { // not registered yet, create a record in DB thisNode = new ClusterNode(); thisNode.setName(localServerName); - if (!dbs.addRecord(thisNode)) { + if (!dbs.getQueryInterface().addRecord(thisNode)) { logger.error("Failed to register ClusterNode <" + localServerName + ">"); - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); return false; } else { - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); logger.info("ClusterNode <" + localServerName + "> registered succesfully."); return true; } } else { // already registered, keep the record from DB - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); thisNode = s.get(0); logger.info("ClusterNode <" + localServerName + "> registered succesfully."); diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBServiceImpl.java index 546b4addd..65e122994 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBServiceImpl.java @@ -36,35 +36,32 @@ import java.io.File; import java.io.FilenameFilter; -import java.net.URL; import java.net.URI; +import java.net.URL; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.QueryException; -import org.hibernate.JDBCException; -import org.hibernate.Query; -import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; -import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Configuration; import org.osgi.framework.BundleContext; import eu.sqooss.core.AlitheiaCoreService; -import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.DBSessionManager; +import eu.sqooss.service.db.DBSessionValidation; +import eu.sqooss.service.db.HQLQueryInterface; +import eu.sqooss.service.db.QueryInterface; +import eu.sqooss.service.db.QueryInterfaceFactory; +import eu.sqooss.service.db.SQLQueryInterface; import eu.sqooss.service.logging.Logger; import eu.sqooss.service.util.URIUtills; @@ -125,52 +122,12 @@ public class DBServiceImpl implements DBService, AlitheiaCoreService { private BundleContext bc = null; private AtomicBoolean isInitialised = new AtomicBoolean(false); private Properties conProp = new Properties(); + private DBSessionManager sessionManager = null; + private DBSessionValidation sessionValidation = null; - private void logSQLException(SQLException e) { - - while (e != null) { - String message = String.format("SQLException: SQL State:%s, Error Code:%d, Message:%s", - e.getSQLState(), e.getErrorCode(), e.getMessage()); - logger.warn(message); - e = e.getNextException(); - } - } - - private void logExceptionAndTerminateSession( Exception e ) { - if ( e instanceof JDBCException ) { - JDBCException jdbce = (JDBCException) e; - logSQLException(jdbce.getSQLException()); - } - logger.warn("Exception caught during database session: " + e.getMessage() - + ". Rolling back current transaction and terminating session..."); - e.printStackTrace(); - Session s = null; - try { - s = sessionFactory.getCurrentSession(); - s.getTransaction().rollback(); - } catch (HibernateException e1) { - logger.error("Error while rolling back failed transaction :" + e1.getMessage()); - if ( s != null ) { - try { - s.close(); - } catch ( HibernateException e2) {} - } - } - - } - - private boolean checkSession() { - if ( !isDBSessionActive() ) { - logger.warn("Trying to call a DBService method without an active session"); - try { - throw new Exception("No active session."); - } catch (Exception e) { - e.printStackTrace(); - } - return false; - } - return true; - } + private Map, Class>> + queryInterfaceFactories = new HashMap<>(); + private Map, QueryInterface> queryInterfaces = new HashMap<>(); private boolean getJDBCConnection() { String driver = conProp.getProperty("hibernate.connection.driver_class"); @@ -190,7 +147,7 @@ private boolean getJDBCConnection() { return false; } catch (SQLException e) { logger.error("Failed to register driver " + driver); - logSQLException(e); + sessionValidation.logSQLException(e); return false; } @@ -205,7 +162,7 @@ private boolean getJDBCConnection() { } catch (SQLException e) { logger.error("Unable to connect to DB URL " + conProp.getProperty("hibernate.connection.url")); - logSQLException(e); + sessionValidation.logSQLException(e); return false; } } @@ -273,6 +230,10 @@ public boolean accept(File dir, String name) { } sessionFactory = c.buildSessionFactory(); + DBSessionManagerImpl ssm = new DBSessionManagerImpl(sessionFactory, logger, isInitialised); + sessionManager = ssm; + sessionValidation = ssm; + if (sessionFactory == null) return false; } catch (Throwable e) { @@ -283,12 +244,19 @@ public boolean accept(File dir, String name) { return true; } + private void preloadFactories() { + registerQueryInterface(QueryInterface.class, HQLQueryInterfaceImpl.Factory.class); + registerQueryInterface(HQLQueryInterface.class, HQLQueryInterfaceImpl.Factory.class); + registerQueryInterface(SQLQueryInterface.class, SQLQueryInterfaceImpl.Factory.class); + } + public DBServiceImpl() { } public DBServiceImpl(Properties p, URL configFileURL, Logger l) { this.conProp = p; this.logger = l; initHibernate(configFileURL); + preloadFactories(); isInitialised.compareAndSet(false, true); instance = this; } @@ -298,480 +266,10 @@ public static DBService getInstance() { instance = new DBServiceImpl(); return instance; } - - public T findObjectById(Class daoClass, long id) { - return doFindObjectById(daoClass, id, false); - } - - public T findObjectByIdForUpdate(Class daoClass, long id) { - return doFindObjectById(daoClass, id, true); - } - - @SuppressWarnings("unchecked") - private T doFindObjectById(Class daoClass, long id, boolean useLock) { - if ( !checkSession() ) - return null; - - try { - Session s = sessionFactory.getCurrentSession(); - return (T) (useLock ? s.get(daoClass, id, LockMode.UPGRADE) : s.get(daoClass, id)); - } catch (HibernateException e) { - logExceptionAndTerminateSession(e); - return null; - } - } - - public List findObjectsByProperties(Class daoClass, Map properties) { - return doFindObjectsByProperties(daoClass, properties, false); - } - - public List findObjectsByPropertiesForUpdate(Class daoClass, Map properties) { - return doFindObjectsByProperties(daoClass, properties, true); - } - - @SuppressWarnings("unchecked") - private List doFindObjectsByProperties(Class daoClass, Map properties, boolean useLock) { - if( !checkSession() ) - return Collections.emptyList(); - - // TODO maybe check that the properties are valid (e.g. with java.bean.PropertyDescriptor) - - Map parameterMap = new HashMap(); - StringBuffer whereClause = new StringBuffer(); - for (String key : properties.keySet()) { - whereClause.append( whereClause.length() == 0 ? " where " : " and " ); - // We use "foo" as the name of the object - whereClause.append("foo" + "." + key + "=:_" + key ); - parameterMap.put( "_" + key, properties.get(key) ); - } - try { - // We use "foo" as the name of the object - return (List) doHQL( "from " + daoClass.getName() + " as foo " + whereClause, parameterMap, useLock ); - } catch (QueryException e) { - logger.warn("findObjectsByProperties(): invalid properties map. Restarting session..."); - // Automatically restart a session - // (just be careful with preloaded DAOs that become detached) - startDBSession(); - return Collections.emptyList(); - } - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doSQL(java.lang.String) - */ - public List doSQL(String sql) - throws SQLException { - return doSQL(sql, null); - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doSQL(java.lang.String, java.util.Map) - */ - public List doSQL(String sql, Map params) - throws SQLException, QueryException { - boolean autoSession = !isDBSessionActive(); - try { - Session s = sessionFactory.getCurrentSession(); - if (autoSession) { - s.beginTransaction(); - } - Query query = s.createSQLQuery(sql); - if ( params != null ) { - for ( String param : params.keySet() ) { - query.setParameter(param, params.get(param)); - } - } - List result = query.list(); - if (autoSession) { - s.getTransaction().commit(); - } - return result; - } catch ( JDBCException e ) { - logExceptionAndTerminateSession(e); - throw e.getSQLException(); - } catch ( QueryException e ) { - logExceptionAndTerminateSession(e); - throw e; - } catch( HibernateException e ) { - logExceptionAndTerminateSession(e); - return Collections.emptyList(); - } - } - - public int callProcedure(String procName, List args, Map params) - throws SQLException, QueryException { - boolean autoSession = !isDBSessionActive(); - StringBuilder sql = new StringBuilder("call " + procName + "("); - - for (String arg : args) { - sql.append(":").append(arg).append(","); - } - sql.deleteCharAt(sql.lastIndexOf(",")).append(")"); - - try { - Session s = sessionFactory.getCurrentSession(); - if (autoSession) { - s.beginTransaction(); - } - Query query = s.createSQLQuery(sql.toString()); - if (params != null) { - for (String param : params.keySet()) { - query.setParameter(param, params.get(param)); - } - } - int result = query.executeUpdate(); - if (autoSession) { - s.getTransaction().commit(); - } - return result; - } catch (JDBCException e) { - logExceptionAndTerminateSession(e); - throw e.getSQLException(); - } catch (QueryException e) { - logExceptionAndTerminateSession(e); - throw e; - } catch (HibernateException e) { - logExceptionAndTerminateSession(e); - throw e; - } - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doHQL(java.lang.String) - */ - public List doHQL(String hql) - throws QueryException { - return doHQL(hql, null, null, false, -1, -1); - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doHQL(java.lang.String, java.util.Map) - */ - public List doHQL(String hql, Map params) - throws QueryException { - return doHQL(hql, params, null, false, -1, -1); - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doHQL(java.lang.String, java.util.Map, int) - */ - public List doHQL(String hql, Map params, int limit) - throws QueryException { - return doHQL(hql, params, null, false, 0, limit); - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doHQL(java.lang.String, java.util.Map, boolean) - */ - public List doHQL(String hql, Map params, boolean lockForUpdate) - throws QueryException { - return doHQL(hql, params, null, lockForUpdate, -1, -1); - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doHQL(java.lang.String, java.util.Map, java.util.Map) - */ - public List doHQL(String hql, Map params, - Map collectionParams) - throws QueryException { - return doHQL(hql, params, collectionParams, false, -1, -1); - } - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#doHQL(java.lang.String, java.util.Map, java.util.Map, boolean, int, int) - */ - public List doHQL(String hql, Map params, - Map collectionParams, boolean lockForUpdate, int start, int limit) - throws QueryException { - if ( !checkSession() ) { - return Collections.emptyList(); - } - try { - Session s = sessionFactory.getCurrentSession(); - Query query = s.createQuery(hql); - if (params != null) { - for ( String param : params.keySet() ) { - query.setParameter(param, params.get(param)); - } - } - if (collectionParams != null) { - for ( String param : collectionParams.keySet() ) { - query.setParameterList(param, collectionParams.get(param)); - } - } - if (lockForUpdate) { - query.setLockMode("foo", LockMode.PESSIMISTIC_WRITE); - } - if ( start >= 0 && limit >= 0 ) { - query.setFirstResult(start); - query.setMaxResults(limit); - } - return query.list(); - } catch ( QueryException e ) { - logExceptionAndTerminateSession(e); - throw e; - } catch( HibernateException e ) { - logExceptionAndTerminateSession(e); - return Collections.emptyList(); - } catch (ClassCastException e) { - // Throw a QueryException instead of forwarding the ClassCastException - // it's more explicit - QueryException ebis = new QueryException("Invalid HQL query parameter type: " - + e.getMessage(), e); - logExceptionAndTerminateSession(ebis); - throw ebis; - } - - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#addRecord(eu.sqooss.service.db.DAObject) - */ - public boolean addRecord(DAObject record) { - ArrayList tmpList = new ArrayList(1); - tmpList.add(record); - return addRecords(tmpList); - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#deleteRecord(eu.sqooss.service.db.DAObject) - */ - public boolean deleteRecord(DAObject record) { - ArrayList tmpList = new ArrayList(1); - tmpList.add(record); - return deleteRecords(tmpList); - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#addRecords(java.util.List) - */ - public boolean addRecords(List records) { - if( !checkSession() ) - return false; - - DAObject lastRecord = null; - try { - Session s = sessionFactory.getCurrentSession(); - for (DAObject record : records) { - lastRecord = record; - s.save(record); - } - lastRecord = null; - s.flush(); - return true; - } catch (HibernateException e) { - if (lastRecord != null) { - logger.error("Failed to add object " - + "[" + lastRecord.getClass().getName() + ":" + lastRecord.getId() + "]" - + " to the database: " + e.getMessage()); - } - logExceptionAndTerminateSession(e); - return false; - } - } - - /* (non-Javadoc) - * @see eu.sqooss.service.db.DBService#deleteRecords(java.util.List) - */ - public boolean deleteRecords(List records) { - if( !checkSession() ) - return false; - - DAObject lastRecord = null; - try { - Session s = sessionFactory.getCurrentSession(); - for (DAObject record : records) { - lastRecord = record; - s.delete(record); - } - lastRecord = null; - s.flush(); - return true; - } catch (HibernateException e) { - if (lastRecord != null) { - logger.error("Failed to remove object " - + "[" + lastRecord.getClass().getName() + ":" + lastRecord.getId() + "]" - + " from the database: " + e.getMessage()); - } - logExceptionAndTerminateSession(e); - return false; - } - } public Logger logger() { return this.logger; - } - - public boolean startDBSession() { - //Boot time check - if(isInitialised.get() == false) { - return false; - } - - if( isDBSessionActive() ) { - logger.debug("startDBSession() - a session was already started for that thread"); - return true; - } - - Session s = null; - try { - s = sessionFactory.getCurrentSession(); - //logger.debug("startDBSession: " + s + "[hashcode=" + s.hashCode() + ",open=" + s.isOpen() + "]"); - s.beginTransaction(); - } catch (HibernateException e) { - logger.error("startDBSession() - error while initializing session: " + e.getMessage()); - if ( s != null ) { - try { - s.close(); - } catch (HibernateException e1) { - } - } - return false; - } - return true; - } - - public boolean commitDBSession() { - if ( !checkSession() ) - return false; - - Session s = null; - try { - s = sessionFactory.getCurrentSession(); - //logger.debug("commitDBSession: " + s + "[hashcode=" + s.hashCode() + ",open=" + s.isOpen() + "]"); - s.getTransaction().commit(); - } catch (HibernateException e) { - logger.error("commitDBSession() - error while committing transaction: " + e.getMessage()); - if ( s != null ) { - // The docs say to do so - try { - s.getTransaction().rollback(); - } catch (HibernateException e1) { - try { - s.close(); - } catch (HibernateException e2) { - } - } - } - return false; - } - return true; - } - - public boolean rollbackDBSession() { - if ( !checkSession() ) - return false; - - Session s = null; - try { - s = sessionFactory.getCurrentSession(); - s.getTransaction().rollback(); - } catch (HibernateException e) { - logger.error("commitDBSession() - error while rolling back transaction: " + e.getMessage()); - if ( s != null ) { - try { - s.close(); - } catch (HibernateException e1) { - } - } - return false; - } - return true; - } - - public boolean flushDBSession() { - if ( !checkSession() ) - return false; - - Session s = null; - try { - s = sessionFactory.getCurrentSession(); - s.flush(); - s.clear(); - } catch (HibernateException e) { - logger.error("flushDBSession() - error while flushing session: " + e.getMessage()); - if ( s != null ) { - try { - s.close(); - } catch (HibernateException e1) { - } - } - return false; - } - return true; - } - - public boolean isDBSessionActive() { - //Boot time check - if(isInitialised.get() == false) { - return false; - } - - Session s = null; - try { - s = sessionFactory.getCurrentSession(); - return s.getTransaction() != null && s.getTransaction().isActive(); - } catch (HibernateException e) { - logger.error("isDBSessionActive() - error while checking session status: " + e.getMessage()); - if ( s != null ) { - try { - s.close(); - } catch (HibernateException e1) { - } - } - return false; - } - } - - @SuppressWarnings("unchecked") - public T attachObjectToDBSession(T obj) { - if( !checkSession() ) - return null; - - try { - Session s = sessionFactory.getCurrentSession(); - if ( s.contains(obj)) { - return obj; - } else { - return (T) s.merge(obj); - } - } catch (HibernateException e) { - logExceptionAndTerminateSession(e); - return null; - } - } - - public int executeUpdate(String hql, Map params) - throws QueryException { - if (!checkSession()) { - return -1; - } - - try { - Session s = sessionFactory.getCurrentSession(); - Query query = s.createQuery(hql); - if (params != null) { - for (String param : params.keySet()) { - query.setParameter(param, params.get(param)); - } - } - - return query.executeUpdate(); - - } catch (QueryException e) { - logExceptionAndTerminateSession(e); - throw e; - } catch (HibernateException e) { - logExceptionAndTerminateSession(e); - return -1; - } catch (ClassCastException e) { - // Throw a QueryException instead of forwarding the ClassCastException - // it's more explicit - QueryException ebis = new QueryException( - "Invalid HQL query parameter type: " + e.getMessage(), e); - logExceptionAndTerminateSession(ebis); - throw ebis; - } - } + } @Override public boolean startUp() { @@ -810,6 +308,72 @@ public void setInitParams(BundleContext bc, Logger l) { this.bc = bc; this.logger = l; } + + @Override + public DBSessionManager getSessionManager() { + return sessionManager; + } + + @Override + public QueryInterface getQueryInterface() { + return getQueryInterface(QueryInterface.class); + } + + @SuppressWarnings("unchecked") + @Override + public T getQueryInterface(Class queryInterfaceType) { + if (!queryInterfaces.containsKey(queryInterfaceType)) { + if (!queryInterfaceFactories.containsKey(queryInterfaceType)) { + logger.error("Requesting QueryInterface of unknown type: " + queryInterfaceType.getName()); + return null; + } + + try { + // Lazy initialization of QueryInterfaces by using a factory pattern + QueryInterfaceFactory factory = (QueryInterfaceFactory) + queryInterfaceFactories.get(queryInterfaceType).newInstance(); + T qi = factory.build(this, sessionFactory, sessionValidation); + + queryInterfaces.put(queryInterfaceType, qi); + } catch (InstantiationException | IllegalAccessException e) { + logger.error("Failed to instantiate QueryInterface: ", e); + e.printStackTrace(); + return null; + } + } + + return (T) queryInterfaces.get(queryInterfaceType); + } + + @Override + public void registerQueryInterface(Class queryInterfaceType, + Class> factoryType) { + // Override any existing interface + if (queryInterfaces.containsKey(queryInterfaceType)) + queryInterfaces.remove(queryInterfaceType); + + queryInterfaceFactories.put(queryInterfaceType, factoryType); + } + + /** + * Prepare the DB service for testing by injecting a custom SessionFactory. + * Note: this should NOT be used in production code. + * + * @param s a custom SessionFactory object + * @param setInitialised true if the DBServiceImpl should be considered initialised + * @param l the logger to use for the DB service + */ + public void prepareForTest(SessionFactory s, boolean setInitialised, Logger l) { + this.sessionFactory = s; + this.logger = l; + + DBSessionManagerImpl ssm = new DBSessionManagerImpl(sessionFactory, logger, isInitialised); + this.sessionManager = ssm; + this.sessionValidation = ssm; + preloadFactories(); + + isInitialised.set(setInitialised); + } } //vi: ai nosi sw=4 ts=4 expandtab diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBSessionManagerImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBSessionManagerImpl.java new file mode 100644 index 000000000..02320db46 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/DBSessionManagerImpl.java @@ -0,0 +1,226 @@ +package eu.sqooss.impl.service.db; + +import java.sql.SQLException; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.hibernate.HibernateException; +import org.hibernate.JDBCException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import eu.sqooss.service.db.DAObject; +import eu.sqooss.service.db.DBSessionManager; +import eu.sqooss.service.db.DBSessionValidation; +import eu.sqooss.service.logging.Logger; + +/** + * Default implementation of the DBSessionManager and DBSessionValidation interfaces + * based on the Hibernate framework. + */ +public class DBSessionManagerImpl implements DBSessionManager, DBSessionValidation { + + private AtomicBoolean isInitialised = null; + private Logger logger = null; + private SessionFactory sessionFactory = null; + + public DBSessionManagerImpl(SessionFactory factory, Logger logger, AtomicBoolean isInit) { + this.sessionFactory = factory; + this.logger = logger; + this.isInitialised = isInit; + } + + @Override + public boolean startDBSession() { + // Boot time check + if (isInitialised.get() == false) { + return false; + } + + if (isDBSessionActive()) { + logger.debug("startDBSession() - a session was already started for that thread"); + return true; + } + + Session s = null; + try { + s = sessionFactory.getCurrentSession(); + // logger.debug("startDBSession: " + s + "[hashcode=" + s.hashCode() + // + ",open=" + s.isOpen() + "]"); + s.beginTransaction(); + } catch (HibernateException e) { + logger.error("startDBSession() - error while initializing session: " + + e.getMessage()); + if (s != null) { + try { + s.close(); + } catch (HibernateException e1) { + } + } + return false; + } + return true; + } + + @Override + public boolean commitDBSession() { + if ( !checkSession() ) + return false; + + Session s = null; + try { + s = sessionFactory.getCurrentSession(); + //logger.debug("commitDBSession: " + s + "[hashcode=" + s.hashCode() + ",open=" + s.isOpen() + "]"); + s.getTransaction().commit(); + } catch (HibernateException e) { + logger.error("commitDBSession() - error while committing transaction: " + e.getMessage()); + if ( s != null ) { + // The docs say to do so + try { + s.getTransaction().rollback(); + } catch (HibernateException e1) { + try { + s.close(); + } catch (HibernateException e2) { + } + } + } + return false; + } + return true; + } + + @Override + public boolean rollbackDBSession() { + if ( !checkSession() ) + return false; + + Session s = null; + try { + s = sessionFactory.getCurrentSession(); + s.getTransaction().rollback(); + } catch (HibernateException e) { + logger.error("commitDBSession() - error while rolling back transaction: " + e.getMessage()); + if ( s != null ) { + try { + s.close(); + } catch (HibernateException e1) { + } + } + return false; + } + return true; + } + + @Override + public boolean flushDBSession() { + if ( !checkSession() ) + return false; + + Session s = null; + try { + s = sessionFactory.getCurrentSession(); + s.flush(); + s.clear(); + } catch (HibernateException e) { + logger.error("flushDBSession() - error while flushing session: " + e.getMessage()); + if ( s != null ) { + try { + s.close(); + } catch (HibernateException e1) { + } + } + return false; + } + return true; + } + + @Override + public boolean isDBSessionActive() { + //Boot time check + if(isInitialised.get() == false) { + return false; + } + + Session s = null; + try { + s = sessionFactory.getCurrentSession(); + return s.getTransaction() != null && s.getTransaction().isActive(); + } catch (HibernateException e) { + logger.error("isDBSessionActive() - error while checking session status: " + e.getMessage()); + if ( s != null ) { + try { + s.close(); + } catch (HibernateException e1) { + } + } + return false; + } + } + + @Override + public T attachObjectToDBSession(T obj) { + if( !checkSession() ) + return null; + + try { + Session s = sessionFactory.getCurrentSession(); + if ( s.contains(obj)) { + return obj; + } else { + return (T) s.merge(obj); + } + } catch (HibernateException e) { + logExceptionAndTerminateSession(e); + return null; + } + } + + @Override + public boolean checkSession() { + if ( !isDBSessionActive() ) { + logger.warn("Trying to call a DBService method without an active session"); + try { + throw new Exception("No active session."); + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + return true; + } + + @Override + public void logExceptionAndTerminateSession( Exception e ) { + if ( e instanceof JDBCException ) { + JDBCException jdbce = (JDBCException) e; + logSQLException(jdbce.getSQLException()); + } + logger.warn("Exception caught during database session: " + e.getMessage() + + ". Rolling back current transaction and terminating session..."); + e.printStackTrace(); + Session s = null; + try { + s = sessionFactory.getCurrentSession(); + s.getTransaction().rollback(); + } catch (HibernateException e1) { + logger.error("Error while rolling back failed transaction :" + e1.getMessage()); + if ( s != null ) { + try { + s.close(); + } catch ( HibernateException e2) {} + } + } + + } + + @Override + public void logSQLException(SQLException e) { + + while (e != null) { + String message = String.format("SQLException: SQL State:%s, Error Code:%d, Message:%s", + e.getSQLState(), e.getErrorCode(), e.getMessage()); + logger.warn(message); + e = e.getNextException(); + } + } +} diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/db/HQLQueryInterfaceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/HQLQueryInterfaceImpl.java new file mode 100644 index 000000000..db997d9f2 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/HQLQueryInterfaceImpl.java @@ -0,0 +1,273 @@ +package eu.sqooss.impl.service.db; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.LockMode; +import org.hibernate.Query; +import org.hibernate.QueryException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import eu.sqooss.service.db.DAObject; +import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.DBSessionManager; +import eu.sqooss.service.db.DBSessionValidation; +import eu.sqooss.service.db.HQLQueryInterface; +import eu.sqooss.service.db.QueryInterfaceFactory; +import eu.sqooss.service.logging.Logger; + +/** + * Default implementation of the doHQL functions and standard query functions. + */ +public class HQLQueryInterfaceImpl implements HQLQueryInterface { + + private SessionFactory sessionFactory; + private DBSessionManager sessionManager; + private DBSessionValidation sessionValidation; + private Logger logger; + + public HQLQueryInterfaceImpl(DBSessionManager sessionManager, DBSessionValidation sessionValidation, + SessionFactory sessionFactory, Logger logger) { + this.sessionManager = sessionManager; + this.sessionValidation = sessionValidation; + this.sessionFactory = sessionFactory; + this.logger = logger; + } + + public T findObjectById(Class daoClass, long id) { + return doFindObjectById(daoClass, id, false); + } + + public T findObjectByIdForUpdate(Class daoClass, long id) { + return doFindObjectById(daoClass, id, true); + } + + @SuppressWarnings("unchecked") + private T doFindObjectById(Class daoClass, long id, boolean useLock) { + if ( !sessionValidation.checkSession() ) + return null; + + try { + Session s = sessionFactory.getCurrentSession(); + return (T) (useLock ? s.get(daoClass, id, LockMode.UPGRADE) : s.get(daoClass, id)); + } catch (HibernateException e) { + sessionValidation.logExceptionAndTerminateSession(e); + return null; + } + } + + public List findObjectsByProperties(Class daoClass, Map properties) { + return doFindObjectsByProperties(daoClass, properties, false); + } + + public List findObjectsByPropertiesForUpdate(Class daoClass, Map properties) { + return doFindObjectsByProperties(daoClass, properties, true); + } + + @SuppressWarnings("unchecked") + private List doFindObjectsByProperties(Class daoClass, Map properties, boolean useLock) { + if( !sessionValidation.checkSession() ) + return Collections.emptyList(); + + // TODO maybe check that the properties are valid (e.g. with java.bean.PropertyDescriptor) + + Map parameterMap = new HashMap(); + StringBuffer whereClause = new StringBuffer(); + for (String key : properties.keySet()) { + whereClause.append( whereClause.length() == 0 ? " where " : " and " ); + // We use "foo" as the name of the object + whereClause.append("foo" + "." + key + "=:_" + key ); + parameterMap.put( "_" + key, properties.get(key) ); + } + try { + // We use "foo" as the name of the object + return (List) doHQL( "from " + daoClass.getName() + " as foo " + whereClause, parameterMap, useLock ); + } catch (QueryException e) { + logger.warn("findObjectsByProperties(): invalid properties map. Restarting session..."); + // Automatically restart a session + // (just be careful with preloaded DAOs that become detached) + sessionManager.startDBSession(); + return Collections.emptyList(); + } + } + + public boolean addRecord(DAObject record) { + ArrayList tmpList = new ArrayList(1); + tmpList.add(record); + return addRecords(tmpList); + } + + public boolean deleteRecord(DAObject record) { + ArrayList tmpList = new ArrayList(1); + tmpList.add(record); + return deleteRecords(tmpList); + } + + public boolean addRecords(List records) { + if( !sessionValidation.checkSession() ) + return false; + + DAObject lastRecord = null; + try { + Session s = sessionFactory.getCurrentSession(); + for (DAObject record : records) { + lastRecord = record; + s.save(record); + } + lastRecord = null; + s.flush(); + return true; + } catch (HibernateException e) { + if (lastRecord != null) { + logger.error("Failed to add object " + + "[" + lastRecord.getClass().getName() + ":" + lastRecord.getId() + "]" + + " to the database: " + e.getMessage()); + } + sessionValidation.logExceptionAndTerminateSession(e); + return false; + } + } + + public boolean deleteRecords(List records) { + if( !sessionValidation.checkSession() ) + return false; + + DAObject lastRecord = null; + try { + Session s = sessionFactory.getCurrentSession(); + for (DAObject record : records) { + lastRecord = record; + s.delete(record); + } + lastRecord = null; + s.flush(); + return true; + } catch (HibernateException e) { + if (lastRecord != null) { + logger.error("Failed to remove object " + + "[" + lastRecord.getClass().getName() + ":" + lastRecord.getId() + "]" + + " from the database: " + e.getMessage()); + } + sessionValidation.logExceptionAndTerminateSession(e); + return false; + } + } + + public List doHQL(String hql) + throws QueryException { + return doHQL(hql, null, null, false, -1, -1); + } + + public List doHQL(String hql, Map params) + throws QueryException { + return doHQL(hql, params, null, false, -1, -1); + } + + public List doHQL(String hql, Map params, int limit) + throws QueryException { + return doHQL(hql, params, null, false, 0, limit); + } + + public List doHQL(String hql, Map params, boolean lockForUpdate) + throws QueryException { + return doHQL(hql, params, null, lockForUpdate, -1, -1); + } + + public List doHQL(String hql, Map params, + Map collectionParams) + throws QueryException { + return doHQL(hql, params, collectionParams, false, -1, -1); + } + + public List doHQL(String hql, Map params, + Map collectionParams, boolean lockForUpdate, int start, int limit) + throws QueryException { + if ( !sessionValidation.checkSession() ) { + return Collections.emptyList(); + } + try { + Session s = sessionFactory.getCurrentSession(); + Query query = s.createQuery(hql); + if (params != null) { + for ( String param : params.keySet() ) { + query.setParameter(param, params.get(param)); + } + } + if (collectionParams != null) { + for ( String param : collectionParams.keySet() ) { + query.setParameterList(param, collectionParams.get(param)); + } + } + if (lockForUpdate) { + query.setLockMode("foo", LockMode.PESSIMISTIC_WRITE); + } + if ( start >= 0 && limit >= 0 ) { + query.setFirstResult(start); + query.setMaxResults(limit); + } + return query.list(); + } catch ( QueryException e ) { + sessionValidation.logExceptionAndTerminateSession(e); + throw e; + } catch( HibernateException e ) { + sessionValidation.logExceptionAndTerminateSession(e); + return Collections.emptyList(); + } catch (ClassCastException e) { + // Throw a QueryException instead of forwarding the ClassCastException + // it's more explicit + QueryException ebis = new QueryException("Invalid HQL query parameter type: " + + e.getMessage(), e); + sessionValidation.logExceptionAndTerminateSession(ebis); + throw ebis; + } + + } + + public int executeUpdate(String hql, Map params) throws QueryException { + if (!sessionValidation.checkSession()) { + return -1; + } + + try { + Session s = sessionFactory.getCurrentSession(); + Query query = s.createQuery(hql); + if (params != null) { + for (String param : params.keySet()) { + query.setParameter(param, params.get(param)); + } + } + + return query.executeUpdate(); + + } catch (QueryException e) { + sessionValidation.logExceptionAndTerminateSession(e); + throw e; + } catch (HibernateException e) { + sessionValidation.logExceptionAndTerminateSession(e); + return -1; + } catch (ClassCastException e) { + // Throw a QueryException instead of forwarding the ClassCastException + // it's more explicit + QueryException ebis = new QueryException( + "Invalid HQL query parameter type: " + e.getMessage(), e); + sessionValidation.logExceptionAndTerminateSession(ebis); + throw ebis; + } + } + + public static class Factory implements QueryInterfaceFactory { + + @Override + public HQLQueryInterface build(DBService dbService, SessionFactory sessionFactory, + DBSessionValidation sessionValidation) { + return new HQLQueryInterfaceImpl(dbService.getSessionManager(), + sessionValidation, sessionFactory, dbService.logger()); + } + } +} diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/db/SQLQueryInterfaceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/SQLQueryInterfaceImpl.java new file mode 100644 index 000000000..9ec935472 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/db/SQLQueryInterfaceImpl.java @@ -0,0 +1,181 @@ +package eu.sqooss.impl.service.db; + +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.JDBCException; +import org.hibernate.Query; +import org.hibernate.QueryException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import eu.sqooss.service.db.DAObject; +import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.DBSessionManager; +import eu.sqooss.service.db.DBSessionValidation; +import eu.sqooss.service.db.QueryInterface; +import eu.sqooss.service.db.QueryInterfaceFactory; +import eu.sqooss.service.db.SQLQueryInterface; + +/** + * Default implementation of the (deprecated) SQL queries. The standard queries + * specified by QueryInterface are not supported through SQL, so these functions + * are delegated to the QueryInterface instance provided by DBService. + */ +public class SQLQueryInterfaceImpl implements SQLQueryInterface { + + private DBService dbService; + private QueryInterface qi; + private DBSessionManager sessionManager; + private DBSessionValidation sessionValidation; + private SessionFactory sessionFactory; + + public SQLQueryInterfaceImpl(DBService dbService, DBSessionValidation sesVal, + SessionFactory sesFac) { + this.sessionManager = dbService.getSessionManager(); + this.sessionValidation = sesVal; + this.sessionFactory = sesFac; + this.dbService = dbService; + this.qi = null; + } + + @Override + @Deprecated + public List doSQL(String sql) throws SQLException { + return doSQL(sql, null); + } + + @Override + @Deprecated + public List doSQL(String sql, Map params) + throws SQLException, QueryException { + boolean autoSession = !sessionManager.isDBSessionActive(); + try { + Session s = sessionFactory.getCurrentSession(); + if (autoSession) { + s.beginTransaction(); + } + Query query = s.createSQLQuery(sql); + if ( params != null ) { + for ( String param : params.keySet() ) { + query.setParameter(param, params.get(param)); + } + } + List result = query.list(); + if (autoSession) { + s.getTransaction().commit(); + } + return result; + } catch ( JDBCException e ) { + sessionValidation.logExceptionAndTerminateSession(e); + throw e.getSQLException(); + } catch ( QueryException e ) { + sessionValidation.logExceptionAndTerminateSession(e); + throw e; + } catch( HibernateException e ) { + sessionValidation.logExceptionAndTerminateSession(e); + return Collections.emptyList(); + } + } + + @Override + @Deprecated + public int callProcedure(String procName, List args, + Map params) throws SQLException, QueryException { + boolean autoSession = !sessionManager.isDBSessionActive(); + StringBuilder sql = new StringBuilder("call " + procName + "("); + + for (String arg : args) { + sql.append(":").append(arg).append(","); + } + sql.deleteCharAt(sql.lastIndexOf(",")).append(")"); + + try { + Session s = sessionFactory.getCurrentSession(); + if (autoSession) { + s.beginTransaction(); + } + Query query = s.createSQLQuery(sql.toString()); + if (params != null) { + for (String param : params.keySet()) { + query.setParameter(param, params.get(param)); + } + } + int result = query.executeUpdate(); + if (autoSession) { + s.getTransaction().commit(); + } + return result; + } catch (JDBCException e) { + sessionValidation.logExceptionAndTerminateSession(e); + throw e.getSQLException(); + } catch (QueryException e) { + sessionValidation.logExceptionAndTerminateSession(e); + throw e; + } catch (HibernateException e) { + sessionValidation.logExceptionAndTerminateSession(e); + throw e; + } + } + + @Override + public T findObjectById(Class daoClass, long id) { + return getQI().findObjectById(daoClass, id); + } + + @Override + public T findObjectByIdForUpdate(Class daoClass, + long id) { + return getQI().findObjectByIdForUpdate(daoClass, id); + } + + @Override + public List findObjectsByProperties( + Class daoClass, Map properties) { + return getQI().findObjectsByProperties(daoClass, properties); + } + + @Override + public List findObjectsByPropertiesForUpdate( + Class daoClass, Map properties) { + return getQI().findObjectsByPropertiesForUpdate(daoClass, properties); + } + + @Override + public boolean addRecord(DAObject record) { + return getQI().addRecord(record); + } + + @Override + public boolean addRecords(List records) { + return getQI().addRecords(records); + } + + @Override + public boolean deleteRecord(DAObject record) { + return getQI().deleteRecord(record); + } + + @Override + public boolean deleteRecords(List records) { + return getQI().deleteRecords(records); + } + + private QueryInterface getQI() { + if (qi == null) + qi = dbService.getQueryInterface(); + return qi; + } + + public static class Factory implements QueryInterfaceFactory { + + @Override + public SQLQueryInterface build(DBService dbService, SessionFactory sessionFactory, + DBSessionValidation sessionValidation) { + return new SQLQueryInterfaceImpl(dbService, sessionValidation, sessionFactory); + } + } +} diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/FDSServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/FDSServiceImpl.java index e28fb7ea3..a96af47d2 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/FDSServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/FDSServiceImpl.java @@ -393,7 +393,7 @@ private ProjectVersion cacheKeyProjectVersion(String key) { DBService dbs = AlitheiaCore.getInstance().getDBService(); Long id = Long.parseLong(key.split("|")[1]); - return dbs.findObjectById(ProjectVersion.class, id); + return dbs.getQueryInterface().findObjectById(ProjectVersion.class, id); } /** diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/OnDiskCheckoutImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/OnDiskCheckoutImpl.java index 36087f5b8..b7c6f0d0a 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/OnDiskCheckoutImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/OnDiskCheckoutImpl.java @@ -122,7 +122,7 @@ public File getRoot() /** {@inheritDoc} */ public ProjectVersion getProjectVersion() { DBService dbs = AlitheiaCore.getInstance().getDBService(); - revision = dbs.attachObjectToDBSession(revision); + revision = dbs.getSessionManager().attachObjectToDBSession(revision); return revision; } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/TimelineImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/TimelineImpl.java index 8707e9348..064284033 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/TimelineImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/fds/TimelineImpl.java @@ -46,6 +46,7 @@ import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.db.Bug; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.MailMessage; import eu.sqooss.service.db.MailingList; import eu.sqooss.service.db.ProjectVersion; @@ -85,7 +86,7 @@ private SortedSet getScmTimeLine(Calendar from, Calendar to) { params.put("paramFrom", begin); params.put("paramProject", project); - List versions = (List) dbs.doHQL(query.toString(), params); + List versions = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query.toString(), params); for(ProjectVersion version : versions) { result.add( new RepositoryEvent(version.getTimestamp(), version) ); @@ -113,7 +114,7 @@ private SortedSet getMailTimeLine(Calendar from, Calendar to) if (lists != null) { for (MailingList list : lists) { params.put("paramList", list); - List messages = (List) dbs.doHQL(query.toString(), params); + List messages = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query.toString(), params); for (MailMessage message : messages) { result.add(new MailingListEvent( @@ -141,7 +142,7 @@ private SortedSet getBugTimeLine(Calendar from, Calendar to) { params.put("paramTo", end); params.put("paramFrom", begin); params.put("paramProject", project); - List bugs = (List) dbs.doHQL(query.toString(), params); + List bugs = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query.toString(), params); for (Bug bug : bugs) { result.add(new BugDBEvent(bug.getCreationTS().getTime(), bug)); diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorImpl.java index 4487e5202..0df5f78c7 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorImpl.java @@ -37,6 +37,7 @@ import java.util.concurrent.atomic.AtomicLong; import eu.sqooss.service.abstractmetric.InvocationOrder; + import org.osgi.framework.BundleContext; import eu.sqooss.core.AlitheiaCore; @@ -51,6 +52,7 @@ import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.EncapsulationUnit; import eu.sqooss.service.db.ExecutionUnit; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.MailMessage; import eu.sqooss.service.db.MailingList; import eu.sqooss.service.db.MailingListThread; @@ -132,7 +134,7 @@ public void syncMetrics(StoredProject sp, Class actType) { @Override public void syncMetrics(AlitheiaPlugin ap) { List lp = - (List) db.doHQL("from StoredProject"); + (List) db.getQueryInterface(HQLQueryInterface.class).doHQL("from StoredProject"); for(StoredProject sp : lp) { syncMetric(ap, sp); @@ -286,7 +288,7 @@ public long priority() { @Override protected void run() throws Exception { DBService dbs = AlitheiaCore.getInstance().getDBService(); - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); sp = DAObject.loadDAObyId(sp.getId(), StoredProject.class); PluginInfo mi = pa.getPluginInfo(m); Set> actTypes = mi.getActivationTypes(); @@ -364,7 +366,7 @@ protected void run() throws Exception { } } sched.enqueueNoDependencies(jobs); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); } @Override diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorJob.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorJob.java index 8a8c923b4..592af556e 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorJob.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/metricactivator/MetricActivatorJob.java @@ -83,9 +83,9 @@ public long priority() { @Override protected void run() throws Exception { - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); metric.setJob(this); - DAObject obj = dbs.findObjectById(daoType, daoID); + DAObject obj = dbs.getQueryInterface().findObjectById(daoType, daoID); try { if (fastSync) { @@ -108,13 +108,13 @@ protected void run() throws Exception { } catch (AlreadyProcessingException ape) { logger.warn("DAO id " + daoID + " is locked, job has been " + "rescheduled"); - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); return; } catch (LockAcquisitionException lae) { - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); } - if (!dbs.commitDBSession()) { + if (!dbs.getSessionManager().commitDBSession()) { logger.warn("commit failed - restarting metric job"); restart(); } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/pa/PAServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/pa/PAServiceImpl.java index 436496aba..379316c3c 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/pa/PAServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/pa/PAServiceImpl.java @@ -397,7 +397,7 @@ public void serviceChanged(ServiceEvent event) { // Get a reference to the affected service ServiceReference affectedService = event.getServiceReference(); - sobjDB.startDBSession(); + sobjDB.getSessionManager().startDBSession(); // Find out what happened to the service switch (event.getType()) { @@ -415,7 +415,7 @@ public void serviceChanged(ServiceEvent event) { } // Close the DB session - sobjDB.commitDBSession(); + sobjDB.getSessionManager().commitDBSession(); } /* ===[ Implementation of the PluginAdmin interface ]===================== */ @@ -646,7 +646,7 @@ protected void run() throws Exception { try { DBService dbs = AlitheiaCore.getInstance().getDBService(); - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); // Get the metric plug-in's service ServiceReference srefPlugin = getPluginService(serviceID); @@ -674,7 +674,7 @@ protected void run() throws Exception { pluginInfo.getHashcode(), pluginInfo); } } - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); } catch (Exception e) { logger.warn(UNINSTALL_FAILED, e); } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/rest/ResteasyServlet.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/rest/ResteasyServlet.java index cbb414ca1..114dcc0ae 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/rest/ResteasyServlet.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/rest/ResteasyServlet.java @@ -51,12 +51,12 @@ protected void service(HttpServletRequest httpServletRequest, DBService db = AlitheiaCore.getInstance().getDBService(); - if (!db.isDBSessionActive()) - db.startDBSession(); + if (!db.getSessionManager().isDBSessionActive()) + db.getSessionManager().startDBSession(); super.service(httpServletRequest, httpServletResponse); - if (db.isDBSessionActive()) - db.commitDBSession(); + if (db.getSessionManager().isDBSessionActive()) + db.getSessionManager().commitDBSession(); } } \ No newline at end of file diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/tds/TDSServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/tds/TDSServiceImpl.java index 9635be25d..b51ae556f 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/tds/TDSServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/tds/TDSServiceImpl.java @@ -146,13 +146,13 @@ private void stuffer() { logger.info("TDS is now running the stuffer."); DBService db = AlitheiaCore.getInstance().getDBService(); - if (db != null && db.startDBSession()) { + if (db != null && db.getSessionManager().startDBSession()) { for (StoredProject p : ClusterNode.thisNode().getProjects()) { addAccessor(p.getId(), p.getName(), p.getBtsUrl(), p.getMailUrl(), p.getScmUrl()); } - db.commitDBSession(); + db.getSessionManager().commitDBSession(); } logger.info("TDS Stuffer is finished."); diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/OhlohUpdater.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/OhlohUpdater.java index 6d7016203..f02c14ba2 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/OhlohUpdater.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/OhlohUpdater.java @@ -106,7 +106,7 @@ public boolean accept(File dir, String name) { for (String file : files) { - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); SAXReader reader = new SAXReader(false); Document document = null; @@ -160,10 +160,10 @@ public InputSource resolveEntity(String publicId, String systemId) { od.setUname(uname); } else { od = new OhlohDeveloper(uname, mailhash, id); - dbs.addRecord(od); + dbs.getQueryInterface().addRecord(od); } } - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); } } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/UpdaterServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/UpdaterServiceImpl.java index 75148b1fe..c63b34732 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/UpdaterServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/updater/UpdaterServiceImpl.java @@ -571,8 +571,8 @@ public synchronized void jobStateChanged(Job j, State newState) { return; } - if (!dbs.isDBSessionActive()) - dbs.startDBSession(); + if (!dbs.getSessionManager().isDBSessionActive()) + dbs.getSessionManager().startDBSession(); StoredProject sp = StoredProject.loadDAObyId(projectId, StoredProject.class); removeUpdater(sp, ut); @@ -580,7 +580,7 @@ public synchronized void jobStateChanged(Job j, State newState) { logger.warn(ut + " updater job for project " + sp + " did not finish properly"); } - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); } } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/AdminServlet.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/AdminServlet.java index bde9ad0e3..ea1b42fba 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/AdminServlet.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/AdminServlet.java @@ -157,8 +157,8 @@ private void addStaticContent(String path, String type) { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - if (!db.isDBSessionActive()) { - db.startDBSession(); + if (!db.getSessionManager().isDBSessionActive()) { + db.getSessionManager().startDBSession(); } try { @@ -199,8 +199,8 @@ else if ((query != null) && (dynamicContentMap.containsKey(query))) { logger.warn("Got a NPE while rendering a page.",e); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } finally { - if (db.isDBSessionActive()) { - db.commitDBSession(); + if (db.getSessionManager().isDBSessionActive()) { + db.getSessionManager().commitDBSession(); } } } @@ -208,8 +208,8 @@ else if ((query != null) && (dynamicContentMap.containsKey(query))) { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - if (!db.isDBSessionActive()) { - db.startDBSession(); + if (!db.getSessionManager().isDBSessionActive()) { + db.getSessionManager().startDBSession(); } try { @@ -236,8 +236,8 @@ protected void doPost(HttpServletRequest request, logger.warn("Got a NPE while handling POST data."); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } finally { - if (db.isDBSessionActive()) { - db.commitDBSession(); + if (db.getSessionManager().isDBSessionActive()) { + db.getSessionManager().commitDBSession(); } } } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectDeleteJob.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectDeleteJob.java index dcdda445d..31491f7ee 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectDeleteJob.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectDeleteJob.java @@ -39,6 +39,7 @@ import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.abstractmetric.AlitheiaPlugin; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Plugin; import eu.sqooss.service.db.ProjectVersion; import eu.sqooss.service.db.StoredProject; @@ -65,17 +66,17 @@ public long priority() { protected void run() throws Exception { DBService dbs = core.getDBService(); - if (!dbs.isDBSessionActive()) { - dbs.startDBSession(); + if (!dbs.getSessionManager().isDBSessionActive()) { + dbs.getSessionManager().startDBSession(); } - sp = dbs.attachObjectToDBSession(sp); + sp = dbs.getSessionManager().attachObjectToDBSession(sp); // Delete any associated invocation rules first HashMap properties = new HashMap(); properties.put("project", sp); //Cleanup plugin results - List ps = (List) dbs.doHQL("from Plugin"); + List ps = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL("from Plugin"); for (Plugin p : ps ) { AlitheiaPlugin ap = core.getPluginAdmin().getPlugin(core.getPluginAdmin().getPluginInfo(p.getHashcode())); @@ -104,16 +105,16 @@ protected void run() throws Exception { //Delete the project's config options List confParams = StoredProjectConfig.fromProject(sp); if (!confParams.isEmpty()) { - success &= dbs.deleteRecords(confParams); + success &= dbs.getQueryInterface().deleteRecords(confParams); } // Delete the selected project - success &= dbs.deleteRecord(sp); + success &= dbs.getQueryInterface().deleteRecord(sp); if (success) { - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); } else { - dbs.rollbackDBSession(); + dbs.getSessionManager().rollbackDBSession(); } } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectsView.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectsView.java index 2975b36d6..957122eea 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectsView.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/webadmin/ProjectsView.java @@ -135,7 +135,7 @@ public static String render(HttpServletRequest req) { // Retrieve the selected project's DAO (if any) reqValProjectId = fromString(req.getParameter(REQ_PAR_PROJECT_ID)); if (reqValProjectId != null) { - selProject = sobjDB.findObjectById( + selProject = sobjDB.getQueryInterface().findObjectById( StoredProject.class, reqValProjectId); } diff --git a/alitheia/core/src/main/java/eu/sqooss/rest/api/MetricsResource.java b/alitheia/core/src/main/java/eu/sqooss/rest/api/MetricsResource.java index a3416b5c7..85e1e5d81 100644 --- a/alitheia/core/src/main/java/eu/sqooss/rest/api/MetricsResource.java +++ b/alitheia/core/src/main/java/eu/sqooss/rest/api/MetricsResource.java @@ -45,6 +45,7 @@ import eu.sqooss.service.abstractmetric.Result; import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Metric; import eu.sqooss.service.db.MetricType; import eu.sqooss.service.db.MetricType.Type; @@ -64,7 +65,7 @@ public MetricsResource() {} public List getMetrics() { DBService db = AlitheiaCore.getInstance().getDBService(); String q = " from Metric"; - List sp = (List) db.doHQL(q); + List sp = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(q); return sp; } @@ -74,7 +75,7 @@ public List getMetrics() { public List getMetricTypes() { DBService db = AlitheiaCore.getInstance().getDBService(); String q = " from MetricType"; - List sp = (List) db.doHQL(q); + List sp = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(q); return sp; } diff --git a/alitheia/core/src/main/java/eu/sqooss/rest/api/StoredProjectResource.java b/alitheia/core/src/main/java/eu/sqooss/rest/api/StoredProjectResource.java index 6c5cf004b..4fcb5fc5f 100644 --- a/alitheia/core/src/main/java/eu/sqooss/rest/api/StoredProjectResource.java +++ b/alitheia/core/src/main/java/eu/sqooss/rest/api/StoredProjectResource.java @@ -48,6 +48,7 @@ import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.Directory; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Metric; import eu.sqooss.service.db.ProjectFile; import eu.sqooss.service.db.ProjectVersion; @@ -64,7 +65,7 @@ public StoredProjectResource() {} public List getProjects() { DBService db = AlitheiaCore.getInstance().getDBService(); String q = " from StoredProject"; - List sp = (List) db.doHQL(q); + List sp = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(q); return sp; } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/abstractmetric/AbstractMetric.java b/alitheia/core/src/main/java/eu/sqooss/service/abstractmetric/AbstractMetric.java index 73df1f9fb..aa7473d4f 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/abstractmetric/AbstractMetric.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/abstractmetric/AbstractMetric.java @@ -60,6 +60,7 @@ import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.EncapsulationUnitMeasurement; import eu.sqooss.service.db.ExecutionUnitMeasurement; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.MailMessageMeasurement; import eu.sqooss.service.db.MailingListThreadMeasurement; import eu.sqooss.service.db.Metric; @@ -70,6 +71,7 @@ import eu.sqooss.service.db.PluginConfiguration; import eu.sqooss.service.db.ProjectFileMeasurement; import eu.sqooss.service.db.ProjectVersionMeasurement; +import eu.sqooss.service.db.QueryInterface; import eu.sqooss.service.db.StoredProject; import eu.sqooss.service.db.StoredProjectMeasurement; import eu.sqooss.service.db.MetricType.Type; @@ -98,6 +100,7 @@ public abstract class AbstractMetric implements AlitheiaPlugin { /** Reference to the DB service, not to be passed to metric jobs */ protected DBService db; + protected QueryInterface qi; /** * Reference to the plugin administrator service, not to be passed to @@ -231,6 +234,8 @@ protected AbstractMetric(BundleContext bc) { if(db == null) log.error("Could not get a reference to the DB service"); + else + qi = db.getQueryInterface(); pa = AlitheiaCore.getInstance().getPluginAdmin(); @@ -561,7 +566,7 @@ public List getAllSupportedMetrics() { Map params = new HashMap(); params.put("plugin", Plugin.getPluginByHashcode(getUniqueKey())); - return (List)db.doHQL(qry, params); + return (List)db.getQueryInterface(HQLQueryInterface.class).doHQL(qry, params); } /** {@inheritDoc} */ @@ -598,7 +603,7 @@ public boolean install() { HashMap h = new HashMap(); h.put("name", this.getName()); - List plugins = db.findObjectsByProperties(Plugin.class, h); + List plugins = qi.findObjectsByProperties(Plugin.class, h); if (!plugins.isEmpty()) { log.warn("A plugin with name <" + getName() @@ -614,7 +619,7 @@ public boolean install() { p.setVersion(getVersion()); p.setActive(true); p.setHashcode(getUniqueKey()); - boolean result = db.addRecord(p); + boolean result = qi.addRecord(p); //3. Add the metrics for (String mnem :metrics.keySet()) { @@ -623,13 +628,13 @@ public boolean install() { MetricType newType = MetricType.getMetricType(type); if (newType == null) { newType = new MetricType(type); - db.addRecord(newType); + qi.addRecord(newType); m.setMetricType(newType); } m.setMetricType(newType); m.setPlugin(p); - db.addRecord(m); + qi.addRecord(m); } return result; @@ -642,7 +647,7 @@ public boolean install() { */ public boolean remove() { Plugin p = Plugin.getPluginByHashcode(getUniqueKey()); - return db.deleteRecord(p); + return qi.deleteRecord(p); } /** @@ -844,12 +849,12 @@ public PluginConfiguration getConfigurationOption(String config) { */ protected List getResult(DAObject o, Class clazz, Metric m, Result.ResultType type) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + //DBService dbs = AlitheiaCore.getInstance().getDBService(); Map props = new HashMap(); props.put(resultFieldNames.get(clazz), o); props.put("metric", m); - List resultat = dbs.findObjectsByProperties(clazz, props); + List resultat = qi.findObjectsByProperties(clazz, props); if (resultat.isEmpty()) return Collections.EMPTY_LIST; @@ -929,7 +934,7 @@ public Map> getObjectIdsToSync(StoredProject sp throw new MetricActivationException("Metric synchronisation with GENERIC objects not implemented"); } - List objectIds = (List) db.doHQL(q, params); + List objectIds = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(q, params); TreeSet ids = new TreeSet(); ids.addAll(objectIds); IDs.put(MetricType.fromActivator(at), ids); diff --git a/alitheia/core/src/main/java/eu/sqooss/service/admin/actions/AddProject.java b/alitheia/core/src/main/java/eu/sqooss/service/admin/actions/AddProject.java index 16dbe459b..76ba4f631 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/admin/actions/AddProject.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/admin/actions/AddProject.java @@ -12,6 +12,7 @@ import eu.sqooss.service.db.ConfigOption; import eu.sqooss.service.db.ConfigurationOption; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.QueryInterface; import eu.sqooss.service.db.StoredProject; import eu.sqooss.service.tds.BTSAccessor; import eu.sqooss.service.tds.InvalidAccessorException; @@ -79,7 +80,7 @@ public String descr() { public void execute() throws Exception { super.execute(); String name = null, bts = null, scm = null, mail = null, contact = null, web = null; - DBService db = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); TDSService tds = AlitheiaCore.getInstance().getTDSService(); if (args.containsKey("dir")) { @@ -122,7 +123,7 @@ public void execute() throws Exception { // 1. Duplicate project HashMap props = new HashMap(); props.put("name", name); - if (!db.findObjectsByProperties(StoredProject.class, props).isEmpty()) { + if (!qi.findObjectsByProperties(StoredProject.class, props).isEmpty()) { error("project.exists", "A project with the same name already exists"); } @@ -179,7 +180,7 @@ public void execute() throws Exception { StoredProject sp = new StoredProject(name); //The project is now ready to be added - db.addRecord(sp); + qi.addRecord(sp); //Store all known properties to the database for (ConfigOption co : ConfigOption.values()) { diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/Branch.java b/alitheia/core/src/main/java/eu/sqooss/service/db/Branch.java index a58576cd3..4169eb5b1 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/Branch.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/Branch.java @@ -147,20 +147,20 @@ public void setBranchOutgoing(Set branchOutgoing) { } public static Branch fromName(StoredProject sp, String name, boolean create) { - DBService db = AlitheiaCore.getInstance().getDBService(); + HQLQueryInterface hqi = AlitheiaCore.getInstance().getDBService().getQueryInterface(HQLQueryInterface.class); Map params = new HashMap(); params.put("name", name); params.put("project", sp); - List branches = (List)db.doHQL(qBranchByName, params); + List branches = (List)hqi.doHQL(qBranchByName, params); if (branches.isEmpty()) { if (!create) return null; Branch b = new Branch(); b.setProject(sp); b.setName(name); - db.addRecord(b); + hqi.addRecord(b); return fromName(sp, name, false); } @@ -168,12 +168,12 @@ public static Branch fromName(StoredProject sp, String name, boolean create) { } public static String suggestName(StoredProject sp) { - DBService db = AlitheiaCore.getInstance().getDBService(); + HQLQueryInterface hqi = AlitheiaCore.getInstance().getDBService().getQueryInterface(HQLQueryInterface.class); Map params = new HashMap(); params.put("project", sp); - List ids = (List) db.doHQL(qNextSequence, params); + List ids = (List) hqi.doHQL(qNextSequence, params); if (ids.isEmpty()) return "1"; else diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/Bug.java b/alitheia/core/src/main/java/eu/sqooss/service/db/Bug.java index 78b67dad8..722d34bef 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/Bug.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/Bug.java @@ -253,7 +253,7 @@ public static Bug getLastUpdate(StoredProject sp) { Map params = new HashMap(); params.put(paramStoredProject, sp); - List buglist = (List) dbs.doHQL(query, params,1); + List buglist = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params,1); if (buglist.isEmpty()) return null; @@ -283,7 +283,7 @@ public List getAllReportComments() { params.put(paramBugID, bugID); params.put(paramStoredProject, project); - return (List) dbs.doHQL(query, params); + return (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params); } /** @@ -305,7 +305,7 @@ public static Bug getBug(String bugID, StoredProject sp) { params.put(paramBugID, bugID); params.put(paramStoredProject, sp); - List bug = (List) dbs.doHQL(query, params, 1); + List bug = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params, 1); if (bug.isEmpty()) return null; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/BugPriority.java b/alitheia/core/src/main/java/eu/sqooss/service/db/BugPriority.java index 1dc1419c2..35bd9b0a2 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/BugPriority.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/BugPriority.java @@ -160,12 +160,12 @@ public static BugPriority getBugPriority(Priority s) { * while modifying the DB. */ public static BugPriority getBugPriority(String priority, boolean create) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("priority", priority); - List st = dbs.findObjectsByProperties(BugPriority.class, + List st = qi.findObjectsByProperties(BugPriority.class, params); if (!st.isEmpty()) { @@ -183,7 +183,7 @@ public static BugPriority getBugPriority(String priority, boolean create) { BugPriority bs = new BugPriority(); bs.setpriority(priority); - if (!dbs.addRecord(bs)) + if (!qi.addRecord(bs)) return null; return bs; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/BugResolution.java b/alitheia/core/src/main/java/eu/sqooss/service/db/BugResolution.java index 1907e44a9..5b44b2d20 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/BugResolution.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/BugResolution.java @@ -163,12 +163,12 @@ public static BugResolution getBugResolution(BugResolution.Resolution s) { * while modifying the DB. */ public static BugResolution getBugResolution(String resolution, boolean create) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("resolution", resolution); - List st = dbs.findObjectsByProperties(BugResolution.class, + List st = qi.findObjectsByProperties(BugResolution.class, params); if (!st.isEmpty()) { @@ -186,7 +186,7 @@ public static BugResolution getBugResolution(String resolution, boolean create) BugResolution bs = new BugResolution(); bs.setResolution(resolution); - if (!dbs.addRecord(bs)) + if (!qi.addRecord(bs)) return null; return bs; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/BugSeverity.java b/alitheia/core/src/main/java/eu/sqooss/service/db/BugSeverity.java index e00652662..121ec6861 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/BugSeverity.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/BugSeverity.java @@ -170,12 +170,12 @@ public static BugSeverity getBugseverity(Severity s) { * while modifying the DB. */ public static BugSeverity getBugSeverity(String severity, boolean create) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("severity", severity); - List st = dbs.findObjectsByProperties(BugSeverity.class, + List st = qi.findObjectsByProperties(BugSeverity.class, params); if (!st.isEmpty()) { @@ -193,7 +193,7 @@ public static BugSeverity getBugSeverity(String severity, boolean create) { BugSeverity bs = new BugSeverity(); bs.setSeverity(severity); - if (!dbs.addRecord(bs)) + if (!qi.addRecord(bs)) return null; return bs; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/BugStatus.java b/alitheia/core/src/main/java/eu/sqooss/service/db/BugStatus.java index 6a3e27ff7..990f09898 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/BugStatus.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/BugStatus.java @@ -168,12 +168,12 @@ public static BugStatus getBugStatus(BugStatus.Status s) { * while modifying the DB. */ public static BugStatus getBugStatus(String status, boolean create) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("status", status); - List st = dbs.findObjectsByProperties(BugStatus.class, + List st = qi.findObjectsByProperties(BugStatus.class, params); if (!st.isEmpty()) { @@ -191,7 +191,7 @@ public static BugStatus getBugStatus(String status, boolean create) { BugStatus bs = new BugStatus(); bs.setStatus(status); - if (!dbs.addRecord(bs)) + if (!qi.addRecord(bs)) return null; return bs; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/ClusterNode.java b/alitheia/core/src/main/java/eu/sqooss/service/db/ClusterNode.java index 1439add8e..6b277984c 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/ClusterNode.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/ClusterNode.java @@ -109,11 +109,11 @@ public void setProjects(Set projects) { } public static ClusterNode getClusteNodeByName(String name) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map parameterMap = new HashMap(); parameterMap.put("name",name); - List cnList = dbs.findObjectsByProperties(ClusterNode.class, parameterMap); + List cnList = qi.findObjectsByProperties(ClusterNode.class, parameterMap); return (cnList == null || cnList.isEmpty()) ? null : cnList.get(0); } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/ConfigurationOption.java b/alitheia/core/src/main/java/eu/sqooss/service/db/ConfigurationOption.java index 5ef0c8220..234a7e318 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/ConfigurationOption.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/ConfigurationOption.java @@ -131,7 +131,7 @@ public void setConfigurations(Set configurations) { */ public void setValues(StoredProject sp, List values, boolean overwrite) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + HQLQueryInterface hqi = AlitheiaCore.getInstance().getDBService().getQueryInterface(HQLQueryInterface.class); String paramProject = "paramProject"; String paramConfOpt = "paramConfOpt"; @@ -149,14 +149,14 @@ public void setValues(StoredProject sp, List values, params.put(paramConfOpt, this); List curValues = - (List) dbs.doHQL(query.toString(),params); + (List) hqi.doHQL(query.toString(),params); boolean found = false; if (overwrite) { - dbs.deleteRecords(curValues); + hqi.deleteRecords(curValues); for (String newValue : values) { StoredProjectConfig newspc = new StoredProjectConfig( this, newValue, sp); - dbs.addRecord(newspc); + hqi.addRecord(newspc); } } else { //Merge values for (String newValue : values) { @@ -168,7 +168,7 @@ public void setValues(StoredProject sp, List values, if (!found) { StoredProjectConfig newspc = new StoredProjectConfig( this, newValue, sp); - dbs.addRecord(newspc); + hqi.addRecord(newspc); } } } @@ -197,18 +197,18 @@ public List getValues(StoredProject sp) { params.put(paramProject, sp); params.put(paramConfOpt, this); - return (List) dbs.doHQL(query.toString(), params); + return (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query.toString(), params); } public static ConfigurationOption fromKey(String key) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + HQLQueryInterface hqi = AlitheiaCore.getInstance().getDBService().getQueryInterface(HQLQueryInterface.class); String paramKey = "key"; Map params = new HashMap(); params.put(paramKey, key); - List opts = dbs.findObjectsByProperties(ConfigurationOption.class, params); + List opts = hqi.findObjectsByProperties(ConfigurationOption.class, params); if (opts.isEmpty()) return null; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/DAObject.java b/alitheia/core/src/main/java/eu/sqooss/service/db/DAObject.java index 752e535fb..6fc8aad66 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/DAObject.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/DAObject.java @@ -64,8 +64,8 @@ public abstract class DAObject { * @return */ public static T loadDAObyId(long id, Class type) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); - return dbs.findObjectById(type, id); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); + return qi.findObjectById(type, id); } } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/DBService.java b/alitheia/core/src/main/java/eu/sqooss/service/db/DBService.java index bb63dcd9b..5101b621f 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/DBService.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/DBService.java @@ -34,35 +34,32 @@ package eu.sqooss.service.db; import eu.sqooss.core.AlitheiaCoreService; -import eu.sqooss.service.db.DAObject; import eu.sqooss.service.logging.Logger; -import java.sql.SQLException; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.hibernate.QueryException; - /** * This is the service providing access to the Alitheia Database, * including project metadata, user management, metrics data... * + * The responsibilities of the DBService are split into multiple interfaces to increase + * cohesion and to narrow down dependencies from other classes. + * * The API includes methods for retrieving data access objects (DAO) by id or by properties, - * and adding/deleting records in the database, and general-purpose querying methods - * for lower-level database access. + * and adding/deleting records in the database, through the QueryInterface provided by the + * getQueryInterface() method. General-purpose querying methods for lower-level database access + * are available through other QueryInterfaces, most notably the HQLQueryInterface. * Access and manipulation of the data is done directly through the DAOs in an object-oriented way. * * All access to the DB service has to be done in the context of a session. You can see the session - * as the connection to the database and the transaction for that connection. - * The method startDBSession() initialises a session, while commitDBSession() and rollbackDBSession() + * as the connection to the database and the transaction for that connection. Methods for database + * session management are provided by the DBSessionManager, obtained through the getSessionManager() + * method. The method startDBSession() initialises a session, while commitDBSession() and rollbackDBSession() * end the session, by committing or cancelling the changes respectively. * You can also query the current state of the session with the method isDBSessionActive(). * - * All the methods in this interface are thread-safe, which means you can call these methods on the - * same DBService object from different threads without needed to protect the access to the object. - * Furthermore, each session is handled within the context of a thread. So if two different threads + * All the methods in this interface and exposed interfaces are thread-safe, which means you can call + * these methods on the same DBService object from different threads without needed to protect the access + * to the object. Furthermore, each session is handled within the context of a thread. So if two different threads * have code that call startDBSession(), they will each start their own, and whatever they do during * the session will be isolated from the other. (ie. no DAO sharing, no changes visible accross threads...) * @@ -80,412 +77,50 @@ * @author Romain Pokrzywka * */ -public interface DBService extends AlitheiaCoreService { - - /** - * Starts a new work session with the DBService for the current thread. - * This method should be called before any other method from DBService, to ensure all resources - * are properly set up and ready, such as database connection, active transaction... - * (the only exception is doSQL, which manages the session internally) - * Only one session per thread can be active at a time, so calling startDBSession with a - * previously started session in the same thread has no effect and will assume usage - * of the existing session. (e.g. if a previous session was not closed properly) - * - * This method is thread-safe, and it creates session for a specific thread only. - * It will also start a database transaction, ensuring that only the current thread has access - * to the database for the duration of the session, therefore simplifying concurrency issues. - * - * @return true if the session was correctly started ; - * false if a session was already started for this thread, - * or if the session couldn't be started - */ - public boolean startDBSession(); - - /** - * Commits the changes made in the current work session into the database and closes the session, - * also releasing the transaction lock on the database. - * - * This method is thread-safe, and it will always close the current session (if any) - * and release any lock on the database, even if an error occurs. - * - * @return true if the commit was successful and the session correctly closed, - * false if there was no active session or if an error occured. - */ - public boolean commitDBSession(); - - /** - * Closes the current work session without committing the changes into the database, - * also releasing the transaction lock on the database. - * - * Note that any DAOs loaded and modified during the session will NOT be reset to - * their state at load-time. In other words, modifications to the DAOs are NOT cancelled, - * however these modifications will not be persisted in the database. - * - * This method is thread-safe, and it will always close the current session (if any) - * and release any lock on the database, even if an error occurs. - * - * @return true if the session was correctly closed, - * false if there was no active session or if an error occured. - */ - public boolean rollbackDBSession(); - - /** - * Flush the current changes in the session to the database and clears the session cache. - * Note that the transaction isn't committed though, so changes will only be visible - * to the current session. - * @return true if the session was correctly flushed, - * false if there was no active session or if an error occured. - */ - public boolean flushDBSession(); - - /** - * Returns the state of the work session for the current thread. - * @return true if a session was started and is still active, - * false otherwise - */ - public boolean isDBSessionActive(); +public interface DBService extends AlitheiaCoreService { - /** - * A generic query method to retrieve a single DAObject subclass using its identifier. - * The return value is parameterized to the actual type of DAObject queried - * so no downcast is needed. - * @param daoClass the actual class of the DAObject. - * @param id the DAObject's identifier - * @return the DAOObject if a match for the class and the identifier was found in the database, - * or null otherwise or if a database access error occured - */ - public T findObjectById(Class daoClass, long id); - - /** - * A generic query method to retrieve a single DAObject subclass using its identifier and - * acquire a pessimistic row-level database lock on it. - * This results in an SQL query with the form "SELECT ... FOR UPDATE". - * You may use this method to ensure that no other session can modify the returned object - * while the current session is active. This can help avoiding database-level deadlocks - * when multiple sessions access and modify the same table in parallel. - * The return value is parameterized to the actual type of DAObject queried - * so no downcast is needed. - * @param daoClass the actual class of the DAObject. - * @param id the DAObject's identifier - * @return the DAOObject if a match for the class and the identifier was found in the database, - * or null otherwise or if a database access error occured - */ - public T findObjectByIdForUpdate(Class daoClass, long id); - - /** - * A generic query method to retrieve a list of DAObjects of a same subclass - * matching a set of properties. - * The returned list contains the objects matching all of the properties specified. - * It is parameterized to the actual type of DAObject queried so no downcast is needed. - * The map key should be the property name as a string, and the value should be a value - * with a matching type for the property. For example, if a class has a String property - * called name (ie. a getName()/setName() accessor pair), then you would use "name" as - * the map key and a String object as the map value. - * If any property in the map isn't valid (either an unknown name or a value of the wrong type) - * the call will fail and an empty list will be returned. - * It uses its own session. - * - * @param daoClass the actual class of the DAObjects - * @param properties a map of property name/value pairs corresponding to properties - * of the DAObject subclass - * @return a list of DAObjects matching the class and the set of properties, - * possibly empty if no match was found in the database or if the properties map - * contains invalid entries or if a database access error occured - */ - public List findObjectsByProperties(Class daoClass, - Map properties ); - - /** - * A generic query method to retrieve a list of DAObjects of a same subclass - * matching a set of properties and acquire a pessimistic row-level database lock - * on each returned object in the list. - * This results in an SQL query with the form "SELECT ... FOR UPDATE". - * You may use this method to ensure that no other session can modify the returned objects - * while the current session is active. This can help avoiding database-level deadlocks - * when multiple sessions access and modify the same table in parallel. - * The returned list contains the objects matching all of the properties specified. - * It is parameterized to the actual type of DAObject queried so no downcast is needed. - * The map key should be the property name as a string, and the value should be a value - * with a matching type for the property. For example, if a class has a String property - * called name (ie. a getName()/setName() accessor pair), then you would use "name" as - * the map key and a String object as the map value. - * If any property in the map isn't valid (either an unknown name or a value of the wrong type) - * the call will fail and an empty list will be returned. - * It uses its own session. - * - * @param daoClass the actual class of the DAObjects - * @param properties a map of property name/value pairs corresponding to properties - * of the DAObject subclass - * @return a list of DAObjects matching the class and the set of properties, - * possibly empty if no match was found in the database or if the properties map - * contains invalid entries or if a database access error occured - */ - public List findObjectsByPropertiesForUpdate(Class daoClass, - Map properties ); - - /** - * Add a new record to the database, including all the associations the record may contain. - * - * @param record the record to persist into the database - * @return true if the record insertion succeeded, false otherwise - */ - public boolean addRecord(DAObject record); /** - * Add multiple new records to the database. - * - * @param records the list of records to persist into the database - * @return true if all the record insertions succeeded, false otherwise - */ - public boolean addRecords(List records); - - /** - * Delete an existing record from the database. - * - * @param record the record to remove from the database - * @return true if the record deletion succeeded, false otherwise - */ - public boolean deleteRecord(DAObject record); - - /** - * Delete multiple existing records from the database. - * - * @param records the list of records to remove from the database - * @return true if all the record deletions succeeded, false otherwise - */ - public boolean deleteRecords(List records); - - /** - * Attach a disconnected object to the current Session. If the corresponding - * row exists, then the returned object will merge the persistent and - * the disconnected object fields. Preference will be given to the field - * values of the detached object. If the detached object contains - * references to other DAOs, the attach operation will cascade. - * - * WARNING : the attached DAO is the returned object, NOT the one you passed as argument ! - * - * @param obj the object to connect - * @return the connected instance of the object - */ - public T attachObjectToDBSession(T obj); - - /** - * Execute a complete SQL query to the database. - * This allows low-level manipulation of the database contents outside of the DAO types. - * To limit risks of SQL injection exploits, please do not execute queries like - * "SELECT * FROM " + tableName. - * If you need dynamic SQL queries, please use the overload with the params argument. - * - * @param sql the sql query string - * @return a list of records. If the query contains multiple columns, - * the results are returned in an instance of Object[] - * @throws SQLException if the query is invalid or a database access error occurs - * - * @see doSQL(String sql, Map params) - * @deprecated - */ - @Deprecated - public List doSQL(String sql) - throws SQLException; - - /** - * Execute a parameterized SQL query to the database. - * This allows low-level manipulation of the database contents outside of the DAO types. - * - * @param sql the sql query string - * @param params the map of parameters to be substituted in the SQL query - * @return a list of records. If the query contains multiple columns, - * the results are returned in an instance of Object[] - * @throws SQLException if the query is invalid or a database access error occurs - * @throws QueryException if some parameters are missing - * @deprecated - */ - @Deprecated - public List doSQL(String sql, Map params) - throws SQLException, QueryException; - - /** - * Execute a named stored procedure. Stored procedures in general should be - * avoided as much as possible as they harm portability and this is why - * this method is marked as deprecated. For the same reason this method only - * returns an integer and not a cursor, as one should expect. - * In some cases however, e.g. when doing large batch updates or when - * moving large volumes, stored procedures can speed up things. To maintain - * portability, there must always be an alternative execution path that - * does not involve calling a stored procedure. - * - * @param sql The name of the procedure to call (case sensitive) - * @param arglist Names for the stored procedure arguments, order must be the - * same as in the stored procedure itself. - * @param params The map of parameters to be substituted in the SQL query - * @return The number of rows affected by the execution of the procedure. - * @throws SQLException if the stored procedure execution fails for some reason. - * @throws QueryException if some parameters are missing - * @deprecated + * Get the logger used by the DB service, to log something DB specific. + * This is the prefered method for DAOs to log things. */ - @Deprecated - public int callProcedure(String procName, List arglist, Map params) - throws SQLException, QueryException; + public Logger logger(); /** - * Execute a complete HQL query to the database. - * To limit risks of HQL injection exploits, please do not execute queries like - * "FROM " + objectClass. - * If you need dynamic HQL queries, please use the overload with the params argument. - * - * @param hql the HQL query string - * @return a list of {@link DAObject}, fetched with a read access lock in the database. - * If the query contains multiple columns, - * the results are returned in an instance of Object[]. - * If the query is invalid or a database access error occurs, - * an empty list will be returned. - * - * @throws QueryException if the query is invalid - * - * @see doHQL(String, Map) + * Get the object responsible for all the session management operations + * like starting, committing and rolling back a database transaction. + * See {@link eu.sqooss.service.db.DBSessionManager}} for more details + * about the available operations. + * @return the instance of the DBSessionManager */ - public List doHQL(String hql) - throws QueryException; + public DBSessionManager getSessionManager(); /** - * Execute a parameterized HQL query to the database. - * - * @param hql the HQL query string - * @param params the map of parameters to be substituted in the HQL query - * @return a list of {@link DAObject}, fetched with a read access lock in the database. - * If the query contains multiple columns, - * the results are returned in an instance of Object[]. - * If the query is invalid or a database access error occurs, - * an empty list will be returned. - * - * @throws QueryException if the query is invalid or if params contains invalid entries - * - * @see doHQL(String, Map, Map) - */ - public List doHQL(String hql, Map params) - throws QueryException; - - /** - * Execute a parameterized HQL query to the database. - * - * @param hql the HQL query string - * @param params the map of parameters to be substituted in the HQL query - * @param limit only retrieve the first n rows - * @return a list of {@link DAObject}, fetched with a read access lock in the database. - * If the query contains multiple columns, - * the results are returned in an instance of Object[] - * If the query is invalid or a database access error occurs, - * an empty list will be returned. - * - * @throws QueryException if the query is invalid or if params contains invalid entries - * - * @see doHQL(String, Map, Map) - */ - public List doHQL(String hql, Map params, int limit) - throws QueryException; - - /** - * Execute a parameterized HQL query to the database. The table whose rows - * should be returned and locked must be aliased as 'foo' for the lock - * mode to work, for example: - *
-     * select foo from Developer as foo, StoredProject sp where foo.project=sp...
-     * 
- * @param hql the HQL query string - * @param params the map of parameters to be substituted in the HQL query - * @param lockForUpdate if true, the generated SQL query will use a "SELECT ... FOR UPDATE" - * statement. Otherwise, a normal "SELECT" will be used. Only one table can be - * locked per query. - * @return a list of {@link DAObject}, with a corresponding lock in the database. - * If the query contains multiple columns, - * the results are returned in an instance of Object[] - * If the query is invalid or a database access error occurs, - * an empty list will be returned. - * - * @throws QueryException if the query is invalid or if params contains invalid entries - * - * @see doHQL(String, Map, Map) - */ - public List doHQL(String hql, Map params, boolean lockForUpdate) - throws QueryException; - - /** - * Execute a parameterized HQL query to the database. - * - * @param hql HQL query string - * @param params the map of parameters to be substituted in the HQL query - * @return a list of {@link DAObject}, fetched with a read access lock in the database. - * If the query contains multiple columns, - * the results are returned in an instance of Object[] - * If the query is invalid or a database access error occurs, - * an empty list will be returned. - * - * @throws QueryException if the query is invalid or if params or collectionParams - * contain invalid entries - */ - public List doHQL(String hql, Map params, - Map collectionParams) - throws QueryException; - - /** - * Execute a parameterized HQL query to the database. - * HQL is very similar to SQL, but differs in a variety of important ways. - * See the hibernate documentation at - * http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html - * for details. As a rule, you do not write 'SELECT *' but only - * 'FROM ' (note: not the table name, the @em class). - * - * The query string may contain named parameters, for which values - * will be substituted from the params and lparams arguments to this - * method. For parameters that expect a single datum, put the mapping - * from name to an object in the params argument. List-based parameters - * (for instance the allowable values in a "IN ( foo, ... )" clause) - * may be placed in the lparams argument. Either may be null if there - * are no paramaters of that kind. - * - * @param hql HQL query string - * @param params the map of parameters to be substituted in the HQL query - * @param lockForUpdate if true, the generated SQL query will use a "SELECT ... FOR UPDATE" - * statement. Otherwise, a normal "SELECT" will be used - * @param start fetch results starting at the specified row - * @param limit only retrieve the specified number of rows - * @return a list of {@link DAObject}, with a corresponding lock in the database. - * If the query contains multiple columns, - * the results are returned in an instance of Object[] - * If the query is invalid or a database access error occurs, - * an empty list will be returned. - * - * @throws QueryException if the query is invalid or if params or collectionParams - * contain invalid entries + * Returns a basic implementation of the QueryInterface used to perform + * simple queries to the database, like adding, deleting and finding + * records. For a complete list of the available operations, see + * {@link eu.sqooss.service.db.QueryInterface}. + * @return a basic QueryInterface instance */ - public List doHQL(String hql, - Map params, - Map collectionParams, - boolean lockForUpdate, - int start, int limit - ) - throws QueryException; + public QueryInterface getQueryInterface(); /** - * Executes a DML-type query. The query forms that HQL supports - * are the following: - *
    - *
  • INSERT INTO ... SELECT ...
  • - *
  • UPDATE ... SET ... WHERE....
  • - *
  • DELETE ... WHERE
  • - *
- * - * @param hql The HQL statement to execute - * @param params the map of parameters to be substituted in the HQL query - * @return The number of rows updated or deleted or -1 in case of error + * This function can be used to retrieve more extended implementations + * of the QueryInterface, for instance an HQLQueryInterface instance. + * @param queryInterfaceType The class of the implementation to be used + * as QueryInterface + * @return an implementation of the QueryInterface interface */ - public int executeUpdate(String hql, Map params); + public T getQueryInterface(Class queryInterfaceType); /** - * Get the logger used by the DB service, to log something DB specific. - * This is the prefered method for DAOs to log things. + * Registers a new QueryInterface by providing a factory that can construct + * an instance of that QueryInterface. + * @param queryInterfaceType the QueryInterface subtype to register + * @param factoryType the QueryInterfaceFactory capable of constructing the QueryInterface */ - public Logger logger(); + public void registerQueryInterface(Class queryInterfaceType, + Class> factoryType); } // vi: ai nosi sw=4 ts=4 expandtab diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionManager.java b/alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionManager.java new file mode 100644 index 000000000..5189669f3 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionManager.java @@ -0,0 +1,84 @@ +package eu.sqooss.service.db; + +/** + * Database service entity that manages the thread-based database sessions. + */ +public interface DBSessionManager { + + /** + * Starts a new work session with the DBService for the current thread. + * This method should be called before any other method from DBService, to ensure all resources + * are properly set up and ready, such as database connection, active transaction... + * Only one session per thread can be active at a time, so calling startDBSession with a + * previously started session in the same thread has no effect and will assume usage + * of the existing session. (e.g. if a previous session was not closed properly) + * + * This method is thread-safe, and it creates session for a specific thread only. + * It will also start a database transaction, ensuring that only the current thread has access + * to the database for the duration of the session, therefore simplifying concurrency issues. + * + * @return true if the session was correctly started ; + * false if a session was already started for this thread, + * or if the session couldn't be started + */ + public boolean startDBSession(); + + /** + * Commits the changes made in the current work session into the database and closes the session, + * also releasing the transaction lock on the database. + * + * This method is thread-safe, and it will always close the current session (if any) + * and release any lock on the database, even if an error occurs. + * + * @return true if the commit was successful and the session correctly closed, + * false if there was no active session or if an error occured. + */ + public boolean commitDBSession(); + + /** + * Closes the current work session without committing the changes into the database, + * also releasing the transaction lock on the database. + * + * Note that any DAOs loaded and modified during the session will NOT be reset to + * their state at load-time. In other words, modifications to the DAOs are NOT cancelled, + * however these modifications will not be persisted in the database. + * + * This method is thread-safe, and it will always close the current session (if any) + * and release any lock on the database, even if an error occurs. + * + * @return true if the session was correctly closed, + * false if there was no active session or if an error occured. + */ + public boolean rollbackDBSession(); + + /** + * Flush the current changes in the session to the database and clears the session cache. + * Note that the transaction isn't committed though, so changes will only be visible + * to the current session. + * @return true if the session was correctly flushed, + * false if there was no active session or if an error occured. + */ + public boolean flushDBSession(); + + /** + * Returns the state of the work session for the current thread. + * @return true if a session was started and is still active, + * false otherwise + */ + public boolean isDBSessionActive(); + + /** + * Attach a disconnected object to the current Session. If the corresponding + * row exists, then the returned object will merge the persistent and + * the disconnected object fields. Preference will be given to the field + * values of the detached object. If the detached object contains + * references to other DAOs, the attach operation will cascade. + * + * WARNING : the attached DAO is the returned object, NOT the one you passed as argument ! + * + * @param obj the object to connect + * @return the connected instance of the object + */ + public T attachObjectToDBSession(T obj); + +} diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionValidation.java b/alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionValidation.java new file mode 100644 index 000000000..8d7855428 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/DBSessionValidation.java @@ -0,0 +1,32 @@ +package eu.sqooss.service.db; + +import java.sql.SQLException; + +public interface DBSessionValidation { + + /** + * Returns the state of the work session for the current thread, while logging + * any access to an inactive session. Should be called whenever a session is + * required to be active. + * + * @return true if a session was started and is still active, + * false otherwise + */ + public boolean checkSession(); + + /** + * Logs a database-related exception and cleans up the database session of the + * current thread, if it exists. + * + * @param e an exception triggering the termination of the active session + */ + public void logExceptionAndTerminateSession(Exception e); + + /** + * Logs an SQL exception. + * + * @param e the exception to be logged + */ + public void logSQLException(SQLException e); + +} diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/Developer.java b/alitheia/core/src/main/java/eu/sqooss/service/db/Developer.java index 26f99af02..12d8ce655 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/Developer.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/Developer.java @@ -235,7 +235,7 @@ public static Developer getDeveloperByEmail(String email, */ public static synchronized Developer getDeveloperByEmail(String email, StoredProject sp, boolean create){ - DBService dbs = AlitheiaCore.getInstance().getDBService(); + HQLQueryInterface hqi = AlitheiaCore.getInstance().getDBService().getQueryInterface(HQLQueryInterface.class); String paramProject = "project"; String paramEmail = "email"; @@ -250,7 +250,7 @@ public static synchronized Developer getDeveloperByEmail(String email, parameterMap.put(paramEmail, email); parameterMap.put(paramProject, sp); - List devs = (List) dbs.doHQL(q.toString(), parameterMap); + List devs = (List) hqi.doHQL(q.toString(), parameterMap); /* Developer in the DB, return it */ if ( !devs.isEmpty() ) @@ -300,7 +300,7 @@ public static synchronized Developer getDeveloperByEmail(String email, d.setStoredProject(sp); /*Failure here probably indicates non-existing StoredProject*/ - if ( !dbs.addRecord(d) ) + if ( !hqi.addRecord(d) ) return null; d.addAlias(email); @@ -342,13 +342,13 @@ public static Developer getDeveloperByUsername(String username, public static synchronized Developer getDeveloperByUsername(String username, StoredProject sp, boolean create) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map parameterMap = new HashMap(); parameterMap.put("username", username); parameterMap.put("storedProject", sp); - List devs = dbs.findObjectsByProperties(Developer.class, + List devs = qi.findObjectsByProperties(Developer.class, parameterMap); /* @@ -365,7 +365,7 @@ public static synchronized Developer getDeveloperByUsername(String username, * only work with certain databases (tested with mysql, postgres and * derby). */ - /*devs = (List) dbs.doHQL("from Developer as foo where email like " + + /*devs = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL("from Developer as foo where email like " + "'%" +username+ "%' and storedProject.id=" + sp.getId() ); for (Developer d : devs) { @@ -389,7 +389,7 @@ public static synchronized Developer getDeveloperByUsername(String username, d.setStoredProject(sp); /*Failure here probably indicates non-existing StoredProject*/ - if (!dbs.addRecord(d)) + if (!qi.addRecord(d)) return null; return d; @@ -408,13 +408,13 @@ public static synchronized Developer getDeveloperByUsername(String username, public static synchronized Developer getDeveloperByName(String name, StoredProject sp, boolean create) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("name", name); params.put("storedProject", sp); - List devs = dbs.findObjectsByProperties(Developer.class,params); + List devs = qi.findObjectsByProperties(Developer.class,params); /* This code assumes that each name is unique in a project*/ if (devs.size() > 0) @@ -425,7 +425,7 @@ public static synchronized Developer getDeveloperByName(String name, Developer d = new Developer(); d.setName(name); - if (!dbs.addRecord(d)) + if (!qi.addRecord(d)) return null; return d; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/Directory.java b/alitheia/core/src/main/java/eu/sqooss/service/db/Directory.java index d84e09068..bad6686e5 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/Directory.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/Directory.java @@ -129,11 +129,11 @@ public boolean isSubDirOf(Directory d) { */ public static synchronized Directory getDirectory(String path, boolean create) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map parameterMap = new HashMap(); parameterMap.put("path", path); - List dirs = dbs.findObjectsByProperties(Directory.class, + List dirs = qi.findObjectsByProperties(Directory.class, parameterMap); /* Dir path in table, return it */ @@ -145,7 +145,7 @@ public static synchronized Directory getDirectory(String path, boolean create) { /* Dir path not in table, create it */ Directory d = new Directory(); d.setPath(path); - if (!dbs.addRecord(d)) { + if (!qi.addRecord(d)) { return null; } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/HQLQueryInterface.java b/alitheia/core/src/main/java/eu/sqooss/service/db/HQLQueryInterface.java new file mode 100644 index 000000000..a835f424a --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/HQLQueryInterface.java @@ -0,0 +1,165 @@ +package eu.sqooss.service.db; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.hibernate.QueryException; + +public interface HQLQueryInterface extends QueryInterface { + + /** + * Execute a complete HQL query to the database. + * To limit risks of HQL injection exploits, please do not execute queries like + * "FROM " + objectClass. + * If you need dynamic HQL queries, please use the overload with the params argument. + * + * @param hql the HQL query string + * @return a list of {@link DAObject}, fetched with a read access lock in the database. + * If the query contains multiple columns, + * the results are returned in an instance of Object[]. + * If the query is invalid or a database access error occurs, + * an empty list will be returned. + * + * @throws QueryException if the query is invalid + * + * @see doHQL(String, Map) + */ + public List doHQL(String hql) + throws QueryException; + + /** + * Execute a parameterized HQL query to the database. + * + * @param hql the HQL query string + * @param params the map of parameters to be substituted in the HQL query + * @return a list of {@link DAObject}, fetched with a read access lock in the database. + * If the query contains multiple columns, + * the results are returned in an instance of Object[]. + * If the query is invalid or a database access error occurs, + * an empty list will be returned. + * + * @throws QueryException if the query is invalid or if params contains invalid entries + * + * @see doHQL(String, Map, Map) + */ + public List doHQL(String hql, Map params) + throws QueryException; + + /** + * Execute a parameterized HQL query to the database. + * + * @param hql the HQL query string + * @param params the map of parameters to be substituted in the HQL query + * @param limit only retrieve the first n rows + * @return a list of {@link DAObject}, fetched with a read access lock in the database. + * If the query contains multiple columns, + * the results are returned in an instance of Object[] + * If the query is invalid or a database access error occurs, + * an empty list will be returned. + * + * @throws QueryException if the query is invalid or if params contains invalid entries + * + * @see doHQL(String, Map, Map) + */ + public List doHQL(String hql, Map params, int limit) + throws QueryException; + + /** + * Execute a parameterized HQL query to the database. The table whose rows + * should be returned and locked must be aliased as 'foo' for the lock + * mode to work, for example: + *
+     * select foo from Developer as foo, StoredProject sp where foo.project=sp...
+     * 
+ * @param hql the HQL query string + * @param params the map of parameters to be substituted in the HQL query + * @param lockForUpdate if true, the generated SQL query will use a "SELECT ... FOR UPDATE" + * statement. Otherwise, a normal "SELECT" will be used. Only one table can be + * locked per query. + * @return a list of {@link DAObject}, with a corresponding lock in the database. + * If the query contains multiple columns, + * the results are returned in an instance of Object[] + * If the query is invalid or a database access error occurs, + * an empty list will be returned. + * + * @throws QueryException if the query is invalid or if params contains invalid entries + * + * @see doHQL(String, Map, Map) + */ + public List doHQL(String hql, Map params, boolean lockForUpdate) + throws QueryException; + + /** + * Execute a parameterized HQL query to the database. + * + * @param hql HQL query string + * @param params the map of parameters to be substituted in the HQL query + * @return a list of {@link DAObject}, fetched with a read access lock in the database. + * If the query contains multiple columns, + * the results are returned in an instance of Object[] + * If the query is invalid or a database access error occurs, + * an empty list will be returned. + * + * @throws QueryException if the query is invalid or if params or collectionParams + * contain invalid entries + */ + public List doHQL(String hql, Map params, + Map collectionParams) + throws QueryException; + + /** + * Execute a parameterized HQL query to the database. + * HQL is very similar to SQL, but differs in a variety of important ways. + * See the hibernate documentation at + * http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html + * for details. As a rule, you do not write 'SELECT *' but only + * 'FROM ' (note: not the table name, the @em class). + * + * The query string may contain named parameters, for which values + * will be substituted from the params and lparams arguments to this + * method. For parameters that expect a single datum, put the mapping + * from name to an object in the params argument. List-based parameters + * (for instance the allowable values in a "IN ( foo, ... )" clause) + * may be placed in the lparams argument. Either may be null if there + * are no paramaters of that kind. + * + * @param hql HQL query string + * @param params the map of parameters to be substituted in the HQL query + * @param lockForUpdate if true, the generated SQL query will use a "SELECT ... FOR UPDATE" + * statement. Otherwise, a normal "SELECT" will be used + * @param start fetch results starting at the specified row + * @param limit only retrieve the specified number of rows + * @return a list of {@link DAObject}, with a corresponding lock in the database. + * If the query contains multiple columns, + * the results are returned in an instance of Object[] + * If the query is invalid or a database access error occurs, + * an empty list will be returned. + * + * @throws QueryException if the query is invalid or if params or collectionParams + * contain invalid entries + */ + public List doHQL(String hql, + Map params, + Map collectionParams, + boolean lockForUpdate, + int start, int limit + ) + throws QueryException; + + /** + * Executes a DML-type query. The query forms that HQL supports + * are the following: + *
    + *
  • INSERT INTO ... SELECT ...
  • + *
  • UPDATE ... SET ... WHERE....
  • + *
  • DELETE ... WHERE
  • + *
+ * + * @param hql The HQL statement to execute + * @param params the map of parameters to be substituted in the HQL query + * @return The number of rows updated or deleted or -1 in case of error + */ + public int executeUpdate(String hql, Map params); + +} diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/MailMessage.java b/alitheia/core/src/main/java/eu/sqooss/service/db/MailMessage.java index dfffa7edc..2792755f2 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/MailMessage.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/MailMessage.java @@ -231,10 +231,10 @@ public Set getMeasurements() { * Return a stored mail message based on messageId */ public static MailMessage getMessageById(String messageId) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map properties = new HashMap(1); properties.put("messageId", messageId); - List msgList = dbs.findObjectsByProperties(MailMessage.class, properties); + List msgList = qi.findObjectsByProperties(MailMessage.class, properties); if ((msgList == null) || (msgList.isEmpty())) { return null; @@ -247,10 +247,10 @@ public static MailMessage getMessageById(String messageId) { * Return a stored mail message based on filename */ public static MailMessage getMessageByFileName(String filename) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map properties = new HashMap(1); properties.put("fileName", filename); - List msgList = dbs.findObjectsByProperties(MailMessage.class, properties); + List msgList = qi.findObjectsByProperties(MailMessage.class, properties); if ((msgList == null) || (msgList.isEmpty())) { return null; @@ -275,7 +275,7 @@ public static MailMessage getLatestMailMessage(StoredProject sp) { Map params = new HashMap(); params.put(paramStoredProject, sp); - List mm = (List) dbs.doHQL(query, params, 1); + List mm = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params, 1); if (!mm.isEmpty()) return mm.get(0); diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/MailingList.java b/alitheia/core/src/main/java/eu/sqooss/service/db/MailingList.java index 1b92720cc..d10883ae4 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/MailingList.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/MailingList.java @@ -161,7 +161,7 @@ public List getMessagesNewerThan(Date d) { params.put(paramDate, d); params.put(paramMailingList, this); - List msgs = (List) dbs.doHQL(query, params); + List msgs = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params); if (msgs == null || msgs.size() == 0) return Collections.emptyList(); @@ -187,7 +187,7 @@ public MailMessage getLatestEmail() { params.put(paramMailingList, this); - List ml = (List) dbs.doHQL(query, params, 1); + List ml = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params, 1); if (ml.isEmpty()) return null; @@ -212,7 +212,7 @@ public MailingListThread getLatestThread() { Map params = new HashMap(); params.put(paramMailingList, this); - List ml = (List) dbs.doHQL(query, params, 1); + List ml = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params, 1); if (ml.isEmpty()) return null; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/MailingListThread.java b/alitheia/core/src/main/java/eu/sqooss/service/db/MailingListThread.java index 791eda19c..733261e06 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/MailingListThread.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/MailingListThread.java @@ -155,13 +155,13 @@ public void setLastUpdated(Date lastUpdated) { */ public MailMessage getStartingEmail() { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("thread", this); params.put("depth", 0); - List mm = dbs.findObjectsByProperties(MailMessage.class, + List mm = qi.findObjectsByProperties(MailMessage.class, params); if (!mm.isEmpty()) @@ -188,7 +188,7 @@ public List getMessagesByArrivalOrder() { Map params = new HashMap(1); params.put(paramThread, this); - List mm = (List) dbs.doHQL(query, params); + List mm = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params); if (mm == null || mm.isEmpty()) return Collections.emptyList(); @@ -212,7 +212,7 @@ public int getThreadDepth() { Map params = new HashMap(1); params.put(paramThread, this); - List mm = (List) dbs.doHQL(query, params, 1); + List mm = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params, 1); if (mm == null || mm.isEmpty()) return 0; @@ -243,7 +243,7 @@ public List getMessagesAtLevel(int level) { params.put(paramThread, this); params.put(paramDepth, level); - List mm = (List) dbs.doHQL(query, params); + List mm = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params); if (mm == null || mm.isEmpty()) return Collections.emptyList(); diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/Metric.java b/alitheia/core/src/main/java/eu/sqooss/service/db/Metric.java index a3b9d8bb0..33cb09a1f 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/Metric.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/Metric.java @@ -302,7 +302,7 @@ public boolean isEvaluated (StoredProject p) { params.put("project", p); params.put("metric", this); - if (dbs.doHQL(query.toString(), params, 1).size() >= 1) + if (dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query.toString(), params, 1).size() >= 1) return true; return false; @@ -343,12 +343,12 @@ public String toString() { * provided mnemonic */ public static Metric getMetricByMnemonic(String mnem) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map properties = new HashMap(); properties.put("mnemonic", mnem); - List result = dbs.findObjectsByProperties(Metric.class, + List result = qi.findObjectsByProperties(Metric.class, properties); if (result.size() <= 0) @@ -365,7 +365,7 @@ public static Metric getMetricByMnemonic(String mnem) { */ public static List getAllMetrics() { DBService dbs = AlitheiaCore.getInstance().getDBService(); - return (List) dbs.doHQL("from Metric"); + return (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL("from Metric"); } } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/MetricType.java b/alitheia/core/src/main/java/eu/sqooss/service/db/MetricType.java index 5b8d0721a..da8cd35c9 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/MetricType.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/MetricType.java @@ -169,10 +169,10 @@ public void setMetrics(Set metrics) { * @return A MetricType DAO representing the metric type */ public static MetricType getMetricType(Type t) { - DBService db = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); HashMap s = new HashMap(); s.put("type", t.toString()); - List result = db.findObjectsByProperties(MetricType.class, s); + List result = qi.findObjectsByProperties(MetricType.class, s); if (result.isEmpty()) { return null; } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/NameSpace.java b/alitheia/core/src/main/java/eu/sqooss/service/db/NameSpace.java index 56360d423..254cfaa51 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/NameSpace.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/NameSpace.java @@ -156,7 +156,7 @@ public static NameSpace findByVersionName(ProjectVersion pv, String name) { params.put("pv", pv); params.put("name", name); - List ns = (List) dbs.doHQL(nsByVersion, params); + List ns = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(nsByVersion, params); if (ns.isEmpty()) return null; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/OhlohDeveloper.java b/alitheia/core/src/main/java/eu/sqooss/service/db/OhlohDeveloper.java index 6403bbf5a..14294a5aa 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/OhlohDeveloper.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/OhlohDeveloper.java @@ -144,17 +144,17 @@ public static OhlohDeveloper getByEmailHash(String hash) { } public static List getByUserName(String uname) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("uname", uname); - return dbs.findObjectsByProperties(OhlohDeveloper.class, params); + return qi.findObjectsByProperties(OhlohDeveloper.class, params); } private static OhlohDeveloper getBy(String name, String value) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put(name, value); - List l = dbs.findObjectsByProperties(OhlohDeveloper.class, params); + List l = qi.findObjectsByProperties(OhlohDeveloper.class, params); if (!l.isEmpty()) return l.get(0); diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/Plugin.java b/alitheia/core/src/main/java/eu/sqooss/service/db/Plugin.java index a1529a2df..424c5501a 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/Plugin.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/Plugin.java @@ -189,10 +189,10 @@ public void setSupportedMetrics(Set supportedMetrics) { } public static List getPluginByName(String name) { - DBService db = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); HashMap s = new HashMap(); s.put("name", name); - return db.findObjectsByProperties(Plugin.class, s); + return qi.findObjectsByProperties(Plugin.class, s); } /** @@ -207,10 +207,10 @@ public static List getPluginByName(String name) { * otherwise */ public static Plugin getPluginByHashcode(String hashcode) { - DBService db = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); HashMap s = new HashMap(); s.put("hashcode", hashcode); - List l = db.findObjectsByProperties(Plugin.class, s); + List l = qi.findObjectsByProperties(Plugin.class, s); if (!l.isEmpty()) return l.get(0); diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/PluginConfiguration.java b/alitheia/core/src/main/java/eu/sqooss/service/db/PluginConfiguration.java index 5456f9885..ba11871f1 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/PluginConfiguration.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/PluginConfiguration.java @@ -126,11 +126,11 @@ public void setMsg(String msg) { * Get a PluginConfiguration entry DAO or null in */ public static PluginConfiguration getConfigurationEntry(Plugin p, HashMap names) { - DBService db = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); names.put("plugin", p); - List l = db.findObjectsByProperties(PluginConfiguration.class, names); + List l = qi.findObjectsByProperties(PluginConfiguration.class, names); if(l.isEmpty()) { return null; @@ -145,7 +145,7 @@ public static PluginConfiguration getConfigurationEntry(Plugin p, HashMap names) { - DBService db = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); PluginConfiguration pc = getConfigurationEntry(p, names); if (pc == null) { @@ -156,7 +156,7 @@ public static boolean updConfigurationEntry(Plugin p, HashMap na names.put("plugin", p); - List l = db.findObjectsByProperties(PluginConfiguration.class, s); + List l = qi.findObjectsByProperties(PluginConfiguration.class, s); if (l.isEmpty()) { return false; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFile.java b/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFile.java index 399ae78ad..d73554048 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFile.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFile.java @@ -368,11 +368,11 @@ public String getFileName() { */ public Directory toDirectory() { if ((isDirectory) && (getFileName() != null)) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map props = new HashMap(); props.put("path", getFileName()); List matches = - dbs.findObjectsByProperties(Directory.class, props); + qi.findObjectsByProperties(Directory.class, props); if ((matches != null) && (matches.size() > 0)) return matches.get(0); } @@ -410,7 +410,7 @@ public ProjectFile getPreviousFileVersion() { parameters.put("paramCopyFromName", this.getCopyFrom().getName()); parameters.put("paramCopyFromDir", this.getCopyFrom().getDir().getId()); } - List projectFiles = dbs.doHQL(query, parameters, 1); + List projectFiles = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters, 1); if (projectFiles.size() == 0) { dbs.logger().warn("No previous versions for " + this + @@ -481,7 +481,7 @@ public static ProjectVersion getDeletionVersion(ProjectFile pf) { params.put(paramProject, pf.getProjectVersion().getProject()); params.put(paramOrder, pf.getProjectVersion().getSequence()); - List pvs = (List) db.doHQL(query, params); + List pvs = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(query, params); if (pvs.size() <= 0) return null; @@ -525,7 +525,7 @@ public ProjectFile getEnclosingDirectory() { params.put(paramIsDir, true); params.put(paramSequence, this.getProjectVersion().getSequence()); - List pfs = (List) db.doHQL(query, params, 1); + List pfs = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(query, params, 1); if (pfs.size() <= 0) return null; @@ -563,7 +563,7 @@ public static List getFileModifications(ProjectFile pf) { parameters.put(paramDir, pf.getDir()); parameters.put(paramProject, pf.getProjectVersion().getProject()); - return (List) dbs.doHQL(query, parameters); + return (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters); } /** @@ -634,7 +634,7 @@ public static ProjectFile findFile(Long projectId, String name, parameters.put(paramPath, path); parameters.put(paramVersion, version); - pfs = (List) dbs.doHQL(query.toString(), parameters, 1); + pfs = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query.toString(), parameters, 1); if (pfs.isEmpty()) return null; @@ -647,7 +647,7 @@ public List getChangedExecutionUnits() { Map params = new HashMap(); params.put("file", this); - return (List)dbs.doHQL(qChangedMethods, params); + return (List)dbs.getQueryInterface(HQLQueryInterface.class).doHQL(qChangedMethods, params); } public String toString() { diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFileState.java b/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFileState.java index 612da0404..15849934e 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFileState.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectFileState.java @@ -119,14 +119,15 @@ public static ProjectFileState replaced() { } public static ProjectFileState fromStatus(int status) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = dbs.getQueryInterface(); - if (!dbs.isDBSessionActive()) + if (!dbs.getSessionManager().isDBSessionActive()) return null; Map params = new HashMap(); params.put("status", status); - List pfs = dbs.findObjectsByProperties( + List pfs = qi.findObjectsByProperties( ProjectFileState.class, params); if (!pfs.isEmpty()) { @@ -136,7 +137,7 @@ public static ProjectFileState fromStatus(int status) { ProjectFileState state = new ProjectFileState(); state.setStatus(status); - dbs.addRecord(state); + qi.addRecord(state); return fromStatus(status); } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectVersion.java b/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectVersion.java index f32cebc48..56c72e8e5 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectVersion.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/ProjectVersion.java @@ -460,7 +460,7 @@ public ProjectVersion getPreviousVersion() { parameters.put(paramOrder, this.getSequence()); parameters.put(paramProject, this.getProject().getId()); - List projectVersions = dbs.doHQL(query, parameters, 1); + List projectVersions = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters, 1); if(projectVersions == null || projectVersions.size() == 0) { return null; @@ -491,7 +491,7 @@ public ProjectVersion getNextVersion() { parameters.put(paramTS, this.getSequence()); parameters.put(paramProject, this.getProject().getId()); - List projectVersions = dbs.doHQL(query, parameters, 1); + List projectVersions = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters, 1); if(projectVersions == null || projectVersions.size() == 0) { return null; @@ -514,13 +514,13 @@ public ProjectVersion getNextVersion() { * or null if there is none. */ public static ProjectVersion getVersionByRevision(StoredProject project, String revisionId) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map parameters = new HashMap(); parameters.put("project", project); parameters.put("revisionId", revisionId); - List versions = dbs.findObjectsByProperties(ProjectVersion.class, parameters); + List versions = qi.findObjectsByProperties(ProjectVersion.class, parameters); if (versions == null || versions.size() == 0) { return null; } else { @@ -547,13 +547,13 @@ public static ProjectVersion getVersionByRevision(StoredProject project, String */ public static ProjectVersion getVersionByTimestamp( StoredProject project, long timestamp) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map parameters = new HashMap(); parameters.put("project", project); parameters.put("timestamp", timestamp); - List versions = dbs.findObjectsByProperties( + List versions = qi.findObjectsByProperties( ProjectVersion.class, parameters); if (versions == null || versions.size() == 0) { return null; @@ -575,7 +575,7 @@ public static ProjectVersion getFirstProjectVersion(StoredProject sp) { Map parameterMap = new HashMap(); parameterMap.put("sp", sp); - List pvList = dbs.doHQL("from ProjectVersion pv where pv.project=:sp" + List pvList = dbs.getQueryInterface(HQLQueryInterface.class).doHQL("from ProjectVersion pv where pv.project=:sp" + " and pv.sequence = 1", parameterMap); @@ -594,7 +594,7 @@ public static ProjectVersion getLastProjectVersion(StoredProject sp) { Map parameterMap = new HashMap(); parameterMap.put("sp", sp); - List pvList = dbs.doHQL("from ProjectVersion pv where pv.project=:sp" + List pvList = dbs.getQueryInterface(HQLQueryInterface.class).doHQL("from ProjectVersion pv where pv.project=:sp" + " and pv.sequence = (select max(pv2.sequence) from " + " ProjectVersion pv2 where pv2.project=:sp)", parameterMap); @@ -622,7 +622,7 @@ public static ProjectVersion getLastMeasuredVersion(Metric m, StoredProject p) { params.put("metric", m); params.put("project", p); List pv = (List) - AlitheiaCore.getInstance().getDBService().doHQL( query, params, 1); + AlitheiaCore.getInstance().getDBService().getQueryInterface(HQLQueryInterface.class).doHQL( query, params, 1); if (pv.isEmpty()) return null; @@ -651,7 +651,7 @@ public long getFilesCount(ProjectFileState state) { Map parameters = new HashMap(); parameters.put(parVersionId, this); parameters.put(parFileStatus, state); - List queryResult = dbs.doHQL(query, parameters); + List queryResult = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters); // Return the query's result (if found) if(queryResult != null || queryResult.size() > 0) return (Long) queryResult.get(0); @@ -700,7 +700,7 @@ public long getLiveFilesCount() { params.put(paramIsDirectory, Boolean.FALSE); params.put(paramState, ProjectFileState.deleted()); - return (Long) dbs.doHQL(q.toString(), params).get(0); + return (Long) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(), params).get(0); } @@ -762,7 +762,7 @@ private List getVersionFiles(Directory d, int mask) { params.put(paramIsDirectory, isDirectory); } - List projectFiles = (List) dbs.doHQL(q.toString(), params); + List projectFiles = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(), params); if (projectFiles == null) return Collections.emptyList(); @@ -876,11 +876,11 @@ public List allFiles() { * Return true if this version's actions generated a tag. */ public boolean isTag() { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map props = new HashMap(); props.put("projectVersion", this); - List tags = dbs.findObjectsByProperties(Tag.class, props); + List tags = qi.findObjectsByProperties(Tag.class, props); if (tags.isEmpty()) return false; diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterface.java b/alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterface.java new file mode 100644 index 000000000..65abb0726 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterface.java @@ -0,0 +1,118 @@ +package eu.sqooss.service.db; + +import java.util.List; +import java.util.Map; + +public interface QueryInterface { + + /** + * A generic query method to retrieve a single DAObject subclass using its identifier. + * The return value is parameterized to the actual type of DAObject queried + * so no downcast is needed. + * @param daoClass the actual class of the DAObject. + * @param id the DAObject's identifier + * @return the DAOObject if a match for the class and the identifier was found in the database, + * or null otherwise or if a database access error occured + */ + public T findObjectById(Class daoClass, long id); + + /** + * A generic query method to retrieve a single DAObject subclass using its identifier and + * acquire a pessimistic row-level database lock on it. + * This results in an SQL query with the form "SELECT ... FOR UPDATE". + * You may use this method to ensure that no other session can modify the returned object + * while the current session is active. This can help avoiding database-level deadlocks + * when multiple sessions access and modify the same table in parallel. + * The return value is parameterized to the actual type of DAObject queried + * so no downcast is needed. + * @param daoClass the actual class of the DAObject. + * @param id the DAObject's identifier + * @return the DAOObject if a match for the class and the identifier was found in the database, + * or null otherwise or if a database access error occured + */ + public T findObjectByIdForUpdate(Class daoClass, long id); + + /** + * A generic query method to retrieve a list of DAObjects of a same subclass + * matching a set of properties. + * The returned list contains the objects matching all of the properties specified. + * It is parameterized to the actual type of DAObject queried so no downcast is needed. + * The map key should be the property name as a string, and the value should be a value + * with a matching type for the property. For example, if a class has a String property + * called name (ie. a getName()/setName() accessor pair), then you would use "name" as + * the map key and a String object as the map value. + * If any property in the map isn't valid (either an unknown name or a value of the wrong type) + * the call will fail and an empty list will be returned. + * It uses its own session. + * + * @param daoClass the actual class of the DAObjects + * @param properties a map of property name/value pairs corresponding to properties + * of the DAObject subclass + * @return a list of DAObjects matching the class and the set of properties, + * possibly empty if no match was found in the database or if the properties map + * contains invalid entries or if a database access error occured + */ + public List findObjectsByProperties(Class daoClass, + Map properties ); + + /** + * A generic query method to retrieve a list of DAObjects of a same subclass + * matching a set of properties and acquire a pessimistic row-level database lock + * on each returned object in the list. + * This results in an SQL query with the form "SELECT ... FOR UPDATE". + * You may use this method to ensure that no other session can modify the returned objects + * while the current session is active. This can help avoiding database-level deadlocks + * when multiple sessions access and modify the same table in parallel. + * The returned list contains the objects matching all of the properties specified. + * It is parameterized to the actual type of DAObject queried so no downcast is needed. + * The map key should be the property name as a string, and the value should be a value + * with a matching type for the property. For example, if a class has a String property + * called name (ie. a getName()/setName() accessor pair), then you would use "name" as + * the map key and a String object as the map value. + * If any property in the map isn't valid (either an unknown name or a value of the wrong type) + * the call will fail and an empty list will be returned. + * It uses its own session. + * + * @param daoClass the actual class of the DAObjects + * @param properties a map of property name/value pairs corresponding to properties + * of the DAObject subclass + * @return a list of DAObjects matching the class and the set of properties, + * possibly empty if no match was found in the database or if the properties map + * contains invalid entries or if a database access error occured + */ + public List findObjectsByPropertiesForUpdate(Class daoClass, + Map properties ); + + /** + * Add a new record to the database, including all the associations the record may contain. + * + * @param record the record to persist into the database + * @return true if the record insertion succeeded, false otherwise + */ + public boolean addRecord(DAObject record); + + /** + * Add multiple new records to the database. + * + * @param records the list of records to persist into the database + * @return true if all the record insertions succeeded, false otherwise + */ + public boolean addRecords(List records); + + /** + * Delete an existing record from the database. + * + * @param record the record to remove from the database + * @return true if the record deletion succeeded, false otherwise + */ + public boolean deleteRecord(DAObject record); + + /** + * Delete multiple existing records from the database. + * + * @param records the list of records to remove from the database + * @return true if all the record deletions succeeded, false otherwise + */ + public boolean deleteRecords(List records); + +} diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterfaceFactory.java b/alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterfaceFactory.java new file mode 100644 index 000000000..cfc7eaea4 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/QueryInterfaceFactory.java @@ -0,0 +1,18 @@ +package eu.sqooss.service.db; + +import org.hibernate.SessionFactory; + +public interface QueryInterfaceFactory { + + /** + * Constructs a new QueryInterface of type T, with references to internal + * database structures. + * @param dbService the database service + * @param sessionFactory the Hibernate session factory + * @param sessionValidation the database error handling interface + * @return a new QueryInterface + */ + public T build(DBService dbService, SessionFactory sessionFactory, + DBSessionValidation sessionValidation); + +} diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/SQLQueryInterface.java b/alitheia/core/src/main/java/eu/sqooss/service/db/SQLQueryInterface.java new file mode 100644 index 000000000..236778916 --- /dev/null +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/SQLQueryInterface.java @@ -0,0 +1,73 @@ +package eu.sqooss.service.db; + +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +import org.hibernate.QueryException; + +/** + * NOTE: This QueryInterface is deprecated in favor of HQLQueryInterface. + */ +@Deprecated +public interface SQLQueryInterface extends QueryInterface { + + /** + * Execute a complete SQL query to the database. + * This allows low-level manipulation of the database contents outside of the DAO types. + * To limit risks of SQL injection exploits, please do not execute queries like + * "SELECT * FROM " + tableName. + * If you need dynamic SQL queries, please use the overload with the params argument. + * + * @param sql the sql query string + * @return a list of records. If the query contains multiple columns, + * the results are returned in an instance of Object[] + * @throws SQLException if the query is invalid or a database access error occurs + * + * @see doSQL(String sql, Map params) + * @deprecated + */ + @Deprecated + public List doSQL(String sql) + throws SQLException; + + /** + * Execute a parameterized SQL query to the database. + * This allows low-level manipulation of the database contents outside of the DAO types. + * + * @param sql the sql query string + * @param params the map of parameters to be substituted in the SQL query + * @return a list of records. If the query contains multiple columns, + * the results are returned in an instance of Object[] + * @throws SQLException if the query is invalid or a database access error occurs + * @throws QueryException if some parameters are missing + * @deprecated + */ + @Deprecated + public List doSQL(String sql, Map params) + throws SQLException, QueryException; + + /** + * Execute a named stored procedure. Stored procedures in general should be + * avoided as much as possible as they harm portability and this is why + * this method is marked as deprecated. For the same reason this method only + * returns an integer and not a cursor, as one should expect. + * In some cases however, e.g. when doing large batch updates or when + * moving large volumes, stored procedures can speed up things. To maintain + * portability, there must always be an alternative execution path that + * does not involve calling a stored procedure. + * + * @param sql The name of the procedure to call (case sensitive) + * @param arglist Names for the stored procedure arguments, order must be the + * same as in the stored procedure itself. + * @param params The map of parameters to be substituted in the SQL query + * @return The number of rows affected by the execution of the procedure. + * @throws SQLException if the stored procedure execution fails for some reason. + * @throws QueryException if some parameters are missing + * @deprecated + */ + @Deprecated + public int callProcedure(String procName, List arglist, Map params) + throws SQLException, QueryException; + +} diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProject.java b/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProject.java index bb9a794d9..3a5424c1d 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProject.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProject.java @@ -332,7 +332,7 @@ public void addConfig(ConfigOption co, String value) { private void updateConfigValue (ConfigOption configOpt, String key, String value, boolean update) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); ConfigurationOption co = null; if (configOpt == null) { @@ -340,7 +340,7 @@ private void updateConfigValue (ConfigOption configOpt, String key, if (co == null) { co = new ConfigurationOption(key, ""); - dbs.addRecord(co); + qi.addRecord(co); } } else { co = ConfigurationOption.fromKey(configOpt.getName()); @@ -348,7 +348,7 @@ private void updateConfigValue (ConfigOption configOpt, String key, if (co == null) { co = new ConfigurationOption(configOpt.getName(), configOpt.getDesc()); - dbs.addRecord(co); + qi.addRecord(co); } } @@ -373,11 +373,11 @@ private void updateConfigValue (ConfigOption configOpt, String key, * @return StoredProject object or null if not found */ public static StoredProject getProjectByName(String name) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map parameterMap = new HashMap(); parameterMap.put("name",name); - List prList = dbs.findObjectsByProperties(StoredProject.class, parameterMap); + List prList = qi.findObjectsByProperties(StoredProject.class, parameterMap); return (prList == null || prList.isEmpty()) ? null : prList.get(0); } @@ -388,7 +388,7 @@ public static StoredProject getProjectByName(String name) { */ public static int getProjectCount() { DBService dbs = AlitheiaCore.getInstance().getDBService(); - List l = dbs.doHQL("SELECT COUNT(*) FROM StoredProject"); + List l = dbs.getQueryInterface(HQLQueryInterface.class).doHQL("SELECT COUNT(*) FROM StoredProject"); if ((l == null) || (l.size() < 1)) { return 0; } @@ -408,7 +408,7 @@ public long getVersionsCount() { Map parameterMap = new HashMap(); parameterMap.put("pid", this.getId()); - List pvList = dbs.doHQL("select count(*)" + List pvList = dbs.getQueryInterface(HQLQueryInterface.class).doHQL("select count(*)" + " from ProjectVersion pv" + " where pv.project.id=:pid", parameterMap); @@ -429,7 +429,7 @@ public long getMailsCount() { Map parameterMap = new HashMap(); parameterMap.put("pid", this.getId()); - List res = dbs.doHQL("select count(*)" + List res = dbs.getQueryInterface(HQLQueryInterface.class).doHQL("select count(*)" + " from MailMessage mm, MailingList ml" + " where ml.storedProject.id=:pid" + " and mm.list.id=ml.id", @@ -449,7 +449,7 @@ public long getBugsCount() { Map parameterMap = new HashMap(); parameterMap.put("pid", this.getId()); - List res = dbs.doHQL("select count(*)" + List res = dbs.getQueryInterface(HQLQueryInterface.class).doHQL("select count(*)" + " from Bug bg" + " where bg.project.id=:pid" + " and bg.status.status='" + Status.NEW + "'", diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProjectConfig.java b/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProjectConfig.java index 7cb8e8942..344c00146 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProjectConfig.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/StoredProjectConfig.java @@ -115,11 +115,11 @@ public void setValue(String value) { } public static List fromProject(StoredProject sp) { - DBService dbs = AlitheiaCore.getInstance().getDBService(); + QueryInterface qi = AlitheiaCore.getInstance().getDBService().getQueryInterface(); Map params = new HashMap(); params.put("project", sp); - return dbs.findObjectsByProperties(StoredProjectConfig.class, params); + return qi.findObjectsByProperties(StoredProjectConfig.class, params); } } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/db/Tag.java b/alitheia/core/src/main/java/eu/sqooss/service/db/Tag.java index 95d4a59e3..af1b3d113 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/db/Tag.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/db/Tag.java @@ -128,7 +128,7 @@ public static ProjectVersion getProjectVersionForNamedTag(String tagName, parameters.put(paramTagName, tagName); parameters.put(paramProject, sp); - List projectVersions = dbs.doHQL(query, parameters, 1); + List projectVersions = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters, 1); if (projectVersions == null || projectVersions.size() == 0) { return null; @@ -150,7 +150,7 @@ public static List getTaggedVersions(StoredProject sp) { Map parameters = new HashMap(); parameters.put(paramProject, sp); - return (List) dbs.doHQL(query, parameters); + return (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters); } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/pa/PluginInfo.java b/alitheia/core/src/main/java/eu/sqooss/service/pa/PluginInfo.java index 6ea33d4f5..03365a691 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/pa/PluginInfo.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/pa/PluginInfo.java @@ -40,11 +40,13 @@ import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; +import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.abstractmetric.AlitheiaPlugin; import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.Plugin; import eu.sqooss.service.db.PluginConfiguration; +import eu.sqooss.service.db.QueryInterface; import eu.sqooss.service.util.StringUtils; /** @@ -301,7 +303,7 @@ else if (type.equals(ConfigurationType.DOUBLE)) { } // Update the given configuration property - pc = db.attachObjectToDBSession(pc); + pc = db.getSessionManager().attachObjectToDBSession(pc); pc.setValue(newVal); return true; } @@ -412,14 +414,16 @@ public boolean removeConfigEntry( || (ConfigurationType.fromString(type) == null)) { throw new Exception("Invalid type!"); } + + QueryInterface qi = db.getQueryInterface(); // Get the property's Id Long propId = getConfPropId(name, type); if (propId != null) { // Remove the specified configuration property - PluginConfiguration prop = db.findObjectById( + PluginConfiguration prop = qi.findObjectById( PluginConfiguration.class, propId); - if ((prop != null) && (db.deleteRecord(prop))) { + if ((prop != null) && (qi.deleteRecord(prop))) { return true; } } diff --git a/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java b/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java index 62e9745cc..fa59951a5 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java @@ -222,9 +222,9 @@ final public long execute() throws Exception { restart(); /*Idiot/bad programmer proofing*/ - assert (!dbs.isDBSessionActive()); - if (dbs.isDBSessionActive()) { - dbs.rollbackDBSession(); + assert (!dbs.getSessionManager().isDBSessionActive()); + if (dbs.getSessionManager().isDBSessionActive()) { + dbs.getSessionManager().rollbackDBSession(); setState(State.Error); //No uncommitted sessions are tolerated } else { if (state() != State.Yielded) @@ -232,8 +232,8 @@ final public long execute() throws Exception { } } catch(Exception e) { - if (dbs.isDBSessionActive()) { - dbs.rollbackDBSession(); + if (dbs.getSessionManager().isDBSessionActive()) { + dbs.getSessionManager().rollbackDBSession(); } // In case of an exception, state becomes Error @@ -505,17 +505,17 @@ public long resume() throws Exception { setState(State.Running); resumePoint.resume(); - assert (!dbs.isDBSessionActive()); - if (dbs.isDBSessionActive()) { - dbs.rollbackDBSession(); + assert (!dbs.getSessionManager().isDBSessionActive()); + if (dbs.getSessionManager().isDBSessionActive()) { + dbs.getSessionManager().rollbackDBSession(); setState(State.Error); //No uncommitted sessions are tolerated } else { setState(State.Finished); } } catch(Exception e) { - if (dbs.isDBSessionActive()) { - dbs.rollbackDBSession(); + if (dbs.getSessionManager().isDBSessionActive()) { + dbs.getSessionManager().rollbackDBSession(); } // In case of an exception, state becomes Error diff --git a/alitheia/core/src/test/java/eu/sqooss/admin/test/AdminServiceImplTest.java b/alitheia/core/src/test/java/eu/sqooss/admin/test/AdminServiceImplTest.java index 9edc33bc6..5400b2426 100644 --- a/alitheia/core/src/test/java/eu/sqooss/admin/test/AdminServiceImplTest.java +++ b/alitheia/core/src/test/java/eu/sqooss/admin/test/AdminServiceImplTest.java @@ -1,10 +1,12 @@ package eu.sqooss.admin.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import java.util.Set; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import eu.sqooss.impl.service.admin.AdminServiceImpl; @@ -15,14 +17,29 @@ public class AdminServiceImplTest { - static AdminServiceImpl impl; - static long failid; - static long successid; + private AdminServiceImpl impl; + private long failid; + private long successid; - @BeforeClass - public static void setUp() { + @Before + public void setUp() { impl = new AdminServiceImpl(); } + + private void setUpRunTimeInfo() { + RunTimeInfo rti = new RunTimeInfo(); + impl.registerAdminAction(rti.mnemonic(), RunTimeInfo.class); + } + + private void setUpFailingAction() { + FailingAction fa = new FailingAction(); + impl.registerAdminAction(fa.mnemonic(), FailingAction.class); + } + + private void setUpSucceedingAction() { + SucceedingAction su = new SucceedingAction(); + impl.registerAdminAction(su.mnemonic(), SucceedingAction.class); + } @Test public void testAdminServiceImpl() { @@ -31,21 +48,18 @@ public void testAdminServiceImpl() { @Test public void testRegisterAdminAction() { - RunTimeInfo rti = new RunTimeInfo(); - impl.registerAdminAction(rti.mnemonic(), RunTimeInfo.class); - assertEquals(1, impl.getAdminActions().size()); - - FailingAction fa = new FailingAction(); - impl.registerAdminAction(fa.mnemonic(), FailingAction.class); - assertEquals(2, impl.getAdminActions().size()); - - SucceedingAction su = new SucceedingAction(); - impl.registerAdminAction(su.mnemonic(), SucceedingAction.class); + setUpRunTimeInfo(); + setUpFailingAction(); + setUpSucceedingAction(); assertEquals(3, impl.getAdminActions().size()); } @Test public void testGetAdminActions() { + setUpRunTimeInfo(); + setUpFailingAction(); + setUpSucceedingAction(); + Set actions = impl.getAdminActions(); for (AdminAction aa : actions) assertNotNull (aa); @@ -53,6 +67,8 @@ public void testGetAdminActions() { @Test public void testCreate() { + setUpFailingAction(); + AdminAction fail = impl.create("blah"); assertNull(fail); @@ -70,6 +86,9 @@ public void testCreate() { @Test public void testExecute() { + setUpSucceedingAction(); + setUpFailingAction(); + AdminAction success = impl.create("win"); assertNotNull(success); impl.execute(success); @@ -91,6 +110,7 @@ public void testExecute() { @Test public void testShow() { + testExecute(); AdminAction aa = impl.show(failid); assertNotNull(aa); @@ -100,6 +120,7 @@ public void testShow() { @Test public void testGC() { + testExecute(); try { Thread.sleep (300); } catch (InterruptedException e) {} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBObject.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBObject.java new file mode 100644 index 000000000..df0e4bc0a --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBObject.java @@ -0,0 +1,63 @@ +package eu.sqooss.test.service.db; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import eu.sqooss.service.db.DAObject; + +@Entity +@Table(name="DBOBJECT") +public class DBObject extends DAObject { + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + @Column(name="OBJECT_ID") + private long id; + + @Column(name="OBJECT_NAME") + private String name; + + // Required for Hibernate + public DBObject() { } + + public DBObject(String name) { + this.name = name; + } + + @Override + public long getId() { + return id; + } + + @Override + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof DBObject)) + return false; + + DBObject other = (DBObject)obj; + + if (other.getId() != getId()) + return false; + if (other.getName() == getName()) + return true; + return other.getName() != null && other.getName().equals(this.getName()); + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBServiceImplTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBServiceImplTest.java new file mode 100644 index 000000000..6e3212414 --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBServiceImplTest.java @@ -0,0 +1,89 @@ +package eu.sqooss.test.service.db; + +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.*; + +import org.hibernate.SessionFactory; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import eu.sqooss.impl.service.db.DBServiceImpl; +import eu.sqooss.impl.service.db.HQLQueryInterfaceImpl; +import eu.sqooss.impl.service.db.SQLQueryInterfaceImpl; +import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.DBSessionValidation; +import eu.sqooss.service.db.HQLQueryInterface; +import eu.sqooss.service.db.QueryInterface; +import eu.sqooss.service.db.QueryInterfaceFactory; +import eu.sqooss.service.db.SQLQueryInterface; + +public class DBServiceImplTest { + + private static InMemoryDatabase db; + private static DBServiceImpl dbs; + + @BeforeClass + public static void setUp() { + db = new InMemoryDatabase(new Class[] { DBObject.class }); + dbs = db.getDatabase(); + } + + @AfterClass + public static void tearDown() { + db.close(); + } + + @Test + public void testGetSessionManager_notNull() { + assertNotNull(dbs.getSessionManager()); + } + + @Test + public void testGetQueryInterface_withoutParameter() { + assertThat(dbs.getQueryInterface(), instanceOf(HQLQueryInterfaceImpl.class)); + } + + @Test + public void testGetQueryInterface_queryInterface() { + assertThat(dbs.getQueryInterface(QueryInterface.class), instanceOf(HQLQueryInterfaceImpl.class)); + } + + @Test + public void testGetQueryInterface_hqlQueryInterface() { + assertThat(dbs.getQueryInterface(HQLQueryInterface.class), instanceOf(HQLQueryInterfaceImpl.class)); + } + + @Test + public void testGetQueryInterface_sqlQueryInterface() { + assertThat(dbs.getQueryInterface(SQLQueryInterface.class), instanceOf(SQLQueryInterfaceImpl.class)); + } + + @Test + public void testGetQueryInterface_unknownInterface() { + assertNull(dbs.getQueryInterface(UnknownQueryInterface.class)); + } + + @Test + public void testRegisterQueryInterface() { + dbs.registerQueryInterface(NewQueryInterface.class, NewQueryInterfaceFactory.class); + + assertThat(dbs.getQueryInterface(NewQueryInterface.class), instanceOf(NewQueryInterface.class)); + } + + private static interface UnknownQueryInterface extends QueryInterface { } + + public static interface NewQueryInterface extends QueryInterface { } + + public static class NewQueryInterfaceFactory implements QueryInterfaceFactory { + + @Override + public NewQueryInterface build(DBService dbService, SessionFactory sessionFactory, + DBSessionValidation sessionValidation) { + return mock(NewQueryInterface.class); + } + + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBTransactionTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBTransactionTest.java new file mode 100644 index 000000000..39e291045 --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/DBTransactionTest.java @@ -0,0 +1,392 @@ +package eu.sqooss.test.service.db; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import org.hibernate.HibernateException; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.classic.Session; +import org.junit.Before; +import org.junit.Test; + +import eu.sqooss.impl.service.db.DBServiceImpl; +import eu.sqooss.service.logging.Logger; + +public class DBTransactionTest { + + private DBServiceImpl db; + private Logger l; + + @Before + public void setUp() { + db = new DBServiceImpl(); + l = mock(Logger.class); + } + + @Test + public void testStartDBSession_uninitialised() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + db.prepareForTest(s, false, l); + + boolean result = db.getSessionManager().startDBSession(); + + assertFalse(result); + verifyNoMoreInteractions(s); + } + + @Test + public void testStartDBSession_beginTransactionFailure() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + when(ss.beginTransaction()).thenThrow(new HibernateException("Failed to start transaction")); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().startDBSession(); + + assertFalse(result); + verify(ss).beginTransaction(); + } + + @Test + public void testStartDBSession_success() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().startDBSession(); + + assertTrue(result); + verify(ss).beginTransaction(); + } + + @Test + public void testIsDBSessionActive_uninitialised() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + db.prepareForTest(s, false, l); + + boolean result = db.getSessionManager().isDBSessionActive(); + + assertFalse(result); + verifyNoMoreInteractions(s); + } + + @Test + public void testIsDBSessionActive_noTransaction() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().isDBSessionActive(); + + assertFalse(result); + } + + @Test + public void testIsDBSessionActive_transactionException() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + when(ss.getTransaction()).thenThrow(new HibernateException("Failed to get transaction")); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().isDBSessionActive(); + + assertFalse(result); + verify(ss).close(); + } + + @Test + public void testIsDBSessionActive_transactionInactive() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Create an inactive transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(false); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().isDBSessionActive(); + + assertFalse(result); + } + + @Test + public void testIsDBSessionActive_true() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Create an active transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().isDBSessionActive(); + + assertTrue(result); + } + + @Test + public void testCommitDBSession_withoutActiveSession() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().commitDBSession(); + + assertFalse(result); + } + + @Test + public void testCommitDBSession_commitException() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Prepare active transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + doThrow(new HibernateException("Failed to commit transaction")).when(t).commit(); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().commitDBSession(); + + assertFalse(result); + verify(t).commit(); + verify(t).rollback(); + } + + @Test + public void testCommitDBSession_success() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Prepare active transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().commitDBSession(); + + assertTrue(result); + verify(t).commit(); + verify(t, atLeastOnce()).isActive(); + verifyNoMoreInteractions(t); + } + + @Test + public void testRollbackDBSession_withoutActiveSession() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().rollbackDBSession(); + + assertFalse(result); + } + + @Test + public void testRollbackDBSession_rollbackException() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Prepare active transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + doThrow(new HibernateException("Failed to commit transaction")).when(t).rollback(); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().rollbackDBSession(); + + assertFalse(result); + verify(t).rollback(); + verify(t, never()).commit(); + } + + @Test + public void testRollbackDBSession_success() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Prepare active transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().rollbackDBSession(); + + assertTrue(result); + verify(t).rollback(); + verify(t, never()).commit(); + } + + @Test + public void testFlushDBSession_withoutActiveSession() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().flushDBSession(); + + assertFalse(result); + } + + @Test + public void testFlushDBSession_flushException() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + doThrow(new HibernateException("Failed to flush session")).when(ss).flush(); + + // Prepare transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().flushDBSession(); + + assertFalse(result); + } + + @Test + public void testFlushDBSession_success() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Prepare transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + + db.prepareForTest(s, true, l); + + boolean result = db.getSessionManager().flushDBSession(); + + assertTrue(result); + verify(ss).flush(); + verify(ss).clear(); + } + + @Test + public void testAttachObjectToDBSession_withoutSession() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + db.prepareForTest(s, true, l); + + DBObject obj = db.getSessionManager().attachObjectToDBSession(new DBObject("test-object")); + + assertNull(obj); + } + + @Test + public void testAttachObjectToDBSession_notYetAttached() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Prepare transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + + db.prepareForTest(s, true, l); + + DBObject unbound = new DBObject("test-object"); + DBObject merged = new DBObject("merged-object"); + when(ss.contains(unbound)).thenReturn(false); + when(ss.merge(unbound)).thenReturn(merged); + DBObject obj = db.getSessionManager().attachObjectToDBSession(unbound); + + assertEquals(merged, obj); + + verify(ss).merge(unbound); + } + + @Test + public void testAttachObjectToDBSession_alreadyAttached() { + // Prepare session + SessionFactory s = mock(SessionFactory.class); + Session ss = mock(Session.class); + when(s.getCurrentSession()).thenReturn(ss); + + // Prepare transaction + Transaction t = mock(Transaction.class); + when(ss.getTransaction()).thenReturn(t); + when(t.isActive()).thenReturn(true); + + db.prepareForTest(s, true, l); + + DBObject unbound = new DBObject("test-object"); + when(ss.contains(unbound)).thenReturn(true); + DBObject obj = db.getSessionManager().attachObjectToDBSession(unbound); + + assertSame(unbound, obj); + + verify(ss, never()).merge(unbound); + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceImplTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceImplTest.java new file mode 100644 index 000000000..80c6886bd --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceImplTest.java @@ -0,0 +1,12 @@ +package eu.sqooss.test.service.db; + +import eu.sqooss.service.db.HQLQueryInterface; + +public class HQLQueryInterfaceImplTest extends HQLQueryInterfaceTest { + + @Override + protected HQLQueryInterface getHQLQueryInterface() { + return getDB().getHQLInterface(); + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceTest.java new file mode 100644 index 000000000..1f51d1f3b --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/HQLQueryInterfaceTest.java @@ -0,0 +1,267 @@ +package eu.sqooss.test.service.db; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.either; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.QueryException; +import org.junit.Test; + +import eu.sqooss.service.db.HQLQueryInterface; +import eu.sqooss.service.db.QueryInterface; + +public abstract class HQLQueryInterfaceTest extends QueryInterfaceTest { + + protected abstract HQLQueryInterface getHQLQueryInterface(); + + @Override + protected QueryInterface getQueryInterface() { + return getHQLQueryInterface(); + } + + @Test + public void testDoHQL_selectNoObjects() { + // Insert test object + DBObject obj = new DBObject("object"); + getDB().addTestObject(obj); + + // Select a non-existent object + List objs = getHQLQueryInterface().doHQL("select o from DBObject o where o.name = 'unknown'"); + assertThat(objs, is(empty())); + } + + @Test + public void testDoHQL_selectMultipleObjects() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("object"); + DBObject objC = new DBObject("other-object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + getDB().addTestObject(objC); + + // Select all objects with name "object" + @SuppressWarnings("unchecked") + List objs = (List) getHQLQueryInterface().doHQL("select o from DBObject o where o.name = 'object'"); + + assertThat(objs, containsInAnyOrder(objA, objB)); + } + + @Test + public void testDoHQL_withParameters() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("other-object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + + // Select second object using a parameter + Map params = new HashMap<>(); + params.put("nameparam", objB.getName()); + @SuppressWarnings("unchecked") + List objs = (List) getHQLQueryInterface().doHQL( + "select o from DBObject o where o.name = :nameparam", params); + + assertThat(objs, contains(objB)); + } + + @Test(expected = QueryException.class) + public void testDoHQL_withMissingParameters() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("other-object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + + // Execute query without specifying all parameters + getHQLQueryInterface().doHQL("select o from DBObject o where o.name = :nameparam", new HashMap()); + } + + @Test + public void testDoHQL_withZeroLimit() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + + // Select one object with name "object" + List objs = getHQLQueryInterface().doHQL( + "select o from DBObject o where o.name = 'object'", new HashMap(), 0); + + assertThat(objs, is(empty())); + } + + @Test + public void testDoHQL_withSmallLimit() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + + // Select one object with name "object" + @SuppressWarnings("unchecked") + List objs = (List) getHQLQueryInterface().doHQL( + "select o from DBObject o where o.name = 'object'", new HashMap(), 1); + + assertThat(objs, hasSize(1)); + assertThat(objs.get(0), either(equalTo(objA)).or(equalTo(objB))); + } + + @Test + public void testDoHQL_withLargeLimit() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + + // Select one object with name "object" + @SuppressWarnings("unchecked") + List objs = (List) getHQLQueryInterface().doHQL( + "select o from DBObject o where o.name = 'object'", new HashMap(), 3); + + assertThat(objs, containsInAnyOrder(objA, objB)); + } + + @Test + public void testDoHQL_withNegativeLimit() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + + // Select one object with name "object" + @SuppressWarnings("unchecked") + List objs = (List) getHQLQueryInterface().doHQL( + "select o from DBObject o where o.name = 'object'", new HashMap(), -1); + + assertThat(objs, containsInAnyOrder(objA, objB)); + } + + @Test + public void testDoHQL_withCollectionParameters() { + // Insert test objects + DBObject objA = new DBObject("object-a"); + DBObject objB = new DBObject("object-b"); + DBObject objC = new DBObject("object-c"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + getDB().addTestObject(objC); + + // Select second object using a parameter + @SuppressWarnings("rawtypes") + Map params = new HashMap<>(); + params.put("namelist", Arrays.asList(objA.getName(), objB.getName())); + @SuppressWarnings("unchecked") + List objs = (List) getHQLQueryInterface().doHQL( + "select o from DBObject o where o.name in (:namelist)", new HashMap(), params); + + assertThat(objs, containsInAnyOrder(objA, objB)); + } + + @SuppressWarnings("rawtypes") + @Test(expected = QueryException.class) + public void testDoHQL_withMissingCollectionParameters() { + // Insert test objects + DBObject objA = new DBObject("object-a"); + DBObject objB = new DBObject("object-b"); + DBObject objC = new DBObject("object-c"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + getDB().addTestObject(objC); + + // Select second object using a parameter + getHQLQueryInterface().doHQL("select o from DBObject o where o.name in (:namelist)", + new HashMap(), new HashMap()); + } + + @Test(expected = QueryException.class) + public void testExecuteUpdate_missingParameter() { + // Insert test object + DBObject objA = new DBObject("object"); + getDB().addTestObject(objA); + + // Update the name of the test object + getHQLQueryInterface().executeUpdate("update DBObject set object_name = :newname where object_id = :obj_id", null); + } + + @Test + public void testExecuteUpdate_oneObject() { + // Insert test objects + DBObject objA = new DBObject("object"); + DBObject objB = new DBObject("object"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + + // Update the name of the test object + Map params = new HashMap<>(); + params.put("newname", "changed"); + params.put("obj_id", objA.getId()); + int rows = getHQLQueryInterface().executeUpdate("update DBObject set name = :newname where id = :obj_id", params); + // Commit the change + getDB().getDatabase().getSessionManager().commitDBSession(); + + try { + // Start a new session to read the changes + getDB().getDatabase().getSessionManager().startDBSession(); + + assertThat(rows, equalTo(1)); + assertThat(getDB().getTestObject(DBObject.class, objA.getId()).getName(), equalTo("changed")); + } catch (Exception e) { + throw e; + } finally { + getDB().getDatabase().getSessionManager().startDBSession(); + getHQLQueryInterface().executeUpdate("delete from DBObject", null); + getDB().getDatabase().getSessionManager().commitDBSession(); + } + } + + @Test + public void testExecuteUpdate_multipleObjects() { + // Insert test objects + DBObject objA = new DBObject("object-a"); + DBObject objB = new DBObject("object-b"); + DBObject objC = new DBObject("object-c"); + getDB().addTestObject(objA); + getDB().addTestObject(objB); + getDB().addTestObject(objC); + + // Update the name of the test object + Map params = new HashMap<>(); + params.put("newname", "changed"); + int rows = getHQLQueryInterface().executeUpdate("update DBObject set name = :newname", params); + // Commit the change + getDB().getDatabase().getSessionManager().commitDBSession(); + + try { + // Start a new session to read the changes + getDB().getDatabase().getSessionManager().startDBSession(); + + assertThat(rows, equalTo(3)); + assertThat(getDB().getTestObject(DBObject.class, objA.getId()).getName(), equalTo("changed")); + assertThat(getDB().getTestObject(DBObject.class, objB.getId()).getName(), equalTo("changed")); + assertThat(getDB().getTestObject(DBObject.class, objC.getId()).getName(), equalTo("changed")); + } catch (Exception e) { + throw e; + } finally { + getDB().getDatabase().getSessionManager().startDBSession(); + getHQLQueryInterface().executeUpdate("delete from DBObject", null); + getDB().getDatabase().getSessionManager().commitDBSession(); + } + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/InMemoryDatabase.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/InMemoryDatabase.java new file mode 100644 index 000000000..f0ea854a9 --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/InMemoryDatabase.java @@ -0,0 +1,125 @@ +package eu.sqooss.test.service.db; + +import java.io.Serializable; + +import org.hibernate.SessionFactory; +import org.hibernate.cfg.AnnotationConfiguration; +import org.mockito.Mockito; + +import eu.sqooss.impl.service.db.DBServiceImpl; +import eu.sqooss.impl.service.db.HQLQueryInterfaceImpl; +import eu.sqooss.service.db.*; +import eu.sqooss.service.logging.Logger; + +public final class InMemoryDatabase { + + private SessionFactory sessionFactory; + private DBServiceImpl db; + + private HQLQueryInterfaceImpl hqlInterface; + + public InMemoryDatabase(Class[] annotatedClasses) { + setUpDatabase(annotatedClasses); + + db = new DBServiceImpl(); + db.prepareForTest(sessionFactory, true, Mockito.mock(Logger.class)); + + hqlInterface = new HQLQueryInterfaceImpl(db.getSessionManager(), (DBSessionValidation)db.getSessionManager(), + sessionFactory, Mockito.mock(Logger.class)); + } + + private void setUpDatabase(Class[] annotatedClasses) { + // setup the session factory + AnnotationConfiguration configuration = new AnnotationConfiguration(); + for (Class annotatedClass : annotatedClasses) + configuration.addAnnotatedClass(annotatedClass); + configuration.setProperty("hibernate.dialect", + "org.hibernate.dialect.H2Dialect"); + configuration.setProperty("hibernate.connection.driver_class", + "org.h2.Driver"); + configuration.setProperty("hibernate.connection.url", "jdbc:h2:mem:"); + configuration.setProperty("hibernate.hbm2ddl.auto", "create"); + configuration.setProperty("hibernate.current_session_context_class", "thread"); + + sessionFactory = configuration.buildSessionFactory(); + } + + public void close() { + sessionFactory.close(); + } + + public SessionFactory getSessionFactory() { + return sessionFactory; + } + + public DBServiceImpl getDatabase() { + return db; + } + + public HQLQueryInterfaceImpl getHQLInterface() { + return hqlInterface; + } + + public void addTestObject(Object obj) { + sessionFactory.getCurrentSession().save(obj); + } + + @SuppressWarnings("unchecked") + public T getTestObject(Class clazz, Serializable id) { + return (T)sessionFactory.getCurrentSession().get(clazz, id); + } + + public void startTransaction() { + sessionFactory.getCurrentSession().beginTransaction(); + } + + public void stopTransaction() { + if (sessionFactory.getCurrentSession().getTransaction() != null && + sessionFactory.getCurrentSession().getTransaction().isActive()) + sessionFactory.getCurrentSession().getTransaction().rollback(); + } + + public static InMemoryDatabase createDefault() { + return new InMemoryDatabase(new Class[] { + Bug.class, + BugStatus.class, + BugReportMessage.class, + BugSeverity.class, + BugPriority.class, + BugResolution.class, + MailingList.class, + MailMessage.class, + MailingListThread.class, + ProjectVersion.class, + ProjectFile.class, + ProjectFileState.class, + Developer.class, + DeveloperAlias.class, + Directory.class, + Tag.class, + Branch.class, + StoredProject.class, + StoredProjectConfig.class, + ConfigurationOption.class, + ClusterNode.class, + Plugin.class, + PluginConfiguration.class, + Metric.class, + MetricType.class, + StoredProjectMeasurement.class, + ProjectVersionMeasurement.class, + ProjectFileMeasurement.class, + MailingListThreadMeasurement.class, + MailMessageMeasurement.class, + OhlohDeveloper.class, + ProjectVersionParent.class, + NameSpace.class, + ExecutionUnit.class, + EncapsulationUnit.class, + NameSpaceMeasurement.class, + ExecutionUnitMeasurement.class, + EncapsulationUnitMeasurement.class + }); + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/QueryInterfaceTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/QueryInterfaceTest.java new file mode 100644 index 000000000..b1312e861 --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/QueryInterfaceTest.java @@ -0,0 +1,362 @@ +package eu.sqooss.test.service.db; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import eu.sqooss.service.db.QueryInterface; + +public abstract class QueryInterfaceTest { + + private static final String objNameA = "test-object-a"; + private static final String objNameB = "test-object-b"; + private static final String objNameC = "test-object-c"; + private static final String objNameD = "test-object-d"; + + private static InMemoryDatabase db; + + protected InMemoryDatabase getDB() { + return db; + } + + protected abstract QueryInterface getQueryInterface(); + + @BeforeClass + public static void setUp() { + db = new InMemoryDatabase(new Class[] { DBObject.class }); + } + + @AfterClass + public static void tearDown() { + db.close(); + } + + @Before + public void beginTransaction() { + db.startTransaction(); + } + + @After + public void closeTransaction() { + db.stopTransaction(); + } + + @Test + public void testAddRecord() { + DBObject obj = new DBObject(objNameA); + + // Store the object and assert that it succeeded + boolean result = getQueryInterface().addRecord(obj); + assertTrue(result); + + // Retrieve + DBObject storedObj = db.getTestObject(DBObject.class, obj.getId()); + assertEquals(obj, storedObj); + } + + @Test + public void testAddRecord_no_active_session() { + DBObject obj = new DBObject(objNameA); + + // Make sure there is no active transaction + closeTransaction(); + + // Store the object and assert that it succeeded + boolean result = getQueryInterface().addRecord(obj); + assertFalse(result); + + beginTransaction(); //necessary for closeTransaction() to succeed + } + + @Test + public void testAddRecord_multiple() { + DBObject objA = new DBObject(objNameA); + DBObject objB = new DBObject(objNameB); + + // Store both objects and assert that it succeeded + boolean result = getQueryInterface().addRecord(objA); + assertTrue(result); + result = getQueryInterface().addRecord(objB); + assertTrue(result); + + // Check that both objects have different IDs + assertThat(objA.getId(), not(equalTo(objB.getId()))); + + // Attempt to retrieve both objects + DBObject storedObjA = db.getTestObject(DBObject.class, objA.getId()); + DBObject storedObjB = db.getTestObject(DBObject.class, objB.getId()); + assertEquals(objA, storedObjA); + assertEquals(objB, storedObjB); + } + + @Test + public void testDeleteRecord() { + DBObject obj = new DBObject(objNameA); + + // Store the object and assert that it succeeded + boolean result = getQueryInterface().addRecord(obj); + assertTrue(result); + + // Retrieve the object + DBObject storedObj = db.getTestObject(DBObject.class, obj.getId()); + assertEquals(obj, storedObj); + + // Delete the record + result = getQueryInterface().deleteRecord(obj); + assertTrue(result); + + // Check whether it is actually deleted + storedObj = db.getTestObject(DBObject.class, obj.getId()); + assertNull(storedObj); + } + + @Test + public void testDeleteRecord_no_active_session() { + DBObject obj = new DBObject(objNameA); + + // Store the object and assert that it succeeded + boolean result = getQueryInterface().addRecord(obj); + assertTrue(result); + + // Retrieve the object + DBObject storedObj = db.getTestObject(DBObject.class, obj.getId()); + assertEquals(obj, storedObj); + + // Make sure there is no active transaction + closeTransaction(); + + // Delete the record + result = getQueryInterface().deleteRecord(obj); + assertFalse(result); + + beginTransaction(); //necessary for closeTransaction() to succeed + } + + @Test + public void testDeleteRecord_multiple_adds_one_delete() { + DBObject objA = new DBObject(objNameA); + DBObject objB = new DBObject(objNameB); + + // Store both objects and assert that it succeeded + boolean result = getQueryInterface().addRecord(objA); + assertTrue(result); + result = getQueryInterface().addRecord(objB); + assertTrue(result); + + // Attempt to retrieve both objects + DBObject storedObjA = db.getTestObject(DBObject.class, objA.getId()); + DBObject storedObjB = db.getTestObject(DBObject.class, objB.getId()); + assertEquals(objA, storedObjA); + assertEquals(objB, storedObjB); + + // Delete the record for objA + result = getQueryInterface().deleteRecord(objA); + assertTrue(result); + + // Check whether only objA is deleted + storedObjA = db.getTestObject(DBObject.class, objA.getId()); + assertNull(storedObjA); + storedObjB = db.getTestObject(DBObject.class, objB.getId()); + assertEquals(objB, storedObjB); + } + + @Test + public void testFindObjectById_success(){ + DBObject objC = new DBObject(objNameC); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objC); + assertTrue(result); + + // Check whether the findObjectById function returns the correct object + DBObject storedObjC = (DBObject)getQueryInterface().findObjectById(DBObject.class, objC.getId()); + assertEquals(objC, storedObjC); + } + + @Test + public void testFindObjectById_no_active_session(){ + DBObject objC = new DBObject(objNameC); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objC); + assertTrue(result); + + // Make sure there is no active transaction + closeTransaction(); + + // Check whether the findObjectById function returns null + DBObject storedObjC = (DBObject)getQueryInterface().findObjectById(DBObject.class, objC.getId()); + assertNull(storedObjC); + + beginTransaction(); //necessary for closeTransaction() to succeed + } + + @Test + public void testFindObjectByIdForUpdate(){ + DBObject objD = new DBObject(objNameD); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + + // Check whether the findObjectByIdForUpdate function returns the correct object + DBObject storedObjD = (DBObject)getQueryInterface().findObjectByIdForUpdate(DBObject.class, objD.getId()); + assertEquals(objD, storedObjD); + } + + @Test + public void testFindObjectsByProperties_single_property(){ + DBObject objD = new DBObject(objNameD); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + + // Create a map with properties of objD + Map properties = new HashMap(); + properties.put("name", objNameD); + + // Check whether the findObjectsByProperties function returns a list with only objD in it + List res = getQueryInterface().findObjectsByProperties(DBObject.class, properties); + assertEquals(1, res.size()); + assertEquals(objD, res.get(0)); + } + + @Test + public void testFindObjectsByProperties_no_active_session(){ + DBObject objD = new DBObject(objNameD); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + + // Make sure there is no active transaction + closeTransaction(); + + // Create a map with properties of objD + Map properties = new HashMap(); + properties.put("name", objNameD); + + // Check whether the findObjectsByProperties function returns the empty list + List res = getQueryInterface().findObjectsByProperties(DBObject.class, properties); + assertEquals(Collections.emptyList(),res); + + beginTransaction(); //necessary for closeTransaction() to succeed + } + + @Test + public void testFindObjectsByProperties_multiple_properties(){ + DBObject objD = new DBObject(objNameD); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + + // Create a map with properties of objD + Map properties = new HashMap(); + properties.put("id", objD.getId()); + properties.put("name", objNameD); + + // Check whether the findObjectsByProperties function returns a list with only objD in it + List res = getQueryInterface().findObjectsByProperties(DBObject.class, properties); + assertEquals(1, res.size()); + assertEquals(objD, res.get(0)); + } + + @Test + public void testFindObjectsByProperties_multiple_results(){ + DBObject objD = new DBObject(objNameD); + DBObject objD2 = new DBObject(objNameD); + + // Store objects and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + result = getQueryInterface().addRecord(objD2); + assertTrue(result); + + // Create a map with the common name property of objD and objD2 + Map properties = new HashMap(); + properties.put("name", objNameD); + + // Check whether the findObjectsByProperties function returns a list with only objD and objD2 in it + List res = getQueryInterface().findObjectsByProperties(DBObject.class, properties); + assertEquals(2, res.size()); + assertTrue(res.contains(objD)); + assertTrue(res.contains(objD2)); + } + + @Test + public void testFindObjectsByPropertiesForUpdate_single_property(){ + DBObject objD = new DBObject(objNameD); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + + // Create a map with properties of objD + Map properties = new HashMap(); + properties.put("name", objNameD); + + // Check whether the findObjectsByPropertiesForUpdate function returns a list with only objD in it + List res = getQueryInterface().findObjectsByPropertiesForUpdate(DBObject.class, properties); + assertEquals(1, res.size()); + assertEquals(objD, res.get(0)); + } + + @Test + public void testFindObjectsByPropertiesForUpdate_multiple_properties(){ + DBObject objD = new DBObject(objNameD); + + // Store object and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + + // Create a map with properties of objD + Map properties = new HashMap(); + properties.put("id", objD.getId()); + properties.put("name", objNameD); + + // Check whether the findObjectsByPropertiesForUpdate function returns a list with only objD in it + List res = getQueryInterface().findObjectsByPropertiesForUpdate(DBObject.class, properties); + assertEquals(1, res.size()); + assertEquals(objD, res.get(0)); + } + + @Test + public void testFindObjectsByPropertiesForUpdate_multiple_results(){ + DBObject objD = new DBObject(objNameD); + DBObject objD2 = new DBObject(objNameD); + + // Store objects and verify it succeeded + boolean result = getQueryInterface().addRecord(objD); + assertTrue(result); + result = getQueryInterface().addRecord(objD2); + assertTrue(result); + + // Create a map with the common name property of objD and objD2 + Map properties = new HashMap(); + properties.put("name", objNameD); + + // Check whether the findObjectsByPropertiesForUpdate function returns a list with only objD and objD2 in it + List res = getQueryInterface().findObjectsByPropertiesForUpdate(DBObject.class, properties); + assertEquals(2, res.size()); + assertTrue(res.contains(objD)); + assertTrue(res.contains(objD2)); + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/ConfigurationOptionTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/ConfigurationOptionTest.java new file mode 100644 index 000000000..18d30767b --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/ConfigurationOptionTest.java @@ -0,0 +1,240 @@ +package eu.sqooss.test.service.db.objects; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; +import static org.hamcrest.Matchers.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import eu.sqooss.core.AlitheiaCore; +import eu.sqooss.service.db.*; +import eu.sqooss.test.service.db.InMemoryDatabase; + +public class ConfigurationOptionTest { + + private static DBService db; + private static QueryInterface qi; + + @BeforeClass + public static void initializeDatabase() { + db = InMemoryDatabase.createDefault().getDatabase(); + qi = db.getQueryInterface(); + AlitheiaCore ac = mock(AlitheiaCore.class); + + when(ac.getDBService()).thenReturn(db); + + AlitheiaCore.setTestInstance(ac); + } + + @AfterClass + public static void tearDown() { + db.shutDown(); + } + + @Before + public void beginTransaction() { + db.getSessionManager().startDBSession(); + } + + @After + public void closeTransaction() { + db.getSessionManager().rollbackDBSession(); + } + + @Test + public void testGetValues_nonExistentProject() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + qi.addRecord(opt); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List values = cfgOpt.getValues(new StoredProject()); + + assertThat(values, is(empty())); + } + + @Test + public void testSetValues_singleProjectNoValues() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + StoredProject sp = new StoredProject("sp1"); + qi.addRecord(opt); + qi.addRecord(sp); + + // Add no values + opt.setValues(sp, Collections. emptyList(), false); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List values = cfgOpt.getValues(sp); + + assertThat(values, is(empty())); + } + + @Test + public void testSetValues_singleProjectSomeValues() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + StoredProject sp = new StoredProject("sp1"); + qi.addRecord(opt); + qi.addRecord(sp); + + // Add some values + List values = Arrays.asList("valueA", "valueB"); + opt.setValues(sp, values, false); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List readValues = cfgOpt.getValues(sp); + + assertThat(readValues, containsInAnyOrder(values.toArray(new String[2]))); + } + + @Test + public void testSetValues_singleProjectMultipleTimes() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + StoredProject sp = new StoredProject("sp1"); + qi.addRecord(opt); + qi.addRecord(sp); + + // Add some values + List values = Arrays.asList("valueA", "valueB"); + opt.setValues(sp, values, false); + // Add some more values + List moreValues = Arrays.asList("valueC", "valueD"); + opt.setValues(sp, moreValues, false); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List readValues = cfgOpt.getValues(sp); + + assertThat(readValues, containsInAnyOrder("valueA", "valueB", "valueC", "valueD")); + } + + @Test + public void testSetValues_singleProjectMultipleTimesWithOverlap() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + StoredProject sp = new StoredProject("sp1"); + qi.addRecord(opt); + qi.addRecord(sp); + + // Add some values + List values = Arrays.asList("valueA", "valueB", "valueD"); + opt.setValues(sp, values, false); + // Add some more values + List moreValues = Arrays.asList("valueC", "valueD"); + opt.setValues(sp, moreValues, false); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List readValues = cfgOpt.getValues(sp); + + assertThat(readValues, containsInAnyOrder("valueA", "valueB", "valueC", "valueD")); + } + + @Test + public void testSetValues_multipleProjectsSomeValues() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + StoredProject sp1 = new StoredProject("sp1"); + StoredProject sp2 = new StoredProject("sp2"); + qi.addRecord(opt); + qi.addRecord(sp1); + qi.addRecord(sp2); + + // Add some values + List values1 = Arrays.asList("valueA", "valueD"); + List values2 = Arrays.asList("valueB", "valueC", "valueE"); + opt.setValues(sp1, values1, false); + opt.setValues(sp2, values2, false); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List readValues1 = cfgOpt.getValues(sp1); + List readValues2 = cfgOpt.getValues(sp2); + + assertThat(readValues1, containsInAnyOrder(values1.toArray(new String[2]))); + assertThat(readValues2, containsInAnyOrder(values2.toArray(new String[3]))); + } + + @Test + public void testSetValues_overwriteNoNewValues() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + StoredProject sp = new StoredProject("sp1"); + qi.addRecord(opt); + qi.addRecord(sp); + + // Add some values + List values = Arrays.asList("valueA", "valueB"); + opt.setValues(sp, values, false); + // Overwrite with no values + opt.setValues(sp, Collections.emptyList(), true); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List readValues = cfgOpt.getValues(sp); + + assertThat(readValues, is(empty())); + } + + @Test + public void testSetValues_overwriteSomeNewValues() { + // Create test objects + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + StoredProject sp = new StoredProject("sp1"); + qi.addRecord(opt); + qi.addRecord(sp); + + // Add some values + List values = Arrays.asList("valueA", "valueB", "valueC"); + opt.setValues(sp, values, false); + // Overwrite with some new values + List newValues = Arrays.asList("valueD", "valueB", "valueE"); + opt.setValues(sp, newValues, true); + + // Read the test object from the database, and look up its values + ConfigurationOption cfgOpt = qi.findObjectById(ConfigurationOption.class, opt.getId()); + List readValues = cfgOpt.getValues(sp); + + assertThat(readValues, containsInAnyOrder(newValues.toArray(new String[3]))); + } + + @Test + public void testFromKey_notFound() { + // Create test object + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + qi.addRecord(opt); + + // Look up a non-existent key + ConfigurationOption found = ConfigurationOption.fromKey("unknown-opt"); + + assertNull(found); + } + + @Test + public void testFromKey_success() { + // Create test object + ConfigurationOption opt = new ConfigurationOption("opt", "A sample option"); + qi.addRecord(opt); + + // Look up a non-existent key + ConfigurationOption found = ConfigurationOption.fromKey("opt"); + + assertNotNull(found); + assertEquals(found.getId(), opt.getId()); + assertEquals(found.getDescription(), opt.getDescription()); + } + +} diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/MetricTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/MetricTest.java new file mode 100644 index 000000000..0a7c104ae --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/db/objects/MetricTest.java @@ -0,0 +1,196 @@ +package eu.sqooss.test.service.db.objects; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isOneOf; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import eu.sqooss.core.AlitheiaCore; +import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.Metric; +import eu.sqooss.service.db.MetricType; +import eu.sqooss.service.db.NameSpace; +import eu.sqooss.service.db.NameSpaceMeasurement; +import eu.sqooss.service.db.ProjectVersion; +import eu.sqooss.service.db.QueryInterface; +import eu.sqooss.service.db.StoredProject; +import eu.sqooss.test.service.db.InMemoryDatabase; + +public class MetricTest { + + private static DBService db; + private static QueryInterface qi; + + private static final String metric_mnemonic = "test-metric"; + private static final String test_project_name = "test-project"; + private static final String metric_type_string = "NAMESPACE"; + private static final String test_measurement_result = "test-result"; + + @BeforeClass + public static void initializeDatabase() { + db = InMemoryDatabase.createDefault().getDatabase(); + qi = db.getQueryInterface(); + AlitheiaCore ac = mock(AlitheiaCore.class); + + when(ac.getDBService()).thenReturn(db); + + AlitheiaCore.setTestInstance(ac); + } + + @AfterClass + public static void tearDown() { + db.shutDown(); + } + + @Before + public void beginTransaction() { + db.getSessionManager().startDBSession(); + } + + @After + public void closeTransaction() { + db.getSessionManager().rollbackDBSession(); + } + + @Test + public void testIsEvaluated(){ + // Create necessary objects + Metric metr = new Metric(); + MetricType type = new MetricType(); + StoredProject project = new StoredProject(test_project_name); + ProjectVersion version = new ProjectVersion(project); + NameSpaceMeasurement meas = new NameSpaceMeasurement(); + NameSpace namespace = new NameSpace(); + + // Set required properties of the objects + type.setType(metric_type_string); + metr.setMetricType(type); + metr.setMnemonic(metric_mnemonic); + namespace.setChangeVersion(version); + meas.setMetric(metr); + meas.setNamespace(namespace); + meas.setResult(test_measurement_result); + + // Add the objects to the database + qi.addRecord(type); + qi.addRecord(metr); + qi.addRecord(project); + qi.addRecord(version); + qi.addRecord(namespace); + qi.addRecord(meas); + + // Call the method and check its result + boolean result = metr.isEvaluated(project); + assertTrue(result); + } + + @Test + public void testIsEvaluated_not_evaluated(){ + Metric metr = new Metric(); + MetricType type = new MetricType(); + type.setType(metric_type_string); + metr.setMetricType(type); + StoredProject project = new StoredProject(test_project_name); + qi.addRecord(type); + qi.addRecord(metr); + qi.addRecord(project); + + boolean result = metr.isEvaluated(project); + assertFalse(result); + } + + @Test + public void testGetMetricByMnemonic_no_results(){ + // Add the metric to the database + Metric obj = new Metric(); + qi.addRecord(obj); + + // Retrieve metric based on mnemonic and check properties + Metric result = Metric.getMetricByMnemonic(metric_mnemonic); + assertNull(result); + } + + @Test + public void testGetMetricByMnemonic_single_result(){ + // Add the metric to the database + Metric obj = new Metric(); + obj.setMnemonic(metric_mnemonic); + qi.addRecord(obj); + + // Retrieve metric based on mnemonic and check properties + Metric result = Metric.getMetricByMnemonic(metric_mnemonic); + assertNotNull(result); + assertEquals(obj.getId(), result.getId()); + assertEquals(obj.getMnemonic(), result.getMnemonic()); + assertEquals(metric_mnemonic, result.getMnemonic()); + } + + @Test + public void testGetMetricByMnemonic_multiple_results(){ + // Add the metrics to the database + Metric obj1 = new Metric(); + Metric obj2 = new Metric(); + obj1.setMnemonic(metric_mnemonic); + obj2.setMnemonic(metric_mnemonic); + qi.addRecord(obj1); + qi.addRecord(obj2); + + // Retrieve metric based on mnemonic and check properties + Metric result = Metric.getMetricByMnemonic(metric_mnemonic); + assertNotNull(result); + assertEquals(metric_mnemonic, result.getMnemonic()); + assertThat(result, isOneOf(obj1,obj2)); + } + + @Test + public void testGetAllMetrics_no_metrics(){ + // Retrieve all metrics and check properties + List results = Metric.getAllMetrics(); + assertThat(results, is(empty())); + } + + @Test + public void testGetAllMetrics_single_metric(){ + // Add the metric to the database + Metric obj = new Metric(); + qi.addRecord(obj); + + // Retrieve all metrics and check properties + List results = Metric.getAllMetrics(); + assertThat(results, is(not(empty()))); + assertEquals(1, results.size()); + assertEquals(obj, results.get(0)); + } + + @Test + public void testGetAllMetrics_multiple_metrics(){ + // Add the metrics to the database + Metric obj1 = new Metric(); + Metric obj2 = new Metric(); + qi.addRecord(obj1); + qi.addRecord(obj2); + + // Retrieve all metrics and check properties + List results = Metric.getAllMetrics(); + assertThat(results, is(not(empty()))); + assertEquals(2, results.size()); + assertThat(results, contains(obj1,obj2)); + } +} diff --git a/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/ContributionMetricImpl.java b/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/ContributionMetricImpl.java index 5d6042bef..bbca76cd8 100644 --- a/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/ContributionMetricImpl.java +++ b/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/ContributionMetricImpl.java @@ -67,16 +67,17 @@ import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.Developer; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.MailMessage; import eu.sqooss.service.db.MailingList; import eu.sqooss.service.db.MailingListThread; import eu.sqooss.service.db.Metric; import eu.sqooss.service.db.MetricType; +import eu.sqooss.service.db.MetricType.Type; import eu.sqooss.service.db.PluginConfiguration; import eu.sqooss.service.db.ProjectFile; import eu.sqooss.service.db.ProjectVersion; import eu.sqooss.service.db.StoredProject; -import eu.sqooss.service.db.MetricType.Type; import eu.sqooss.service.fds.FileTypeMatcher; import eu.sqooss.service.metricactivator.MetricActivationException; import eu.sqooss.service.pa.PluginInfo; @@ -121,7 +122,7 @@ public boolean remove() { "ContribActionType"}; for (String tablename : tables) { - result &= db.deleteRecords((List) db.doHQL( + result &= db.getQueryInterface().deleteRecords((List) db.getQueryInterface(HQLQueryInterface.class).doHQL( "from " + tablename)); } @@ -160,10 +161,10 @@ private boolean cleanupResource (Collection c, params.put("changedResourceId", o.getId()); params.put("actionCategory", ac.toString()); List pas = - db.findObjectsByProperties(ContribAction.class, params); + db.getQueryInterface(HQLQueryInterface.class).findObjectsByProperties(ContribAction.class, params); if (!pas.isEmpty()) { for (ContribAction pa : pas) { - result &= db.deleteRecord(pa); + result &= db.getQueryInterface().deleteRecord(pa); } } params.clear(); @@ -179,19 +180,19 @@ public Map> getObjectIdsToSync(StoredProject sp params.put("sp", sp); String qVersionIDs = "select pv.id from ProjectVersion pv where pv.id not in (select ca.changedResourceId from ContribAction ca where developer.storedProject =:sp and ca.contribActionType.actionCategory='C') and pv.project = :sp order by pv.sequence"; - List objectIds = (List) db.doHQL(qVersionIDs, params); + List objectIds = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(qVersionIDs, params); TreeSet ids = new TreeSet(); ids.addAll(objectIds); IDs.put(MetricType.Type.PROJECT_VERSION, ids); String qThreadIDs = "select mlt.id from MailingListThread mlt where mlt.id not in (select ca.changedResourceId from ContribAction ca where developer.storedProject =:sp and ca.contribActionType.actionCategory='M') and mlt.list.storedProject = :sp order by mlt.lastUpdated"; - objectIds = (List) db.doHQL(qThreadIDs, params); + objectIds = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(qThreadIDs, params); ids = new TreeSet(); ids.addAll(objectIds); IDs.put(MetricType.Type.MAILTHREAD, ids); String qBugIDs = "select b.id from Bug b where b.id not in (select ca.changedResourceId from ContribAction ca where developer.storedProject =:sp and ca.contribActionType.actionCategory='B') and b.project = :sp order by b.updateRun"; - objectIds = (List) db.doHQL(qBugIDs, params); + objectIds = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(qBugIDs, params); ids = new TreeSet(); ids.addAll(objectIds); IDs.put(MetricType.Type.BUG, ids); @@ -250,7 +251,7 @@ private ContribAction getResult(DAObject o) { parameters.put(paramActionCategory, ActionCategory.B.toString()); } - List lp = (List) db.doHQL(query, parameters, 1); + List lp = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters, 1); if (lp == null || lp.isEmpty()) { return null; @@ -553,7 +554,7 @@ private void updateField(DAObject o, Developer dev, isPositive); if (at == null) { - db.rollbackDBSession(); + db.getSessionManager().rollbackDBSession(); return; } @@ -577,7 +578,7 @@ else if (o instanceof Bug) else a.setChangedResourceTimestamp(null); //Make it fail - db.addRecord(a); + db.getQueryInterface().addRecord(a); } else { a.setTotal(a.getTotal() + value); } diff --git a/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribAction.java b/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribAction.java index e079a1340..66db72ed3 100644 --- a/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribAction.java +++ b/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribAction.java @@ -44,6 +44,7 @@ import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.Developer; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.StoredProject; public class ContribAction extends DAObject { @@ -113,7 +114,7 @@ public static ContribAction getContribAction(Developer dev, properties.put("changedResourceId", resourceId); properties.put("contribActionType", actionType); - List pa = dbs.findObjectsByProperties(ContribAction.class, properties); + List pa = dbs.getQueryInterface().findObjectsByProperties(ContribAction.class, properties); return pa.isEmpty() ? null : pa.get(0); } @@ -138,7 +139,7 @@ public static Long getDevActionsPerType(Developer dev, params.put(paramContribActionType, actionType); - List result = (List) dbs.doHQL(q.toString(),params); + List result = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(),params); if (!result.isEmpty()) { if (result.get(0) != null) @@ -169,7 +170,7 @@ public static Long getTotalActionsPerTypePerProject(StoredProject sp, params.put(paramProject, sp); params.put(paramContribActionType, actionType); - List result = (List) dbs.doHQL(q.toString(),params); + List result = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(),params); if (!result.isEmpty()) { if (result.get(0) != null) @@ -187,7 +188,7 @@ public static long getTotalActions(){ String query = "select sum(total) from ContribAction" ; - List totalActions = dbs.doHQL(query); + List totalActions = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query); if(totalActions == null || totalActions.size() == 0 || totalActions.get(0) == null) { @@ -210,7 +211,7 @@ public static long getTotalActionsPerCategory(ActionCategory ac) { Map parameters = new HashMap(); parameters.put(paramCategory, ac.toString()); - List totalActions = dbs.doHQL(query, parameters); + List totalActions = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters); if(totalActions == null || totalActions.size() == 0 || totalActions.get(0) == null) { @@ -234,7 +235,7 @@ public static long getTotalActionsPerType( Map parameters = new HashMap(); parameters.put(paramType, actionType.toString()); - List totalActions = dbs.doHQL(query, parameters); + List totalActions = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters); if(totalActions == null || totalActions.size() == 0 || totalActions.get(0) == null) { @@ -261,7 +262,7 @@ public static long getTotalActionsPerTypePerDeveloper(ActionType actionType, parameters.put(paramType, actionType.toString()); parameters.put(paramDeveloper, dev); - List totalActions = dbs.doHQL(query, parameters); + List totalActions = dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, parameters); if(totalActions == null || totalActions.size() == 0 || totalActions.get(0) == null) { diff --git a/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribActionType.java b/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribActionType.java index e3f60cf08..810b7b2b8 100644 --- a/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribActionType.java +++ b/metrics/contrib/src/main/java/eu/sqooss/metrics/contrib/db/ContribActionType.java @@ -42,6 +42,7 @@ import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.StoredProject; public class ContribActionType extends DAObject { @@ -126,7 +127,7 @@ public static List getProjectActionTypes(StoredProject sp, params.put(paramBefore, before); //params.put(paramCat, ac); - return (List) dbs.doHQL(q.toString(),params); + return (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(),params); } public static ContribActionType getContribActionType( @@ -138,7 +139,7 @@ public static ContribActionType getContribActionType( Map parameterMap = new HashMap(); parameterMap.put("actionType", actionType.toString()); - List atl = dbs.findObjectsByProperties( + List atl = dbs.getQueryInterface().findObjectsByProperties( ContribActionType.class, parameterMap); if (!atl.isEmpty()) @@ -152,7 +153,7 @@ public static ContribActionType getContribActionType( at.setType(actionType); at.setIsPositive(isPositive); - if (!dbs.addRecord(at)) { + if (!dbs.getQueryInterface().addRecord(at)) { return null; } return at; diff --git a/metrics/developermetrics/src/main/java/eu/sqooss/metrics/developermetrics/Developermetrics.java b/metrics/developermetrics/src/main/java/eu/sqooss/metrics/developermetrics/Developermetrics.java index a91916044..3ac1e236c 100644 --- a/metrics/developermetrics/src/main/java/eu/sqooss/metrics/developermetrics/Developermetrics.java +++ b/metrics/developermetrics/src/main/java/eu/sqooss/metrics/developermetrics/Developermetrics.java @@ -45,6 +45,7 @@ import eu.sqooss.service.abstractmetric.Result.ResultType; import eu.sqooss.service.db.Developer; import eu.sqooss.service.db.Directory; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Metric; import eu.sqooss.service.db.ProjectDirectory; import eu.sqooss.service.db.ProjectFile; @@ -107,17 +108,17 @@ public void run(ProjectVersion v) throws AlreadyProcessingException { Metric m = Metric.getMetricByMnemonic(MNEM_TEAMSIZE1); ProjectVersionMeasurement pvmOne = new ProjectVersionMeasurement( m, v, String.valueOf(commSize(v, oneMonth))); - db.addRecord(pvmOne); + db.getQueryInterface().addRecord(pvmOne); m = Metric.getMetricByMnemonic(MNEM_TEAMSIZE3); ProjectVersionMeasurement pvmThree = new ProjectVersionMeasurement( m, v, String.valueOf(commSize(v, threeMonths))); - db.addRecord(pvmThree); + db.getQueryInterface().addRecord(pvmThree); m = Metric.getMetricByMnemonic(MNEM_TEAMSIZE6); ProjectVersionMeasurement pvmSix = new ProjectVersionMeasurement( m, v, String.valueOf(commSize(v, sixMonths))); - db.addRecord(pvmSix); + db.getQueryInterface().addRecord(pvmSix); } private long commSize(ProjectVersion v, long ts) { @@ -126,7 +127,7 @@ private long commSize(ProjectVersion v, long ts) { params.put("paramOld", ts); params.put("paramProject", v.getProject()); - return (Long) db.doHQL(activeLast, params).get(0); + return (Long) db.getQueryInterface(HQLQueryInterface.class).doHQL(activeLast, params).get(0); } public List getResult(ProjectFile pf, Metric m) { @@ -156,7 +157,7 @@ public void run(ProjectFile a) throws AlreadyProcessingException { ProjectFileMeasurement pfm = new ProjectFileMeasurement(m, a, String.valueOf(eyeballs)); - db.addRecord(pfm); + db.getQueryInterface().addRecord(pfm); } private List fileEyeballs(ProjectFile a) { @@ -166,7 +167,7 @@ private List fileEyeballs(ProjectFile a) { params.put("paramProject", a.getProjectVersion().getProject()); params.put("paramFileId", a.getId()); - return (List) db.doHQL(fileEyeballs, params); + return (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(fileEyeballs, params); } } diff --git a/metrics/discussionheat/src/main/java/eu/sqooss/metrics/discussionheat/DiscussionHeat.java b/metrics/discussionheat/src/main/java/eu/sqooss/metrics/discussionheat/DiscussionHeat.java index af3c91300..f3a87cbd0 100644 --- a/metrics/discussionheat/src/main/java/eu/sqooss/metrics/discussionheat/DiscussionHeat.java +++ b/metrics/discussionheat/src/main/java/eu/sqooss/metrics/discussionheat/DiscussionHeat.java @@ -48,6 +48,7 @@ import eu.sqooss.service.abstractmetric.MetricMismatchException; import eu.sqooss.service.abstractmetric.Result; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.MailMessage; import eu.sqooss.service.db.MailingListThread; import eu.sqooss.service.db.MailingListThreadMeasurement; @@ -107,8 +108,8 @@ public void run(MailingListThread m) throws AlreadyProcessingException { Map params = new HashMap(); params.put("lst", m.getList()); - List thrDepths = (List)db.doHQL(thrDepth, params); - List mailsPerList = (List)db.doHQL(numMails, params); + List thrDepths = (List)db.getQueryInterface(HQLQueryInterface.class).doHQL(thrDepth, params); + List mailsPerList = (List)db.getQueryInterface(HQLQueryInterface.class).doHQL(numMails, params); //Get one day's worth of messages List msgs = m.getMessagesByArrivalOrder(); @@ -137,7 +138,7 @@ public void run(MailingListThread m) throws AlreadyProcessingException { MailingListThreadMeasurement mm = new MailingListThreadMeasurement( hotness, m, String.valueOf(score)); - dbs.addRecord(mm); + dbs.getQueryInterface().addRecord(mm); if (score < 6) return; @@ -155,7 +156,7 @@ public void run(MailingListThread m) throws AlreadyProcessingException { MailingListThreadMeasurement mltm = new MailingListThreadMeasurement( hoteffect, m, String.valueOf(result)); - dbs.addRecord(mltm); + dbs.getQueryInterface().addRecord(mltm); } private int getLocsForVersions(List versions) throws AlreadyProcessingException { @@ -219,7 +220,7 @@ private ProjectVersion getVersionByDate(Date ts, StoredProject sp) { Map params = new HashMap(); params.put("ts", ts.getTime()); params.put("sp", sp); - List vers = (List) dbs.doHQL(getPVbyDate, params, 1); + List vers = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(getPVbyDate, params, 1); if (vers.size() > 0) return vers.get(0); @@ -283,7 +284,7 @@ public void run(ProjectVersion pv) throws AlreadyProcessingException { ProjectVersionMeasurement pvm = new ProjectVersionMeasurement(m, pv, String.valueOf(linesChanged)); - dbs.addRecord(pvm); + dbs.getQueryInterface().addRecord(pvm); } private int getLOCResult(ProjectFile pf, AlitheiaPlugin plugin, diff --git a/metrics/findbugs/src/main/java/gr/aueb/metrics/findbugs/FindbugsMetrics.java b/metrics/findbugs/src/main/java/gr/aueb/metrics/findbugs/FindbugsMetrics.java index a31d5395c..909ff7ef7 100644 --- a/metrics/findbugs/src/main/java/gr/aueb/metrics/findbugs/FindbugsMetrics.java +++ b/metrics/findbugs/src/main/java/gr/aueb/metrics/findbugs/FindbugsMetrics.java @@ -502,8 +502,8 @@ private void storeResults(Map > results, versionMeasurements.add(new ProjectVersionMeasurement(m, pv, bugTotal.toString())); } } - db.addRecords(fileMeasurements); - db.addRecords(versionMeasurements); + db.getQueryInterface().addRecords(fileMeasurements); + db.getQueryInterface().addRecords(versionMeasurements); } private boolean pvMeasurementExists(ProjectVersion pv, Metric m) { @@ -516,7 +516,7 @@ private boolean pvMeasurementExists(ProjectVersion pv, Metric m) { parameters.put("metric", m); parameters.put("version", pv); - return db.doHQL(q, parameters).size() > 0; + return db.getQueryInterface(HQLQueryInterface.class).doHQL(q, parameters).size() > 0; } private ProjectFile findFile(List files, String path) { diff --git a/metrics/javametrics/src/main/java/eu/sqooss/metrics/java/JavaMetrics.java b/metrics/javametrics/src/main/java/eu/sqooss/metrics/java/JavaMetrics.java index e0ee2a7fc..cc3a78979 100644 --- a/metrics/javametrics/src/main/java/eu/sqooss/metrics/java/JavaMetrics.java +++ b/metrics/javametrics/src/main/java/eu/sqooss/metrics/java/JavaMetrics.java @@ -86,7 +86,7 @@ public void run(ExecutionUnit eu) throws Exception { public void run(ProjectVersion pv) throws Exception { db = AlitheiaCore.getInstance().getDBService(); - pv = db.attachObjectToDBSession(pv); + pv = db.getSessionManager().attachObjectToDBSession(pv); this.pv = pv; Pattern p = Pattern.compile("([^\\s]+(\\.(?i)(java))$)"); @@ -107,18 +107,18 @@ public void run(ProjectVersion pv) throws Exception { reducer = new ConcurrentHashMap(); for (ProjectFile pf : pv.getFiles(p)) try { - if(!db.isDBSessionActive()) db.startDBSession(); + if(!db.getSessionManager().isDBSessionActive()) db.getSessionManager().startDBSession(); parseFile(pf); } catch (Exception e) { } finally { - if(db.isDBSessionActive()) db.commitDBSession(); + if(db.getSessionManager().isDBSessionActive()) db.getSessionManager().commitDBSession(); } List changedClasses = new ArrayList(); for (ProjectFile pf : changedFiles) { - pf = db.attachObjectToDBSession(pf); + pf = db.getSessionManager().attachObjectToDBSession(pf); changedClasses.addAll(pf.getEncapsulationUnits()); } @@ -140,12 +140,12 @@ public void run(ProjectVersion pv) throws Exception { noc++; EncapsulationUnitMeasurement eum = new EncapsulationUnitMeasurement(clazz, DIT, String.valueOf(dit)); - db.addRecord(eum); + db.getQueryInterface().addRecord(eum); eum = new EncapsulationUnitMeasurement(clazz, NOC, String.valueOf(dit)); - db.addRecord(eum); + db.getQueryInterface().addRecord(eum); } - db.commitDBSession(); + db.getSessionManager().commitDBSession(); } protected void parseFile(ProjectFile pf) throws Exception { @@ -224,12 +224,12 @@ protected void parseFile(ProjectFile pf) throws Exception { ExecutionUnitMeasurement eum = new ExecutionUnitMeasurement( method, Metric.getMetricByMnemonic("MCCABE"), res.toString()); - db.addRecord(eum); + db.getQueryInterface().addRecord(eum); } EncapsulationUnitMeasurement eum = new EncapsulationUnitMeasurement(clazz, m, wmc.toString()); - db.addRecord(eum); + db.getQueryInterface().addRecord(eum); } // NUMM results @@ -238,7 +238,7 @@ protected void parseFile(ProjectFile pf) throws Exception { new EncapsulationUnitMeasurement(clazz, Metric.getMetricByMnemonic("NUMM"), clazz.getExecUnits().toString()); - db.addRecord(eum); + db.getQueryInterface().addRecord(eum); } } @@ -254,7 +254,7 @@ private void writeClassResults(Set classes, } EncapsulationUnitMeasurement eum = new EncapsulationUnitMeasurement(clazz, m, res.toString()); - db.addRecord(eum); + db.getQueryInterface().addRecord(eum); } } diff --git a/metrics/mi/src/main/java/eu/sqooss/metrics/mi/Mi.java b/metrics/mi/src/main/java/eu/sqooss/metrics/mi/Mi.java index 580de8aed..7738b171c 100644 --- a/metrics/mi/src/main/java/eu/sqooss/metrics/mi/Mi.java +++ b/metrics/mi/src/main/java/eu/sqooss/metrics/mi/Mi.java @@ -45,6 +45,7 @@ import eu.sqooss.service.abstractmetric.Result; import eu.sqooss.service.db.DAObject; import eu.sqooss.service.db.Directory; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Metric; import eu.sqooss.service.db.ProjectDirectory; import eu.sqooss.service.db.ProjectFile; @@ -99,7 +100,7 @@ public List getResult(ProjectFile pf, Metric m) { public void run(ProjectFile pf) throws AlreadyProcessingException { - pf = db.attachObjectToDBSession(pf); + pf = db.getSessionManager().attachObjectToDBSession(pf); /*MI works at the module level for src directories*/ if (!pf.getIsDirectory()) @@ -208,7 +209,7 @@ public void run(ProjectFile pf) throws AlreadyProcessingException { Metric m = Metric.getMetricByMnemonic(MNEMONIC_MODMI); ProjectFileMeasurement pfm = new ProjectFileMeasurement(m, pf, String.valueOf(MI)); - db.addRecord(pfm); + db.getQueryInterface().addRecord(pfm); } public List getResult(ProjectVersion pv, Metric m) { @@ -264,7 +265,7 @@ public void run(ProjectVersion pv) throws AlreadyProcessingException { // Get the list of folders which exist in this project version. List srcDirs = - (List) db.doHQL(q.toString(), params); + (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(), params); // Calculate the metric results double miTotal = 0; @@ -284,7 +285,7 @@ public void run(ProjectVersion pv) throws AlreadyProcessingException { metric, pv, String.valueOf(0)); ams.setResult(String.valueOf(((float) (miTotal / srcDirs.size())))); - db.addRecord(ams); + db.getQueryInterface().addRecord(ams); } } diff --git a/metrics/modulemetrics/src/main/java/eu/sqooss/metrics/modulemetrics/ModuleMetricsImplementation.java b/metrics/modulemetrics/src/main/java/eu/sqooss/metrics/modulemetrics/ModuleMetricsImplementation.java index 33c4eaaef..3244121e8 100644 --- a/metrics/modulemetrics/src/main/java/eu/sqooss/metrics/modulemetrics/ModuleMetricsImplementation.java +++ b/metrics/modulemetrics/src/main/java/eu/sqooss/metrics/modulemetrics/ModuleMetricsImplementation.java @@ -49,6 +49,7 @@ import eu.sqooss.service.abstractmetric.MetricDeclarations; import eu.sqooss.service.abstractmetric.Result; import eu.sqooss.service.db.Directory; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Metric; import eu.sqooss.service.db.ProjectDirectory; import eu.sqooss.service.db.ProjectFile; @@ -136,17 +137,17 @@ public void run(ProjectFile pf) throws AlreadyProcessingException { Metric m = Metric.getMetricByMnemonic(MET_ISSRCMOD); ProjectFileMeasurement pfm = new ProjectFileMeasurement(m, pf, String.valueOf(1)); - db.addRecord(pfm); + db.getQueryInterface().addRecord(pfm); m = Metric.getMetricByMnemonic(MET_MNOL); pfm = new ProjectFileMeasurement(m, pf, String.valueOf(mnol)); - db.addRecord(pfm); + db.getQueryInterface().addRecord(pfm); m = Metric.getMetricByMnemonic(MET_MNOF); pfm = new ProjectFileMeasurement(m, pf, String.valueOf(mnof)); - db.addRecord(pfm); + db.getQueryInterface().addRecord(pfm); } } @@ -198,7 +199,7 @@ public void run(ProjectVersion pv) throws AlreadyProcessingException { // Get the list of folders which exist in this project version. List srcDirs = - (List) db.doHQL(q.toString(), params); + (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(), params); // Calculate the metric results int locs = 0; @@ -219,7 +220,7 @@ public void run(ProjectVersion pv) throws AlreadyProcessingException { metric, pv, String.valueOf(0)); ams.setResult(String.valueOf(((float) (locs / srcDirs.size())))); - db.addRecord(ams); + db.getQueryInterface().addRecord(ams); } } diff --git a/metrics/structural/src/main/java/eu/sqooss/metrics/structural/Structural.java b/metrics/structural/src/main/java/eu/sqooss/metrics/structural/Structural.java index ab12f9050..d2bb62dcb 100644 --- a/metrics/structural/src/main/java/eu/sqooss/metrics/structural/Structural.java +++ b/metrics/structural/src/main/java/eu/sqooss/metrics/structural/Structural.java @@ -177,7 +177,7 @@ public void run(ProjectFile pf) { return; } - pf = db.attachObjectToDBSession(pf); + pf = db.getSessionManager().attachObjectToDBSession(pf); this.fileDAO.set(pf); FDSService fds = AlitheiaCore.getInstance().getFDSService(); @@ -621,7 +621,7 @@ private Set uniq(List arlList) { private void addRecord(String mnem, ProjectFile pf, String value) { Metric m = Metric.getMetricByMnemonic(mnem); ProjectFileMeasurement pfm = new ProjectFileMeasurement(m, pf, value); - db.addRecord(pfm); + db.getQueryInterface().addRecord(pfm); } } diff --git a/metrics/testability/src/main/java/eu/sqooss/metrics/testability/TestabilityImplementation.java b/metrics/testability/src/main/java/eu/sqooss/metrics/testability/TestabilityImplementation.java index f3efba83a..d5380b6e6 100644 --- a/metrics/testability/src/main/java/eu/sqooss/metrics/testability/TestabilityImplementation.java +++ b/metrics/testability/src/main/java/eu/sqooss/metrics/testability/TestabilityImplementation.java @@ -151,7 +151,7 @@ public void run(ProjectFile pf) { Metric metric = Metric.getMetricByMnemonic(MNEMONIC_NCASES); ProjectFileMeasurement ncases = new ProjectFileMeasurement( metric,pf,String.valueOf(numTestCases)); - db.addRecord(ncases); + db.getQueryInterface().addRecord(ncases); } catch (IOException e) { log.error(this.getClass().getName() + " IO Error <" + e + "> while measuring: " + pf.getFileName()); diff --git a/metrics/wc/src/main/java/eu/sqooss/metrics/wc/WcImplementation.java b/metrics/wc/src/main/java/eu/sqooss/metrics/wc/WcImplementation.java index 6a5b630d3..bff808864 100644 --- a/metrics/wc/src/main/java/eu/sqooss/metrics/wc/WcImplementation.java +++ b/metrics/wc/src/main/java/eu/sqooss/metrics/wc/WcImplementation.java @@ -53,6 +53,7 @@ import eu.sqooss.service.abstractmetric.MetricDecl; import eu.sqooss.service.abstractmetric.MetricDeclarations; import eu.sqooss.service.abstractmetric.Result; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Metric; import eu.sqooss.service.db.ProjectFile; import eu.sqooss.service.db.ProjectFileMeasurement; @@ -120,7 +121,7 @@ public List getResult(ProjectFile a, Metric m) { filter.put("projectFile", a); filter.put("metric", m); List measurement = - db.findObjectsByProperties(ProjectFileMeasurement.class, filter); + db.getQueryInterface().findObjectsByProperties(ProjectFileMeasurement.class, filter); for (ProjectFileMeasurement pfm : measurement) results.add(new Result(a, m, pfm.getResult(), Result.ResultType.INTEGER)); @@ -252,25 +253,25 @@ public void run(ProjectFile pf) { Metric metric = Metric.getMetricByMnemonic(MNEMONIC_WC_LOC); ProjectFileMeasurement locm = new ProjectFileMeasurement( metric,pf,String.valueOf(results[0])); - db.addRecord(locm); + db.getQueryInterface().addRecord(locm); toUpdate.add(metric); metric = Metric.getMetricByMnemonic(MNEMONIC_WC_LOCOM); ProjectFileMeasurement locc = new ProjectFileMeasurement( metric,pf,String.valueOf(results[1])); - db.addRecord(locc); + db.getQueryInterface().addRecord(locc); toUpdate.add(metric); metric = Metric.getMetricByMnemonic(MNEMONIC_WC_LONB); ProjectFileMeasurement lonb = new ProjectFileMeasurement( metric,pf,String.valueOf(results[2])); - db.addRecord(lonb); + db.getQueryInterface().addRecord(lonb); toUpdate.add(metric); metric = Metric.getMetricByMnemonic(MNEMONIC_WC_WORDS); ProjectFileMeasurement words_measure = new ProjectFileMeasurement( metric,pf,String.valueOf(results[3])); - db.addRecord(words_measure); + db.getQueryInterface().addRecord(words_measure); toUpdate.add(metric); } @@ -390,7 +391,7 @@ public List getResult(ProjectVersion p, Metric m) { filter.put("projectVersion", p); filter.put("metric", m); List measurement = - db.findObjectsByProperties(ProjectVersionMeasurement.class, filter); + db.getQueryInterface().findObjectsByProperties(ProjectVersionMeasurement.class, filter); for (ProjectVersionMeasurement pfm : measurement) results.add(new Result(p, m, pfm.getResult(), Result.ResultType.INTEGER)); @@ -440,7 +441,7 @@ public void run(ProjectVersion v) throws AlreadyProcessingException { params.put(paramState, ProjectFileState.deleted()); List results = - (List) db.doHQL(q.toString(), params); + (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(q.toString(), params); long nof = 0; //Number of files int nosf = 0; //Number of source code files @@ -488,7 +489,7 @@ private Metric addPVMeasurement(String s, ProjectVersion pv, int value) { Metric m = Metric.getMetricByMnemonic(s); ProjectVersionMeasurement pvm = new ProjectVersionMeasurement(m , pv, String.valueOf(value)); - db.addRecord(pvm); + db.getQueryInterface().addRecord(pvm); return m; } } diff --git a/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaUpdater.java b/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaUpdater.java index 0a9849965..0332dd81e 100644 --- a/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaUpdater.java +++ b/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaUpdater.java @@ -87,8 +87,8 @@ public int progress() { @Override public void update() throws Exception { jobCounter = new AtomicInteger(); - dbs.startDBSession(); - project = dbs.attachObjectToDBSession(project); + dbs.getSessionManager().startDBSession(); + project = dbs.getSessionManager().attachObjectToDBSession(project); Scheduler s = AlitheiaCore.getInstance().getScheduler(); @@ -124,8 +124,8 @@ public void update() throws Exception { } catch(InterruptedException ignored){} } - if (dbs.isDBSessionActive()) - dbs.commitDBSession(); + if (dbs.getSessionManager().isDBSessionActive()) + dbs.getSessionManager().commitDBSession(); } @Override diff --git a/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaXMLJob.java b/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaXMLJob.java index 56eecbd2f..8279ec156 100644 --- a/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaXMLJob.java +++ b/plug-ins/bugzilla/src/main/java/eu/sqooss/plugins/bugzilla/BugzillaXMLJob.java @@ -79,11 +79,11 @@ public long priority() { @Override protected void run() throws Exception { - if (!dbs.isDBSessionActive()) - dbs.startDBSession(); + if (!dbs.getSessionManager().isDBSessionActive()) + dbs.getSessionManager().startDBSession(); BTSAccessor bts = AlitheiaCore.getInstance().getTDSService().getAccessor( project.getId()).getBTSAccessor(); - project = dbs.attachObjectToDBSession(project); + project = dbs.getSessionManager().attachObjectToDBSession(project); Bug bug = BTSEntryToBug(bts.getBug(bugID)); @@ -117,9 +117,9 @@ protected void run() throws Exception { bug.setReportMessages(toadd); } - dbs.addRecord(bug); + dbs.getQueryInterface().addRecord(bug); logger.debug(project.getName() + ": Added bug " + bugID); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); } @@ -204,7 +204,7 @@ private boolean bugExists(StoredProject sp, String bugId) { params.put("project", sp); params.put("bugID", bugId); - List buglist = dbs.findObjectsByProperties(Bug.class, params); + List buglist = dbs.getQueryInterface().findObjectsByProperties(Bug.class, params); if (buglist.isEmpty()) return false; diff --git a/plug-ins/devmatcher/src/main/java/eu/sqooss/plugins/devmatcher/DeveloperMatcher.java b/plug-ins/devmatcher/src/main/java/eu/sqooss/plugins/devmatcher/DeveloperMatcher.java index 027696d5d..37fae92c3 100644 --- a/plug-ins/devmatcher/src/main/java/eu/sqooss/plugins/devmatcher/DeveloperMatcher.java +++ b/plug-ins/devmatcher/src/main/java/eu/sqooss/plugins/devmatcher/DeveloperMatcher.java @@ -41,6 +41,7 @@ import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.Developer; import eu.sqooss.service.db.DeveloperAlias; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.StoredProject; import eu.sqooss.service.logging.Logger; import eu.sqooss.service.updater.MetadataUpdater; @@ -92,12 +93,12 @@ public void setUpdateParams(StoredProject arg0, Logger arg1) { @Override public void update() throws Exception { - dbs.startDBSession(); - project = dbs.attachObjectToDBSession(project); + dbs.getSessionManager().startDBSession(); + project = dbs.getSessionManager().attachObjectToDBSession(project); DoubleMetaphone dm = new DoubleMetaphone(); Map params = new HashMap(); params.put("storedProject", project); - List devs = dbs.findObjectsByPropertiesForUpdate(Developer.class, params); + List devs = dbs.getQueryInterface().findObjectsByPropertiesForUpdate(Developer.class, params); long ts = System.currentTimeMillis(); //Fill in indices for (Developer d : devs) { @@ -211,13 +212,13 @@ public void update() throws Exception { } for (String upd : updates) { - long lines = dbs.executeUpdate(upd, updParam); + long lines = dbs.getQueryInterface(HQLQueryInterface.class).executeUpdate(upd, updParam); debug(upd + " old:" + byEmail + " new:" + byUsrName + " " + lines + " changed"); } for (String del : deletes) { - long lines = dbs.executeUpdate(del, delParam); + long lines = dbs.getQueryInterface(HQLQueryInterface.class).executeUpdate(del, delParam); debug(del + " old:" + byEmail.getId() + lines + " changed"); } @@ -227,7 +228,7 @@ public void update() throws Exception { info("Matched " + matches.size() + " developers in " + (System.currentTimeMillis() - ts) + "ms"); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); progress = 100; } diff --git a/plug-ins/git/src/main/java/eu/sqooss/plugins/updater/git/GitUpdater.java b/plug-ins/git/src/main/java/eu/sqooss/plugins/updater/git/GitUpdater.java index 00ad047e2..b91c99de5 100644 --- a/plug-ins/git/src/main/java/eu/sqooss/plugins/updater/git/GitUpdater.java +++ b/plug-ins/git/src/main/java/eu/sqooss/plugins/updater/git/GitUpdater.java @@ -150,8 +150,8 @@ public void setUpdateParams(StoredProject sp, Logger l) { public void update() throws Exception { - dbs.startDBSession(); - project = dbs.attachObjectToDBSession(project); + dbs.getSessionManager().startDBSession(); + project = dbs.getSessionManager().attachObjectToDBSession(project); info("Running source update for project " + project.getName() @@ -167,7 +167,7 @@ public void update() throws Exception { if (r.compareTo(git.newRevision(latestVersion.getRevisionId())) <= 0) { info("Project is already at the newest version: " + r.getUniqueId()); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); return; } next = git.newRevision(latestVersion.getRevisionId()); @@ -188,7 +188,7 @@ public void updateFromTo(Revision from, Revision to) int numRevisions = 0; CommitLog commitLog = git.getCommitLog("", from, to); - if(!dbs.isDBSessionActive()) dbs.startDBSession(); + if(!dbs.getSessionManager().isDBSessionActive()) dbs.getSessionManager().startDBSession(); for (Revision entry : commitLog) { if (ProjectVersion.getVersionByRevision(project, entry.getUniqueId()) != null) { @@ -206,12 +206,12 @@ public void updateFromTo(Revision from, Revision to) updateValidUntil(pv, pv.getVersionFiles()); - if (!dbs.commitDBSession()) { + if (!dbs.getSessionManager().commitDBSession()) { warn("Intermediate commit failed, failing update"); return; } - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); progress = (float) (((double)numRevisions / (double)commitLog.size()) * 100); numRevisions++; @@ -236,14 +236,14 @@ private ProjectVersion processOneRevision(Revision entry) pv.setCommitMsg(commitMsg); pv.setSequence(Integer.MAX_VALUE); - dbs.addRecord(pv); + dbs.getQueryInterface().addRecord(pv); //Tags String tag = git.allTags().get(entry.getUniqueId()); if (tag != null) { Tag t = new Tag(pv); t.setName(tag); - dbs.addRecord(t); + dbs.getQueryInterface().addRecord(t); pv.getTags().add(t); } @@ -263,7 +263,7 @@ private ProjectVersion processOneRevision(Revision entry) //Parent is a branch if (git.getCommitChidren(parentId).length > 1) { Branch b = new Branch(project, Branch.suggestName(project)); - dbs.addRecord(b); + dbs.getQueryInterface().addRecord(b); parent.getOutgoingBranches().add(b); pv.getIncomingBranches().add(b); } else { @@ -279,7 +279,7 @@ private ProjectVersion processOneRevision(Revision entry) //New line of development if (entry.getParentIds().size() == 0) { Branch b = new Branch(project, Branch.suggestName(project)); - dbs.addRecord(b); + dbs.getQueryInterface().addRecord(b); pv.getOutgoingBranches().add(b); } else { pv.getOutgoingBranches().addAll(pv.getIncomingBranches()); diff --git a/plug-ins/git/src/test/java/eu/sqooss/plugins/git/test/TestGitUpdater.java b/plug-ins/git/src/test/java/eu/sqooss/plugins/git/test/TestGitUpdater.java index c156b2c65..9ded015f6 100644 --- a/plug-ins/git/src/test/java/eu/sqooss/plugins/git/test/TestGitUpdater.java +++ b/plug-ins/git/src/test/java/eu/sqooss/plugins/git/test/TestGitUpdater.java @@ -99,11 +99,11 @@ public static void setup() throws IOException, URISyntaxException { AlitheiaCore.testInstance(); db = new DBServiceImpl(conProp, config.toURL() , l); - db.startDBSession(); + db.getSessionManager().startDBSession(); sp = new StoredProject(); sp.setName(projectName); - db.addRecord(sp); - db.commitDBSession(); + db.getQueryInterface().addRecord(sp); + db.getSessionManager().commitDBSession(); } @Before @@ -115,7 +115,7 @@ public void setUp() throws AccessorException, URISyntaxException { @Test public void testGetAuthor() { - db.startDBSession(); + db.getSessionManager().startDBSession(); //Test a properly formatted name Developer d = updater.getAuthor(sp, "Papa Smurf "); @@ -159,7 +159,7 @@ public void testGetAuthor() { assertNull(d.getName()); assertEquals(1, d.getAliases().size()); - db.rollbackDBSession(); + db.getSessionManager().rollbackDBSession(); } @Test @@ -184,8 +184,8 @@ public void testUpdate() throws Exception { tw.addTree(commit.getTree()); tw.setRecursive(true); - db.startDBSession(); - sp = db.attachObjectToDBSession(sp); + db.getSessionManager().startDBSession(); + sp = db.getSessionManager().attachObjectToDBSession(sp); ProjectVersion pv = ProjectVersion.getVersionByRevision(sp, from.getUniqueId()); assertNotNull(pv); @@ -216,7 +216,7 @@ public void testUpdate() throws Exception { } } - db.commitDBSession(); + db.getSessionManager().commitDBSession(); tw.release(); rw.release(); from = to; diff --git a/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdater.java b/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdater.java index 149cfc9cf..e540aed3c 100644 --- a/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdater.java +++ b/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdater.java @@ -9,6 +9,7 @@ import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.Language; import eu.sqooss.service.db.ProjectVersion; import eu.sqooss.service.db.StoredProject; @@ -58,11 +59,11 @@ public void setUpdateParams(StoredProject sp, Logger l) { } public void update() throws Exception { - db.startDBSession(); + db.getSessionManager().startDBSession(); Map params = new HashMap(); params.put("sp", sp); - List toProcess = (List) db.doHQL(notProcessed, params); + List toProcess = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(notProcessed, params); if (toProcess.size() == 0) { log.info("No versions to process"); @@ -87,7 +88,7 @@ public void update() throws Exception { } catch(InterruptedException ignored){} } - if (db.isDBSessionActive())db.commitDBSession(); + if (db.getSessionManager().isDBSessionActive())db.getSessionManager().commitDBSession(); } public void jobStateChanged(Job j, State newState) { diff --git a/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdaterJob.java b/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdaterJob.java index 7e3f0b058..1660b90d6 100644 --- a/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdaterJob.java +++ b/plug-ins/javaparser/src/main/java/eu/sqooss/plugins/javaparser/JavaUpdaterJob.java @@ -62,9 +62,9 @@ public long priority() { @Override protected void run() throws Exception { - db.startDBSession(); - sp = db.attachObjectToDBSession(sp); - pv = db.attachObjectToDBSession(pv); + db.getSessionManager().startDBSession(); + sp = db.getSessionManager().attachObjectToDBSession(sp); + pv = db.getSessionManager().attachObjectToDBSession(pv); Pattern p = Pattern.compile(".*\\.java$"); FDSService fds = AlitheiaCore.getInstance().getFDSService(); @@ -125,7 +125,7 @@ protected void run() throws Exception { ns.setName(ee.getPackageName()); ns.setChangeVersion(pf.getProjectVersion()); ns.setLang(Language.JAVA); - db.addRecord(ns); + db.getQueryInterface().addRecord(ns); } for (String clazz : ee.getResults().keySet()) { @@ -134,7 +134,7 @@ protected void run() throws Exception { eu.setName(clazz); eu.setNamespace(ns); eu.setFile(pf); - db.addRecord(eu); + db.getQueryInterface().addRecord(eu); for (CodeFragment fragment : ee.getResults().get(clazz)) { ExecutionUnit exu = new ExecutionUnit(eu); @@ -148,11 +148,11 @@ protected void run() throws Exception { pf.getProjectVersion().toString()); exu.setChanged(true); } - db.addRecord(exu); + db.getQueryInterface().addRecord(exu); } } } - db.commitDBSession(); + db.getSessionManager().commitDBSession(); } private List getChangedMethods(EntityExtractor ee, ProjectFile pf, diff --git a/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailDirUpdater.java b/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailDirUpdater.java index f902e82b2..25dea6cf1 100644 --- a/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailDirUpdater.java +++ b/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailDirUpdater.java @@ -97,7 +97,7 @@ public void update() throws Exception { List listIds = Collections.emptyList(); try { //Process mailing lists first - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); listIds = processMailingLists(mailAccessor); for (Long mlId : listIds) { @@ -107,7 +107,7 @@ public void update() throws Exception { } if (total == 0) { - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); return; } @@ -145,7 +145,7 @@ private List processMailingLists(MailAccessor mailAccessor) { MailingList nml = new MailingList(); nml.setListId(listId); nml.setStoredProject(project); - dbs.addRecord(nml); + dbs.getQueryInterface().addRecord(nml); } } List listIds = new ArrayList(); @@ -161,7 +161,7 @@ private List processMailingLists(MailAccessor mailAccessor) { private List getMailingLists(StoredProject sp) { Map params = new HashMap(); params.put("storedProject", sp); - return dbs.findObjectsByProperties(MailingList.class, params); + return dbs.getQueryInterface().findObjectsByProperties(MailingList.class, params); } @Override diff --git a/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailMessageJob.java b/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailMessageJob.java index 11af8e2fc..a6497c426 100644 --- a/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailMessageJob.java +++ b/plug-ins/maildir/src/main/java/eu/sqooss/plugins/maildir/MailMessageJob.java @@ -81,9 +81,9 @@ public long priority() { protected void run() throws Exception { DBService dbs = AlitheiaCore.getInstance().getDBService(); - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); - ml = dbs.attachObjectToDBSession(ml); + ml = dbs.getSessionManager().attachObjectToDBSession(ml); project = ml.getStoredProject(); ProjectAccessor spAccessor = AlitheiaCore.getInstance().getTDSService().getAccessor(project.getId()); @@ -188,10 +188,10 @@ protected void run() throws Exception { mmsg.setSubject(subject); mmsg.setFilename(fileName); - dbs.addRecord(mmsg); + dbs.getQueryInterface().addRecord(mmsg); debug("Adding message " + mm.getMessageID()); - if (dbs.commitDBSession()) { + if (dbs.getSessionManager().commitDBSession()) { if (!mailAccessor.markMessageAsSeen(ml.getListId(), fileName)) warn("Failed to mark message <" + fileName diff --git a/plug-ins/mailthreadresolver/src/main/java/eu/sqooss/plugins/mailthreadresolver/MailThreadResolver.java b/plug-ins/mailthreadresolver/src/main/java/eu/sqooss/plugins/mailthreadresolver/MailThreadResolver.java index ffc502be8..651222269 100755 --- a/plug-ins/mailthreadresolver/src/main/java/eu/sqooss/plugins/mailthreadresolver/MailThreadResolver.java +++ b/plug-ins/mailthreadresolver/src/main/java/eu/sqooss/plugins/mailthreadresolver/MailThreadResolver.java @@ -37,8 +37,11 @@ import javax.mail.internet.MimeMessage; +import org.hibernate.hql.ast.HqlASTFactory; + import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.db.DBService; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.MailMessage; import eu.sqooss.service.db.MailingList; import eu.sqooss.service.db.MailingListThread; @@ -88,14 +91,14 @@ public void setUpdateParams(StoredProject sp, Logger l) { @Override public void update() throws Exception { dbs = AlitheiaCore.getInstance().getDBService(); - dbs.startDBSession(); - sp = dbs.attachObjectToDBSession(sp); + dbs.getSessionManager().startDBSession(); + sp = dbs.getSessionManager().attachObjectToDBSession(sp); lists = sp.getMailingLists(); for (MailingList l : lists) { this.ml = l; realupdate(); } - if (dbs.isDBSessionActive())dbs.commitDBSession(); + if (dbs.getSessionManager().isDBSessionActive())dbs.getSessionManager().commitDBSession(); } @Override @@ -104,8 +107,8 @@ public int progress() { } private void realupdate() throws Exception { - if (!dbs.isDBSessionActive()) dbs.startDBSession(); - ml = dbs.attachObjectToDBSession(ml); + if (!dbs.getSessionManager().isDBSessionActive()) dbs.getSessionManager().startDBSession(); + ml = dbs.getSessionManager().attachObjectToDBSession(ml); int newThreads = 0, updatedThreads = 0, processedEmails = 0; MailMessage lastEmail = null; lastEmail = ml.getLatestEmail(); @@ -113,7 +116,7 @@ private void realupdate() throws Exception { if (lastEmail == null) { info("No mail messages for list " + ml); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); return; //No messages for this mailing list } @@ -128,17 +131,17 @@ private void realupdate() throws Exception { Map params = new HashMap(1); params.put(paramMl, ml); - List mmList = (List) dbs.doHQL(query, params); + List mmList = (List) dbs.getQueryInterface(HQLQueryInterface.class).doHQL(query, params); if (mmList.isEmpty()) { info("No unprocessed mail messages found for list " + ml); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); return; } for (Long mailId : mmList) { - if (!dbs.isDBSessionActive()) - dbs.startDBSession(); + if (!dbs.getSessionManager().isDBSessionActive()) + dbs.getSessionManager().startDBSession(); MailMessage mail = MailMessage.loadDAObyId(mailId, MailMessage.class); // Message has been already added to thread @@ -267,7 +270,7 @@ private void realupdate() throws Exception { /* Create a new thread */ mlt = new MailingListThread(ml, mail.getSendDate()); - dbs.addRecord(mlt); + dbs.getQueryInterface().addRecord(mlt); mail.setThread(mlt); mail.setDepth(0); debug("Adding new thread " + mlt.getId()); @@ -276,16 +279,16 @@ private void realupdate() throws Exception { if (mail.getThread() == null) warn("Mail message " + mail + " was not assigned any thread"); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); processedEmails ++; progress = (float)((double)processedEmails / (double)mmList.size()) * 100; } - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); info("Mail thread updater - " + ml.getListId() + " " + processedEmails + " new emails, " + newThreads + " new threads, " + updatedThreads + " thread updates" ); - if (dbs.isDBSessionActive()) dbs.commitDBSession(); + if (dbs.getSessionManager().isDBSessionActive()) dbs.getSessionManager().commitDBSession(); } @Override diff --git a/plug-ins/moduleresolver/src/main/java/eu/sqooss/plugins/moduleresolver/ModuleResolver.java b/plug-ins/moduleresolver/src/main/java/eu/sqooss/plugins/moduleresolver/ModuleResolver.java index 78bee23d3..844a0edef 100644 --- a/plug-ins/moduleresolver/src/main/java/eu/sqooss/plugins/moduleresolver/ModuleResolver.java +++ b/plug-ins/moduleresolver/src/main/java/eu/sqooss/plugins/moduleresolver/ModuleResolver.java @@ -7,6 +7,7 @@ import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.db.DBService; import eu.sqooss.service.db.Directory; +import eu.sqooss.service.db.HQLQueryInterface; import eu.sqooss.service.db.ProjectFile; import eu.sqooss.service.db.ProjectVersion; import eu.sqooss.service.db.StoredProject; @@ -45,11 +46,11 @@ public void setUpdateParams(StoredProject sp, Logger l) { @Override public void update() throws Exception { - db.startDBSession(); + db.getSessionManager().startDBSession(); Map params = new HashMap(); params.put("sp", sp); - List toProcess = (List) db.doHQL(notProcessed, params); + List toProcess = (List) db.getQueryInterface(HQLQueryInterface.class).doHQL(notProcessed, params); if (toProcess.size() == 0) { log.info("No versions to process"); @@ -59,8 +60,8 @@ public void update() throws Exception { int i = 0; for (ProjectVersion pv : toProcess) { i ++; - if (!db.isDBSessionActive()) db.startDBSession(); - pv = db.attachObjectToDBSession(pv); + if (!db.getSessionManager().isDBSessionActive()) db.getSessionManager().startDBSession(); + pv = db.getSessionManager().attachObjectToDBSession(pv); log.info("ModuleResolver: Processing version: " + pv); for (ProjectFile pf : pv.allDirs()) { @@ -82,7 +83,7 @@ public void update() throws Exception { pf.setModule(false); } progress = ((float)i / (float)toProcess.size()); - db.commitDBSession(); + db.getSessionManager().commitDBSession(); } } diff --git a/plug-ins/svn/src/main/java/eu/sqooss/plugins/updater/svn/SVNUpdaterImpl.java b/plug-ins/svn/src/main/java/eu/sqooss/plugins/updater/svn/SVNUpdaterImpl.java index 32e1a05a5..139569e45 100644 --- a/plug-ins/svn/src/main/java/eu/sqooss/plugins/updater/svn/SVNUpdaterImpl.java +++ b/plug-ins/svn/src/main/java/eu/sqooss/plugins/updater/svn/SVNUpdaterImpl.java @@ -172,8 +172,8 @@ public int progress() { @Override public void update() throws Exception { - dbs.startDBSession(); - project = dbs.attachObjectToDBSession(project); + dbs.getSessionManager().startDBSession(); + project = dbs.getSessionManager().attachObjectToDBSession(project); init(); @@ -195,7 +195,7 @@ public void update() throws Exception { if (r.compareTo(scm.newRevision(latestVersion.getRevisionId())) <= 0) { info("Project is already at the newest version " + r.getUniqueId()); - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); return; } } else { @@ -206,7 +206,7 @@ public void update() throws Exception { zero.setCommitMsg("Artificial revision to include / directory"); zero.setRevisionId("0"); zero.setSequence(0); - dbs.addRecord(zero); + dbs.getQueryInterface().addRecord(zero); ProjectFile root = new ProjectFile(zero); root.setIsDirectory(true); root.setDir(getDirectory("/", true)); @@ -214,9 +214,9 @@ public void update() throws Exception { root.setState(ProjectFileState.added()); root.setValidFrom(zero); root.setValidUntil(zero); - dbs.addRecord(root); - dbs.commitDBSession(); - dbs.startDBSession(); + dbs.getQueryInterface().addRecord(root); + dbs.getSessionManager().commitDBSession(); + dbs.getSessionManager().startDBSession(); latestVersion = ProjectVersion.getLastProjectVersion(project); } commitLog = scm.getCommitLog("", scm.getNextRevision( @@ -274,8 +274,8 @@ public void update() throws Exception { } else { debug(msg + ". Removing"); //dbs.deleteRecord(curVersion); - dbs.rollbackDBSession(); - dbs.startDBSession(); + dbs.getSessionManager().rollbackDBSession(); + dbs.getSessionManager().startDBSession(); continue; } } @@ -283,19 +283,19 @@ public void update() throws Exception { /* * Add files to the database */ - dbs.addRecords(versionFiles); + dbs.getQueryInterface().addRecords(versionFiles); updateValidUntil(curVersion); numRevisions++; dirCache.clear(); - if (!dbs.commitDBSession()) { + if (!dbs.getSessionManager().commitDBSession()) { warn("Intermediate commit failed, failing update"); //restart(); return; } - dbs.startDBSession(); + dbs.getSessionManager().startDBSession(); progress = (float) (((double)numRevisions / (double)commitLog.size()) * 100); } info("Processed " + numRevisions + " revisions"); @@ -306,7 +306,7 @@ public void update() throws Exception { err("Not such repository revision:" + e.getMessage()); throw e; } - dbs.commitDBSession(); + dbs.getSessionManager().commitDBSession(); } private void init() { @@ -387,12 +387,12 @@ private ProjectVersion processCommit(SCMAccessor scm, Revision entry) { curVersion.setCommitMsg(commitMsg); curVersion.setSequence(Integer.MAX_VALUE); - dbs.addRecord(curVersion); + dbs.getQueryInterface().addRecord(curVersion); ProjectVersion prev = curVersion.getPreviousVersion(); curVersion.setSequence(prev.getSequence() + 1); ProjectVersionParent pvp = new ProjectVersionParent(curVersion, prev); - dbs.addRecord(pvp); + dbs.getQueryInterface().addRecord(pvp); debug("Got version " + curVersion.getRevisionId() + " ID " + curVersion.getId()); @@ -424,13 +424,13 @@ private ProjectVersion processCommit(SCMAccessor scm, Revision entry) { Branch b = new Branch(project, FileUtils.basename(copyOp.toPath())); b.getBranchIncoming().add(prev); b.getBranchOutgoing().add(curVersion); - dbs.addRecord(b); + dbs.getQueryInterface().addRecord(b); } if (dirname.equals(tagsPath) || dirname.equals(tagsPath + "/")) { Tag tag = new Tag(curVersion); tag.setName(FileUtils.basename(copyOp.toPath())); - dbs.addRecord(tag); + dbs.getQueryInterface().addRecord(tag); } } diff --git a/pom.xml b/pom.xml index 12683f1ee..988922e5f 100644 --- a/pom.xml +++ b/pom.xml @@ -246,6 +246,8 @@ maven-surefire-plugin 2.7.1 + + ${surefireArgLine} false