diff --git a/rudder-core/pom.xml b/rudder-core/pom.xml index 31e4078d704..5bff77d1b07 100644 --- a/rudder-core/pom.xml +++ b/rudder-core/pom.xml @@ -229,11 +229,6 @@ along with Rudder. If not, see . ${spring-version} test - - org.springframework - spring-jdbc - ${spring-version} - diff --git a/rudder-core/src/main/scala/com/normation/rudder/db/Doobie.scala b/rudder-core/src/main/scala/com/normation/rudder/db/Doobie.scala index 7aec8437795..9ac8bd6db3f 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/db/Doobie.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/db/Doobie.scala @@ -123,6 +123,16 @@ object Doobie { case \/-(a) => Full(a) } } + implicit def xorBoxToBox[A](res: \/[Throwable, Box[A]]): Box[A] = res match { + case -\/(e) => Failure(e.getMessage, Full(e), Empty) + case \/-(a) => a + } + implicit class XorBoxToBox[A](res: \/[Throwable, Box[A]]) { + def box = res match { + case -\/(e) => Failure(e.getMessage, Full(e), Empty) + case \/-(a) => a + } + } /* * Doobie is missing a Query0 builder, so here is simple one. diff --git a/rudder-core/src/main/scala/com/normation/rudder/migration/XmlFileFormatMigration_5_6.scala b/rudder-core/src/main/scala/com/normation/rudder/migration/XmlFileFormatMigration_5_6.scala index c57ba4390c0..5e03c71c8f1 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/migration/XmlFileFormatMigration_5_6.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/migration/XmlFileFormatMigration_5_6.scala @@ -39,14 +39,12 @@ package com.normation.rudder.migration import scala.xml.Elem -import org.springframework.jdbc.core.JdbcTemplate import com.normation.rudder.domain.Constants import com.normation.rudder.services.marshalling.TestFileFormat import net.liftweb.common.Box import net.liftweb.util.Helpers.StringToCssBindPromoter -import net.liftweb.util.Helpers.tryo import com.normation.rudder.db.Doobie /** diff --git a/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ChangeRequestJdbcRepository.scala b/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ChangeRequestJdbcRepository.scala index 4b4ce1d0278..dce72064b4b 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ChangeRequestJdbcRepository.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ChangeRequestJdbcRepository.scala @@ -45,22 +45,16 @@ import java.sql.ResultSet import java.sql.Connection import java.sql.PreparedStatement import java.sql.Timestamp -import org.springframework.jdbc.core.JdbcTemplate import com.normation.rudder.domain.workflows.ChangeRequest -import org.springframework.jdbc.core.RowMapper import com.normation.rudder.domain.workflows.ConfigurationChangeRequest import com.normation.rudder.domain.workflows.ChangeRequestId import com.normation.rudder.domain.workflows.ChangeRequestInfo -import scala.util.{Try, Failure => Catch, Success} import scala.collection.JavaConversions._ -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource import com.normation.rudder.domain.policies.DirectiveId import com.normation.rudder.domain.nodes.NodeGroupId import com.normation.rudder.domain.policies.RuleId import com.normation.rudder.repository.WoChangeRequestRepository import com.normation.rudder.services.marshalling.ChangeRequestChangesSerialisation -import org.springframework.jdbc.support.GeneratedKeyHolder -import org.springframework.jdbc.core.PreparedStatementCreator import com.normation.eventlog.EventActor import com.normation.rudder.services.marshalling.ChangeRequestChangesUnserialisation import scala.xml.XML @@ -70,80 +64,53 @@ import com.normation.rudder.domain.logger.ApplicationLogger import com.normation.eventlog.ModificationId import scala.xml.Elem +import com.normation.rudder.db.Doobie +import com.normation.rudder.db.Doobie._ import scalaz.{Failure => _, _}, Scalaz._ import doobie.imports._ import scalaz.concurrent.Task +import com.normation.utils.Control + class RoChangeRequestJdbcRepository( - jdbcTemplate : JdbcTemplate - , changeRequestsMapper : ChangeRequestsMapper + doobie: Doobie + , mapper: ChangeRequestMapper ) extends RoChangeRequestRepository with Loggable { + import doobie._ + import mapper.ChangeRequestComposite + + val SELECT_SQL = "SELECT id, name, description, creationTime, content, modificationId FROM ChangeRequest" val SELECT_SQL_JOIN_WORKFLOW = "SELECT CR.id, name, description, creationTime, content, modificationId FROM changeRequest CR LEFT JOIN workflow W on CR.id = W.id" override def getAll() : Box[Vector[ChangeRequest]] = { - Try { - jdbcTemplate.query(SELECT_SQL, Array[AnyRef](), changeRequestsMapper).toSeq - } match { - case Success(x) => - Full(x.:\(Vector[ChangeRequest]()){(changeRequest,seq) => changeRequest match { - case Full(cr) => seq :+ cr - case eb:EmptyBox => - seq - } - } ) - case Catch(error) => - Failure(error.toString()) - } + val q = query[Box[ChangeRequest]](SELECT_SQL) + q.vector.attempt.map( + // we are just ignoring change request with unserialisation + // error. Does not seem the best. + _.map(_.flatten.toVector) + ).transact(xa).run } override def get(changeRequestId:ChangeRequestId) : Box[Option[ChangeRequest]] = { - Try { - jdbcTemplate.query( - SELECT_SQL + " where id = ?" - , Array[AnyRef](changeRequestId.value.asInstanceOf[AnyRef]) - , changeRequestsMapper).toSeq - } match { - case Success(x) => x match { - case Seq() => Full(None) - case Seq(res) => Full(res.headOption) - case _ => Failure(s"Too many change request have the same id ${changeRequestId.value}") - } - case Catch(error) => Failure(error.toString()) - } + val q = Query[ChangeRequestId, Box[ChangeRequest]](SELECT_SQL + " where id = ?", None).toQuery0(changeRequestId) + q.option.map(_.map(_.toOption)).transact(xa).run + } // Get every change request where a user add a change override def getByContributor(actor:EventActor) : Box[Vector[ChangeRequest]] = { - Try { - jdbcTemplate.query( - new PreparedStatementCreator() { - def createPreparedStatement(connection : Connection) : PreparedStatement = { - - val query= s"${SELECT_SQL} where cast( xpath('//firstChange/change/actor/text()',content) as text[]) = ?" - val ps = connection.prepareStatement( - query, Array[String]()); - ps.setArray(1, connection.createArrayOf("text", Seq(actor.name).toArray[AnyRef]) ) + val q = (fr"${SELECT_SQL}" ++ sql"""where cast( xpath('//firstChange/change/actor/text()',content) as text[]) = ${actor.name}""").query[Box[ChangeRequest]] - // if with have eventtype filter, apply them - ps - } - }, changeRequestsMapper) - } match { - case Success(x) => - Full(x.:\(Vector[ChangeRequest]()){(changeRequest,seq) => changeRequest match { - case Full(cr) => seq :+ cr - case eb:EmptyBox => - seq - } - } ) - case Catch(x) => ApplicationLogger.error(s"could not fetch change request for user ${actor}: ${x}") - Failure(s"could not fetch change request for user ${actor}") - } + q.vector.attempt.map( + // we are just ignoring change request with unserialisation + // error. Does not seem the best. + _.map(_.flatten.toVector) + ).transact(xa).run } override def getByDirective(id : DirectiveId, onlyPending:Boolean) : Box[Vector[ChangeRequest]] = { @@ -212,7 +179,6 @@ class RoChangeRequestJdbcRepository( class WoChangeRequestJdbcRepository( jdbcTemplate : JdbcTemplate - , crSerialiser : ChangeRequestChangesSerialisation , roRepo : RoChangeRequestRepository ) extends WoChangeRequestRepository with Loggable { @@ -328,53 +294,71 @@ class WoChangeRequestJdbcRepository( } } + // doobie mapping, must be done here because of TechniqueRepo in ChangeRequestChangesUnserialisation impl +class ChangeRequestMapper( + crcUnserialiser: ChangeRequestChangesUnserialisation + , crcSerialiser : ChangeRequestChangesSerialisation +) extends Loggable { + implicit val ChangeRequestComposite: Composite[Box[ChangeRequest]] = { -class ChangeRequestsMapper( - changeRequestChangesUnserialisation : ChangeRequestChangesUnserialisation -) extends RowMapper[Box[ChangeRequest]] with Loggable { - + type CR = (Int, Elem, Option[String], Option[String], Option[String]) // unserialize the XML. // If it fails, produce a failure // directives map is boxed because some Exception could be launched - def unserialize(id: Int, content: Elem, modId: Option[String], name: Option[String], description: Option[String]) = { - changeRequestChangesUnserialisation.unserialise(content) match { - case Full((directivesMaps, nodesMaps, ruleMaps, paramMaps)) => - directivesMaps match { - case Full(map) => Full(ConfigurationChangeRequest( - ChangeRequestId(id) - , modId.map(ModificationId.apply) - , ChangeRequestInfo( - name.getOrElse("") - , description.getOrElse("") - ) - , map - , nodesMaps - , ruleMaps - , paramMaps - ) ) - case eb:EmptyBox => - val fail = eb ?~! s"could not deserialize directive change of change request #${id} cause is: ${eb}" - ApplicationLogger.error(fail) + def unserialize(id: Int, content: Elem, modId: Option[String], name: Option[String], description: Option[String]): Box[ConfigurationChangeRequest] = { + crcUnserialiser.unserialise(content) match { + case Full((directivesMaps, nodesMaps, ruleMaps, paramMaps)) => + directivesMaps match { + case Full(map) => Full(ConfigurationChangeRequest( + ChangeRequestId(id) + , modId.map(ModificationId.apply) + , ChangeRequestInfo( + name.getOrElse("") + , description.getOrElse("") + ) + , map + , nodesMaps + , ruleMaps + , paramMaps + ) ) + + case eb:EmptyBox => + val fail = eb ?~! s"could not deserialize directive change of change request #${id} cause is: ${eb}" + logger.error(fail) + fail + } + + case eb:EmptyBox => + val fail = eb ?~! s"Error when trying to get the content of the change request ${id} : ${eb}" + logger.error(fail.msg) fail - } + } + } + + def serialize(optCR: Box[ChangeRequest]): CR = { + optCR match { + case Full(cr) => + val elem = crcSerialiser.serialise(cr) + val name = cr.info.name match { + case "" => None + case x => Some(x) + } + val desc = cr.info.description match { + case "" => None + case x => Some(x) + } + (cr.id.value, elem, cr.modId.map(_.value), name, desc) - case eb:EmptyBox => - val fail = eb ?~! s"Error when trying to get the content of the change request ${id} : ${eb}" - logger.error(fail.msg) - fail + case _ => throw new IllegalArgumentException(s"We can only serialize Full(ChangeRequest)") + } } - } - def mapRow(rs : ResultSet, rowNum: Int) : Box[ChangeRequest] = { - unserialize( - rs.getInt("id") - , XML.load(rs.getSQLXML("content").getBinaryStream()) - , Some(rs.getString("modificationId")) - , Some(rs.getString("name")) - , Some(rs.getString("description")) + Composite[CR].xmap( + (t : CR ) => unserialize(t._1, t._2, t._3, t._4, t._5) + , (cr: Box[ChangeRequest]) => serialize(cr) ) - } + } } diff --git a/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ComplianceRepository.scala b/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ComplianceRepository.scala index 6bb54dc67d2..1c537c2b582 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ComplianceRepository.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ComplianceRepository.scala @@ -45,14 +45,10 @@ import com.normation.rudder.db.Doobie import com.normation.rudder.db.Doobie._ import scalaz.{Failure => _, _}, Scalaz._ import doobie.imports._ -import scalaz.concurrent.Task -import doobie.postgres.pgtypes._ -import com.normation.rudder.db.DB import com.normation.rudder.services.reports._ import com.normation.inventory.domain.NodeId import org.joda.time.DateTime import com.normation.rudder.domain.reports.RunComplianceInfo -import com.normation.rudder.domain.reports.ComplianceLevel import com.normation.rudder.domain.reports.AggregatedStatusReport import com.normation.rudder.domain.reports.CompliancePercent diff --git a/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala b/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala index 7f146e27410..2bfdf8b0178 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala @@ -53,11 +53,9 @@ import com.normation.rudder.repository.ReportsRepository import org.joda.time._ import org.slf4j.{Logger,LoggerFactory} -import org.springframework.jdbc.core._ import net.liftweb.common._ import net.liftweb.common.Box._ -import org.springframework.dao.DataAccessException import scalaz.{Failure => _, _}, Scalaz._ import doobie.imports._ diff --git a/rudder-core/src/main/scala/com/normation/rudder/services/system/DatabaseManager.scala b/rudder-core/src/main/scala/com/normation/rudder/services/system/DatabaseManager.scala index 5ab3087c599..7d64b05ab6d 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/services/system/DatabaseManager.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/services/system/DatabaseManager.scala @@ -40,7 +40,6 @@ package com.normation.rudder.services.system import net.liftweb.common._ import org.joda.time.DateTime -import org.springframework.jdbc.core.JdbcTemplate import net.liftweb.common.Loggable import com.normation.rudder.repository.ReportsRepository import com.normation.rudder.repository.UpdateExpectedReportsRepository