/**
* Copyright (C) 2008-2010, Squale Project - http://www.squale.org
*
* This file is part of Squale.
*
* Squale is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or any later version.
*
* Squale is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Squale. If not, see <http://www.gnu.org/licenses/>.
*/
package org.squale.squalix.core;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.squale.jraf.commons.exception.JrafDaoException;
import org.squale.jraf.commons.exception.JrafEnterpriseException;
import org.squale.jraf.commons.exception.JrafPersistenceException;
import org.squale.jraf.helper.PersistenceHelper;
import org.squale.jraf.spi.persistence.IPersistenceProvider;
import org.squale.jraf.spi.persistence.ISession;
import org.squale.squalecommon.daolayer.component.ApplicationDAOImpl;
import org.squale.squalecommon.daolayer.component.AuditDAOImpl;
import org.squale.squalecommon.daolayer.component.ProjectDAOImpl;
import org.squale.squalecommon.daolayer.result.MarkDAOImpl;
import org.squale.squalecommon.daolayer.result.MeasureDAOImpl;
import org.squale.squalecommon.daolayer.result.rulechecking.RuleCheckingTransgressionDAOImpl;
import org.squale.squalecommon.datatransfertobject.config.ServeurDTO;
import org.squale.squalecommon.datatransfertobject.config.SqualixConfigurationDTO;
import org.squale.squalecommon.datatransfertobject.result.SqualeReferenceDTO;
import org.squale.squalecommon.datatransfertobject.transform.component.AuditTransform;
import org.squale.squalecommon.datatransfertobject.transform.config.AuditFrequencyTransform;
import org.squale.squalecommon.enterpriselayer.businessobject.component.ApplicationBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.AuditBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.ProjectBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.roi.RoiMetricsBO;
import org.squale.squalecommon.enterpriselayer.facade.config.ServeurFacade;
import org.squale.squalecommon.enterpriselayer.facade.config.SqualixConfigFacade;
import org.squale.squalecommon.enterpriselayer.facade.quality.SqualeReferenceFacade;
import org.squale.squalecommon.util.SqualeCommonConstants;
import org.squale.squalecommon.util.SqualeCommonUtils;
import org.squale.squalecommon.util.mail.IMailerProvider;
import org.squale.squalecommon.util.mail.MailerHelper;
import org.squale.squalix.core.exception.ConfigurationException;
import org.squale.squalix.core.export.Export;
import org.squale.squalix.core.purge.Purge;
import org.squale.squalix.messages.MessageMailManager;
import org.squale.squalix.messages.Messages;
import org.squale.squalix.stats.ComputeStats;
import org.squale.squalix.util.sourcesrecovering.SourcesRecoveringOptimisation;
import org.squale.squalix.util.stoptime.StopTimeHelper;
/**
* A partir du fichier de configuration globale, il d�termine la s�quence des actions pour le projet associ� et les
* ex�cute.<br />
* Le scheduler assure :
* <ul>
* <li>la r�cup�ration de la configuration du moteur de t�ches,</li>
* <li>la r�cup�ration des audits � lancer,</li>
* <li>la cr�ation d'un ex�cuteur d'analyse (AuditExecutor) pour chacun des projets associ�s aux audits,</li>
* <li>le lancement des t�ches ind�pendantes d'un projet,</li>
* <li>le lancement des ex�cuteurs d'analyse,</li>
* <li>le lancement des t�ches calculant les r�sultats au niveau du projet (graphes,...),</li>
* <li>la modification du statut de l'audit lorsque celui-ci est termin�, et la cr�ation �ventuelle du prochain audit
* dans le cas d'un audit de suivi.</li>
* </ul>
* <br />
* Tous les audits et t�ches sont ex�cut�s via des pools de threads, g�r�s par le gestionnaire de ressources.<br />
* Voir la documentation de la classe <code>ResourcesManager</code> pour plus de renseignements sur son fonctionnement. <br />
* <br />
* Lorsque tous les audits ont �t� lanc�s, les scheduler est bloqu� tant que les pools sont ouverts.<br />
* Pour s'assurer que ceux-ci sont ouverts, on utilise un <code>CountDownLatch</code> d�cr�ment� par le gestionnaire de
* ressources lorsqu'il ferme ses pools. <br />
* <br />
* Les t�ches non li�es � un projet et les ex�cuteurs d'analyse sont associ�s au scheduler par un pattern
* Observateur-Observable, dans lequel le scheduler est l'observateur. Sa m�thode <code>update()</code> est appel�e
* lorsque l'ex�cuteur ou la t�che est termin�.
*
* @see org.squale.squalix.core.ResourcesManager
* @see org.squale.squalix.core.AuditExecutor
* @author m400842
* @version 1.0
*/
public class Scheduler
implements Runnable
{
/**
* L'objet contenant les configurations
*/
private SqualixConfigurationDTO mConf;
/**
* Logger
*/
private static final Log LOGGER = LogFactory.getLog( Scheduler.class );
/**
* Liste des audits executeur cr�es.
*/
private List mAudits = new ArrayList( 0 );
/**
* Cl� du site h�bergeant l'application.
*/
private long mSiteId;
/**
* Provider de persistance
*/
private static final IPersistenceProvider PERSISTANT_PROVIDER = PersistenceHelper.getPersistenceProvider();
/**
* Session de travail
*/
private ISession mSession;
/**
* Le calendrier permettant de savoir � quel heure � �t� lanc� le batch
*/
private Calendar mLaunchingCal;
/** la liste des projets d'un audit */
private List mProjectsByAudit;
/** pour envoyer des mails */
private IMailerProvider mMailer = MailerHelper.getMailerProvider();
/**
* Instantiate a scheduler.
*
* @param pSiteId Technical id of the Squalix server.
* @param launchMail boolean which indicate if we want launch a mail
* @throws ConfigurationException Si un probl�me de configuration appara�t.
* @roseuid 42935241035F
*/
public Scheduler( long pSiteId, boolean launchMail )
throws ConfigurationException
{
try
{
mSession = PERSISTANT_PROVIDER.getSession();
mConf = SqualixConfigFacade.getConfig();
mLaunchingCal = Calendar.getInstance();
// If launchMail is true then we launch a mail fro indicat to the admins that squalix has been launched
if ( launchMail )
{
String sender = Messages.getString( "mail.sender.squalix" );
MessageMailManager mail = new MessageMailManager();
String object = sender + Messages.getString( "mail.squalix.launch.object" );
mail.addContent( "mail.header", null );
mail.addContent( "mail.squalix.launch.content", null );
String content = mail.getContent();
SqualeCommonUtils.notifyByEmail( mMailer, null, SqualeCommonConstants.ONLY_ADMINS, null, object,
content, false );
}
}
catch ( JrafEnterpriseException e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
catch ( JrafPersistenceException e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
mSiteId = pSiteId;
}
/**
* R�cup�re les audits � r�aliser le jour pr�sent.
*
* @param pStopTime timer donnant l'arr�t du batch
* @return la liste des audits � r�aliser ce jour
* @throws JrafDaoException si un probleme de r�cup�ration appara�t.
* @roseuid 42B7E4E30396
*/
private List getAudits( StopTimeHelper pStopTime )
throws JrafDaoException
{
mSession.beginTransaction();
// R�cup�re les audits dont la date d'ex�cution est
// ant�rieure � la date limite d'ex�cution
List audits =
(List) AuditDAOImpl.getInstance().findBeforeBySiteAndStatus( mSession, mSiteId, AuditBO.NOT_ATTEMPTED,
pStopTime.getLimitCal().getTime() );
mSession.commitTransactionWithoutClose();
LOGGER.info( CoreMessages.getString( "audits.toprocess", new Object[] { new Integer( audits.size() ) } ) );
return audits;
}
/**
* R�cup�re la liste des projets d'un audit, et ex�cute les analyses dans l'ordre. L'audit est rattach� � chaque
* projet
*
* @param pAudit Audit pour lequel on d�sire obtenir la liste des projets
* @return La collection des projets li�s � l'audit
* @roseuid 42B7E54D0127
*/
private List getProjectsByAudit( final AuditBO pAudit )
{
List list = new ArrayList();
try
{
Long id = new Long( pAudit.getId() );
mSession.beginTransaction();
ApplicationBO application = ApplicationDAOImpl.getInstance().loadByAuditId( mSession, id );
Collection children = application.getChildren();
if ( null != children )
{
// Si l'application contient des projets, on les ajoute
// � la liste des projets � analyser
// pour cet audit.
Iterator it = children.iterator();
Object obj = null;
while ( it.hasNext() )
{
obj = it.next();
if ( obj instanceof ProjectBO )
{
ProjectBO project = (ProjectBO) obj;
// Rattachement de l'audit au projet si celui-ci est actif
if ( project.getStatus() == ProjectBO.ACTIVATED )
{
project.addAudit( pAudit );
ProjectDAOImpl.getInstance().save( mSession, project );
list.add( project );
}
}
}
}
mSession.commitTransactionWithoutClose();
}
catch ( Exception e )
{
// Si un probl�me de DAO appara�t, l'exception est loggu�e
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
return list;
}
/**
* Lance le scheduleur.<br>
*
* @roseuid 42CD2F0B0287
*/
public void run()
{
try
{
// On lance le monitoring de la m�moire
// MemoryMonitor.startMonitoring(new MemoryMonitorConfiguration());
StopTimeHelper stop = new StopTimeHelper( mConf, mLaunchingCal );
if ( LOGGER.isDebugEnabled() )
{
LOGGER.debug( CoreMessages.getString( "time.limit", stop.getLimitCal().getTime() ) );
}
boolean canContinue = true;
List audits = getAudits( stop );
// Launch the export for the shared repository
Thread export = null;
Export exportTools = new Export();
export = exportTools.launchExport( mSiteId );
// purge dans un thread parallele
Purge prg = new Purge( mSiteId, audits );
prg.start();
// Test si il y a des audits avec le status en cours pour le site concern�
// Si oui, c'est anormal, on pr�vient les administrateurs mais on continue quand meme
// car c'est peut etre simplement un audit qui a �t� interrompu brutalement et �a n'empechera
// donc pas le nouveau de tourner
if ( existsAlreadyRunningAudits( mSiteId ) )
{
// On envoie un mail pour signaler qu'un audit est en cours sur l'application
String sender = Messages.getString( "mail.sender.squalix" );
String object = sender + Messages.getString( "mail.running_audit.exists.object" );
MessageMailManager mail = new MessageMailManager();
mail.addContent( "mail.header", null );
mail.addContent( "mail.running_audit.exists.content", null );
String content = mail.getContent();
String dest = SqualeCommonConstants.ONLY_ADMINS;
// On envoir le mail qu'aux abonn�s
SqualeCommonUtils.notifyByEmail( mMailer, null, dest, null, object, content, false );
}
// Ex�cuter les audits
launchAudits( audits, stop );
// Mise � jour des indicateurs DICT pour squale
if ( !audits.isEmpty() )
{
new ComputeStats().computeDICTStats();
}
// Correction automatique de la fr�quence des audits si la configuration existe
if ( null != mConf.getFrequencies() && mConf.getFrequencies().size() > 0 )
{
manageAuditFrequency();
}
// Wait the end of the purge thread
prg.join();
if ( export != null )
{
export.join();
}
LOGGER.info( CoreMessages.getString( "endofexec" ) );
// Fermeture de la session
mSession.closeSession();
}
catch ( JrafDaoException e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
catch ( ConfigurationException e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
catch ( InterruptedException e )
{
// On n'a pas pu effectuer la purge correctement
// On pr�vient les admins
String sender = Messages.getString( "mail.sender.squalix" );
String object = sender + Messages.getString( "mail.rotation.audit.shutDown.object" );
MessageMailManager mail = new MessageMailManager();
mail.addContent( "mail.header", null );
mail.addContent( "mail.rotation.audit.shutDown.content", null );
String content = mail.getContent();
SqualeCommonUtils.notifyByEmail( mMailer, null, SqualeCommonConstants.ONLY_ADMINS, null, object, content,
false );
}
}
/**
* On fait une passe sur toutes les applications ayant un audit programm� pour v�rifier les r�gles d�fini dans le
* param�trage de la fr�quence. On baisse ensuite la fr�quence des applications si besoin et on envoie un mail de
* notification de changement de param�trage � l'administrateur de l'application et aux admins SQUALE.
*
* @throws JrafDaoException si erreur
*/
private void manageAuditFrequency()
throws JrafDaoException
{
mSession.beginTransaction();
// On r�cup�re les applications du site qui ont un audit de suivi programm�
Collection applis = ApplicationDAOImpl.getInstance().findWhereHaveNotAttemptedAuditBySite( mSession, mSiteId );
// Pour toutes les applis, on modifie la fr�quence en fonction de son dernier acc�s utilisateur
ApplicationBO appli = null;
// On sauvegarde l'ancienne valeur de la fr�quence pour le message du mail
int oldFreq = 0;
for ( Iterator it = applis.iterator(); it.hasNext(); )
{
appli = (ApplicationBO) it.next();
oldFreq = appli.getAuditFrequency();
// On change la fr�quence si n�cessaire
if ( appli.changeFrequency( AuditFrequencyTransform.dto2bo( mConf.getFrequencies() ) ) )
{
LOGGER.info( "frequency has been changed for " + appli.getName() );
// On sauvegarde les modifications
ApplicationDAOImpl.getInstance().save( mSession, appli );
// On envoit un mail d'information aux managers de l'application et aux admins SQUALE
String sender = Messages.getString( "mail.sender.squalix" );
String object = sender + Messages.getString( "mail.application_frequency.changed.object" );
MessageMailManager mail = new MessageMailManager();
mail.addContent( "mail.header", null );
mail.addContent( "mail.application_frequency.changed.content", new String[] { appli.getName(),
"" + oldFreq, "" + appli.getAuditFrequency() } );
String content = mail.getContent();
SqualeCommonUtils.notifyByEmail( mMailer, null, SqualeCommonConstants.MANAGERS_AND_ADMINS, null,
object, content, false );
}
}
mSession.commitTransactionWithoutClose();
}
/**
* @param pSiteId le nom du site
* @return true si il existe des audits avec le status running pour ce site
* @throws JrafDaoException en cas d'�chec
*/
private boolean existsAlreadyRunningAudits( long pSiteId )
throws JrafDaoException
{
return AuditDAOImpl.getInstance().countWhereStatusAndSite( mSession, pSiteId, AuditBO.RUNNING ) != 0;
}
/**
* @return un bool�en indiquant si il faut faire la r�partition des audits ou pas
* @throws JrafDaoException en cas d'echec de r�cup�ration de l'audit
*/
private boolean isRotationDay()
throws JrafDaoException
{
AuditDAOImpl auditDao = AuditDAOImpl.getInstance();
Calendar today = Calendar.getInstance();
Calendar auditDate = Calendar.getInstance();
Collection coll;
boolean result = false;
coll = auditDao.findRotationAudit( mSession );
if ( coll != null && coll.size() != 0 )
{
Iterator it = coll.iterator();
// Normalement un seul r�sultat
while ( it.hasNext() )
{
AuditBO audit = (AuditBO) it.next();
auditDate.setTime( audit.getDate() );
result =
audit.getDate() != null
&& auditDate.get( Calendar.DAY_OF_WEEK ) <= today.get( Calendar.DAY_OF_WEEK );
}
}
else
{
// On a pas pu trouver l'audit de rotation des partitions,
// On en informe les admins
ServeurDTO serveur = new ServeurDTO();
serveur = ServeurFacade.getServeur( mSiteId );
String sender = Messages.getString( "mail.sender.squalix" );
String object =
sender + Messages.getString( "mail.rotation.audit.unknown.object", new String[] { serveur.getName() } );
MessageMailManager mail = new MessageMailManager();
mail.addContent( "mail.header", null );
mail.addContent( "mail.rotation.audit.unknown.content", null );
String content = mail.getContent();
SqualeCommonUtils.notifyByEmail( mMailer, null, SqualeCommonConstants.ONLY_ADMINS, null, object, content,
false );
}
return result;
}
/**
* Lance les ex�cutions des audits
*
* @param pAudits audits � r�aliser.
* @param pStopTime timer d'arr�t du scheduler
* @roseuid 42CE34390161
*/
private void launchAudits( List pAudits, StopTimeHelper pStopTime )
{
if ( null != pAudits )
{
Iterator it = pAudits.iterator();
AuditBO audit = null;
// pour chaque audit lance les auditExecutors associ�s
while ( it.hasNext() && !pStopTime.isTimeToStop() )
{
SourcesRecoveringOptimisation.reinit();
audit = (AuditBO) it.next();
audit.setRealBeginningDate( Calendar.getInstance().getTime() );
launchAudit( audit );
audit.setEndDate( Calendar.getInstance().getTime() );
// met � jour le champ dur�e de l'audit en calculant
// � partir des dates de d�but et de fin
audit.calculeDuration();
// Ne stocke pas la taille de la JVM car le r�sultat n'est pas pertinent
}
// Affichage d'un message s'il reste des audits � traiter
if ( it.hasNext() )
{
LOGGER.warn( CoreMessages.getString( "time.limitreached" ) );
}
}
}
/**
* Lance l'ex�cution d'un audit et donc de tous ses ex�cuteurs d'audit pour les projets que l'application contient
*
* @param pCurrentAudit l'audit lanc�
*/
private void launchAudit( AuditBO pCurrentAudit )
{
AuditBO previousAudit = null;
ApplicationBO application = null;
// on passe tout de suite le status de l'audit � "en cours" et on cr�e de suite
// un nouvel audit pour �viter les probl�mes li�s � l'interruption brutale du batch
// enregistrement de l'audit
try
{
mSession.beginTransaction();
pCurrentAudit.setStatus( AuditBO.RUNNING );
// On met � jour la version de SQUALE
pCurrentAudit.setSqualeVersion( AuditBO.getCurrentSqualeVersion() );
// On met la date tout de suite pour ne pas avoir de probl�mes avec les audits interrompus
pCurrentAudit.setDate( Calendar.getInstance().getTime() );
AuditDAOImpl.getInstance().save( mSession, pCurrentAudit );
application = ApplicationDAOImpl.getInstance().loadByAuditId( mSession, new Long( pCurrentAudit.getId() ) );
// On r�cup�re l'audit pr�c�dent
AuditDAOImpl dao = AuditDAOImpl.getInstance();
previousAudit = dao.getLastAuditByApplication( mSession, application.getId(), null, AuditBO.TERMINATED );
createNewAudit( pCurrentAudit, application );
mSession.commitTransactionWithoutClose();
// On met la variable � termin� par d�faut, de toute fa�on si on l'affecte alors la bonne valeur
// a �t� trait�e dans la boucle suivante, et si on ne rentre pas dans la boucle
// c'est qu'on avait rien � faire mais on a pas eu d'erreurs
int status = AuditBO.TERMINATED;
// r�cup�re la liste des auditsExecutors
// un AuditExecutor par projet de l'application de l'audit
List aeList = getAuditExecutors( pCurrentAudit );
// le nombre de projets pour cet audit
// aeList ne peut pas etre null, au pire vide
// lance les taches de l'auditExecutor
for ( int i = 0; i < aeList.size(); i++ )
{
launchTasks( (AuditExecutor) aeList.get( i ) );
// un audit failed est d�finitif
if ( status != AuditBO.FAILED )
{
// Si il n'est pas non plus partiel, on r�cup�re la valeur courante
// Sinon, un status partial ne peut etre chang� que pour un status failed
// car failed est prioritaire sur partial
int newStatus = ( (AuditExecutor) aeList.get( i ) ).getFinalStatus();
if ( status != AuditBO.PARTIAL || ( status == AuditBO.PARTIAL && newStatus == AuditBO.FAILED ) )
{
status = newStatus;
}
}
}
// on met � jour le status de l'audit que si on a effectu� tous les projets de l'application de l'audit
pCurrentAudit.setStatus( status );
// sauvegarde l'audit
saveCurrentAudit( pCurrentAudit, application );
// Notification : en cas de r�ussite, on pr�vient les managers de l'application
// que l'audit s'est bien pass�
String[] infos = new String[] { application.getName(), application.getServeurBO().getName() };
manageResultMailing( pCurrentAudit.getStatus(), infos, application.getId() );
// On ex�cute le calcul du ROI si l'audit a fonctionn� et si l'application a un audit
// termin� qui pr�c�de le courant
if ( pCurrentAudit.getStatus() == AuditBO.TERMINATED && null != previousAudit )
{
mSession.beginTransaction();
int nbCorrections = calculateNbCorrection( previousAudit, pCurrentAudit );
createROI( nbCorrections, application, pCurrentAudit );
mSession.commitTransactionWithoutClose();
}
}
catch ( JrafDaoException e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
}
/**
* M�thode qui g�re l'envoi de mail en fonction du r�sultat de l'audit
*
* @param pStatus le status de l'audit
* @param pInfos les informations concernant l'audit pour le mail
* @param pApplicationId l'id de l'application concern�e
*/
private void manageResultMailing( int pStatus, String[] pInfos, long pApplicationId )
{
String dest = "";
String object = "";
String content = "";
boolean sendMail = false;
String sender = Messages.getString( "mail.sender.squalix.task", pInfos );
MessageMailManager mail = new MessageMailManager();
if ( pStatus == AuditBO.TERMINATED )
{
object = sender + Messages.getString( "mail.audit.terminated.object", pInfos );
mail.addContent( "mail.header", null );
mail.addContent( "mail.audit.terminated.content", pInfos );
content = mail.getContent();
dest = SqualeCommonConstants.MANAGERS_AND_READERS;
sendMail = true;
}
else
{
// en cas d'�chec, on pr�vient les administrateurs de SQUALE et
// les managers de l'application concern�e de l'�chec
if ( pStatus == AuditBO.FAILED )
{
object = sender + Messages.getString( "mail.audit.failed.object", pInfos );
mail.addContent( "mail.header", null );
mail.addContent( "mail.audit.failed.content", pInfos );
content = mail.getContent();
dest = SqualeCommonConstants.MANAGERS_AND_ADMINS;
sendMail = true;
}
else
{
// en cas d'�chec, on pr�vient les administrateurs de SQUALE et
// les managers de l'application concern�e de l'�chec
if ( pStatus == AuditBO.PARTIAL )
{
object = sender + Messages.getString( "mail.audit.partial.object", pInfos );
mail.addContent( "mail.header", null );
mail.addContent( "mail.audit.partial.content", pInfos );
content = mail.getContent();
dest = SqualeCommonConstants.MANAGERS_AND_ADMINS;
sendMail = true;
}
}
}
// On envoie un email aux utilisateurs abonn�s selon le statut de l'audit
if ( sendMail )
{
// compl�ment d'infos
SqualeCommonUtils.notifyByEmail( mMailer, null, dest, new Long( pApplicationId ), object, content, false );
}
}
/**
* Sauvegarde le roi calcul� en base
*
* @param pValue le nombre de correction
* @param pApplication l'application courante
* @param pAudit l'audit courant
* @throws JrafDaoException si erreur
*/
public void createROI( int pValue, ApplicationBO pApplication, AuditBO pAudit )
throws JrafDaoException
{
RoiMetricsBO roi = new RoiMetricsBO();
roi.setNbCorrections( pValue );
roi.setComponent( pApplication );
roi.setAudit( pAudit );
// Initialisation du DAO
MeasureDAOImpl roiDAO = MeasureDAOImpl.getInstance();
roiDAO.create( mSession, roi );
}
/**
* Calcule le nombre de corrections pour l'audit courant pour le ROI
*
* @param pPreviousAudit l'audit pr�c�dent
* @param pCurrentAudit l'audit courant
* @return le nombre de corrections faites entre les deux audits
* @throws JrafDaoException si erreur
*/
public int calculateNbCorrection( AuditBO pPreviousAudit, AuditBO pCurrentAudit )
throws JrafDaoException
{
int nbProgressions = 0;
int nbSuppressions = 0;
int transgressionDiff = 0;
if ( pCurrentAudit.getRealDate().before( pPreviousAudit.getRealDate() ) )
{
// On ne calcule pas le nombre de correction si il s'agit d'un audit de jalon intercal�
LOGGER.info( CoreMessages.getString( "roi.not_calculated",
new Object[] { new Long( pCurrentAudit.getId() ) } ) );
}
else
{
/* On r�cup�re le nombre de corrections faites entre les deux audits */
Long auditId = new Long( pCurrentAudit.getId() );
Long previousAuditId = new Long( pPreviousAudit.getId() );
MarkDAOImpl markDao = MarkDAOImpl.getInstance();
// Les composants qui sont pass�s de z�ro � 1, 2 ou 3
nbProgressions = markDao.findCorrectionsWithProgessions( mSession, auditId, previousAuditId );
// Les composants qui �taient � z�ro et qui n'existent plus
nbSuppressions = markDao.findCorrectionsWithSuppressions( mSession, auditId, previousAuditId );
// La progression du nombre de transgressions de niveau erreur et warning
RuleCheckingTransgressionDAOImpl ruleDao = RuleCheckingTransgressionDAOImpl.getInstance();
int nbTransgressions = ruleDao.findNbErrorAndWarning( mSession, auditId );
int nbPreviousTransgressions = ruleDao.findNbErrorAndWarning( mSession, previousAuditId );
transgressionDiff = nbPreviousTransgressions - nbTransgressions;
if ( transgressionDiff <= 0 )
{
transgressionDiff = 0;
}
}
return nbProgressions + nbSuppressions + transgressionDiff;
}
/**
* Lance les t�ches .
*
* @param pAuditExec l'executeur d'audit .
* @roseuid 42CE30D601DD
*/
private void launchTasks( AuditExecutor pAuditExec )
{
// lance les taches de l'auditExecutor
pAuditExec.run();
}
/**
* @param pAudit audit d'applications � r�aliser.
* @return Retourne une liste d'executeur d'audits pour l'audit en parametre.<br>
* @roseuid 42CE37D70124
*/
private List getAuditExecutors( final AuditBO pAudit )
{
AuditExecutor ae = null;
List aeList = new ArrayList( 0 );
ProjectBO project = null;
// La liste des taches � effectuer
List analyze = new ArrayList( 0 );
// La liste des taches de terminaison � effectuer dans tous les cas
List termination = new ArrayList( 0 );
// La liste des taches � effectuer pour r�cup�rer les sources
List analyzeSource = new ArrayList( 0 );
// La liste des taches de terminaison � effectuer pour la r�cup�ration
// de sources, comme le d�montage de la vue clearcase...
List terminationSource = new ArrayList( 0 );
// La liste des taches de profil
List analyzeProfil = new ArrayList( 0 );
// La liste des taches de terminaison de profil � effectuer
List terminationProfil = new ArrayList( 0 );
try
{
// On r�cup�re tous les projets � analyser pour cet audit
mProjectsByAudit = getProjectsByAudit( pAudit );
Iterator it = mProjectsByAudit.iterator();
while ( it.hasNext() )
{
// Pour chaque projet, on cr�e un ex�cuteur d'audit,
// g�rant le type de r�cup�rateur de source associ� au projet et
// d�pendant du profil du projet
project = (ProjectBO) it.next();
analyzeSource = project.getSourceManager().getAnalysisTasks();
terminationSource = project.getSourceManager().getTerminationTasks();
String profile = project.getProfile().getName();
analyzeProfil = project.getProfile().getAnalysisTasks();
terminationProfil = project.getProfile().getTerminationTasks();
// Il y a 2 types de taches (analyse ou terminale) combinable
// avec 2 types de fonction (r�cup�ration de source ou profil)
// il faut faire dans l'ordre:
// * Taches d'analyse de r�cup�ration de source
// * Taches d'analyse du profil
// * Taches terminales du profil
// * Taches terminales de r�cup�ration de source
analyze.addAll( analyzeSource );
analyze.addAll( analyzeProfil );
termination.addAll( terminationProfil );
termination.addAll( terminationSource );
// Es-ce le dernier projet de l'audit ?
boolean lastProject = false;
if ( !it.hasNext() )
{
lastProject = true;
}
// creation de lauditexecutor associ�
ae = new AuditExecutor( analyze, termination, pAudit, project, lastProject );
ae.setScheduler( this );
aeList.add( ae );
mAudits.add( ae );
analyze = new ArrayList( 0 );
termination = new ArrayList( 0 );
}
}
catch ( Exception e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
pAudit.setStatus( AuditBO.FAILED );
}
return aeList;
}
/**
* R�alise les t�ches de niveau application (cr�ation des graphes, calculs,...)
*
* @param pCurrentAudit l'audit courant.
* @param pApplicationBO l'application sur lequel calculer les r�sultats.
* @roseuid 42CE40E102B8
*/
private void createNewAudit( final AuditBO pCurrentAudit, final ApplicationBO pApplicationBO )
{
ApplicationBO application = null;
// on ne cr�e pas de nouvelles transactions car il faut faut que la transaction
// pour cette m�thode soit la meme que pour la m�thode appelante de cette m�thode
try
{
Long applicationId = new Long( pApplicationBO.getId() );
application = (ApplicationBO) ApplicationDAOImpl.getInstance().get( mSession, applicationId );
GregorianCalendar cal = new GregorianCalendar();
// Cr�ation d'un nouvel audit si il s'agit d'un audit de suivi
if ( pCurrentAudit.getType().equals( AuditBO.NORMAL ) )
{
// Cr�ation d'un nouvel audit
AuditBO audit = new AuditBO();
// Ajout de la fr�quence d'audit � la date courante
cal.add( Calendar.DATE, pApplicationBO.getAuditFrequency() );
audit.setDate( cal.getTime() );
audit.setStatus( AuditBO.NOT_ATTEMPTED );
audit.setType( pCurrentAudit.getType() );
AuditDAOImpl.getInstance().create( mSession, audit );
// Ajout du nouvel audit � l'application
application.addAudit( audit );
ApplicationDAOImpl.getInstance().save( mSession, application );
}
}
catch ( Exception e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
}
/**
* enregistre l'audit courant
*
* @param pCurrentAudit l'audit courant
* @param pApplicationBO l'application li�e � l'audit
*/
private void saveCurrentAudit( final AuditBO pCurrentAudit, final ApplicationBO pApplicationBO )
{
ApplicationBO application = null;
try
{
Long applicationId = new Long( pApplicationBO.getId() );
mSession.beginTransaction();
application = (ApplicationBO) ApplicationDAOImpl.getInstance().get( mSession, applicationId );
Long auditId = new Long( pCurrentAudit.getId() );
GregorianCalendar cal = new GregorianCalendar();
AuditBO finishedAudit = (AuditBO) AuditDAOImpl.getInstance().get( mSession, auditId );
// Remet � jour la date r�elle de l'audit
finishedAudit.setDate( Calendar.getInstance().getTime() );
finishedAudit.setStatus( pCurrentAudit.getStatus() );
// sauvegarde l'audit
AuditDAOImpl.getInstance().save( mSession, finishedAudit );
// on commit pour sauvegarder le status de l'audit
mSession.commitTransactionWithoutClose();
mSession.beginTransaction();
// Ajoute l'audit r�ussit dans le Referenciel
manageSqualeReference( finishedAudit, pApplicationBO.getName(), pApplicationBO.getId() );
mSession.commitTransactionWithoutClose();
}
catch ( Exception e )
{
LOGGER.error( CoreMessages.getString( "exception" ), e );
}
}
/**
* @param pAudit l'audit courant termin�
* @param pAppliName le nom de l'application recherch�
* @param pAppliId l'id de l'application pour la transformation
* @throws JrafEnterpriseException en cas d'�chec de sauvegarde de l'outil
*/
private void manageSqualeReference( AuditBO pAudit, String pAppliName, long pAppliId )
throws JrafEnterpriseException
{
boolean insert = false;
SqualeReferenceDTO storedAudit = SqualeReferenceFacade.getReferencedAudit( pAppliName, mSession );
// Les diff�rentes r�gles suivantes sont prioris�es
// 1) On ne peut ajouter au r�f�rentiel que des audits termin�s
// 2) Si aucun audit n'est d�j� pr�sent en base, on ins�re le courant de toute facon
// 3) les audits de jalon sont prioritaires
// 4) On garde l'audit le plus r�cent
if ( pAudit.getStatus() == AuditBO.TERMINATED
&& ( null == storedAudit || ( ( AuditBO.NORMAL.equals( storedAudit.getAuditType() ) && AuditBO.MILESTONE.equals( pAudit.getType() ) ) || ( storedAudit.getAuditType().equals(
pAudit.getType() ) && pAudit.getDate().getTime() > storedAudit.getDate().getTime() ) ) ) )
{
SqualeReferenceFacade.insertAudit( AuditTransform.bo2Dto( pAudit, pAppliId ), mSession );
}
}
}