/** * 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.tools.mccabe; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.squale.jraf.commons.exception.JrafDaoException; import org.squale.jraf.spi.persistence.ISession; import org.squale.squalecommon.daolayer.result.MeasureDAOImpl; import org.squale.squalecommon.enterpriselayer.businessobject.component.AuditBO; import org.squale.squalecommon.enterpriselayer.businessobject.component.parameters.ListParameterBO; import org.squale.squalecommon.enterpriselayer.businessobject.component.parameters.ParametersConstants; import org.squale.squalecommon.enterpriselayer.businessobject.result.mccabe.McCabeQAClassMetricsBO; import org.squale.squalecommon.enterpriselayer.businessobject.result.mccabe.McCabeQAJspMetricsBO; import org.squale.squalecommon.enterpriselayer.businessobject.result.mccabe.McCabeQAMethodMetricsBO; import org.squale.squalecommon.enterpriselayer.businessobject.result.mccabe.McCabeQAProjectMetricsBO; import org.squale.squalix.core.TaskData; import org.squale.squalix.util.buildpath.BuildProjectPath; import org.squale.squalix.util.csv.CSVParser; import org.squale.squalix.util.file.FileUtility; import org.squale.squalix.util.file.ToolsReportsUtility; import org.squale.squalix.util.parser.LanguageParser; import org.squale.squalix.util.repository.ComponentRepository; /** * Objet de persistence des m�triques McCabe pour les langages par objet (Java, C++, etc.). */ public class OOMcCabePersistor extends McCabePersistor { /** L'extension d'une page jsp */ public static final String JSP_EXTENSION = ".jsp"; /** Signature McCabe de la m�thode d'une JSP */ public static final String JSP_METHOD_REGEXP = "._jspService\\(HttpServletRequest,HttpServletResponse\\)"; /** * Metriques des JSP */ private Map mJspResults = new HashMap(); /** * Nombre de m�thodes */ private int mNumberOfMethods = 0; /** * Nombre de classes */ private int mNumberOfClasses = 0; /** * Adaptateur */ private OOMcCabeAdaptator mAdaptator; /** * Chemin du fichier � parser */ private String mReportFileName = null; /** * Logger */ private static final Log LOGGER = LogFactory.getLog( McCabePersistor.class ); /** le parser */ private LanguageParser mParser; /** Le template pour le rapport de classe */ private String mClassTemplate; /** Les chemins vers les JSPs si il y en a */ private List mJspPaths; /** * Constructeur. * * @param pParser le parser. * @param pConfiguration configuration du framework. * @param pAudit audit encadrant l'ex�cution. * @param pSession la session de persistance utilis�e par la t�che. * @param pDatas la liste des param�tres temporaires du projet * @param pTaskName le nom de la tache (pour diff�rencier java et cpp) * @param pClassTemplate le template � utiliser * @throws JrafDaoException si une session de peristance ne peut �tre cr��e. */ public OOMcCabePersistor( LanguageParser pParser, final McCabeConfiguration pConfiguration, final AuditBO pAudit, final ISession pSession, TaskData pDatas, String pTaskName, String pClassTemplate ) throws JrafDaoException { super(pSession,pDatas,pTaskName,pAudit,pConfiguration); mParser = pParser; ComponentRepository repository = new ComponentRepository( mProject, mSession ); mAdaptator = new OOMcCabeAdaptator( pParser, repository ); mClassTemplate = pClassTemplate; ListParameterBO jsps = (ListParameterBO) mProject.getParameter( ParametersConstants.JSP ); if ( null != jsps ) { // Il s'agit d'un projet J2EE mJspPaths = BuildProjectPath.buildProjectPath( (String) pDatas.getData( TaskData.VIEW_PATH ), jsps.getParameters() ); } } /** * Parse le rapport des m�triques de classe. * * @param pFilename chemin du fichier rapport. * @throws Exception si un probl�me de parsing apparait. * @return le nombre de r�sultats de niveau classe * @roseuid 42B976100269 */ public int parseClassReport( final String pFilename ) throws Exception { mReportFileName = pFilename; LOGGER.info( McCabeMessages.getString( "logs.debug.report_parsing_class" ) + mReportFileName ); // R�cup�rer les beans issus du rapport de classes McCabe CSVParser csvparser = new CSVParser( McCabeMessages.getString( "csv.config.file" ) ); Collection classResults = csvparser.parse( McCabeMessages.getString( mClassTemplate ), pFilename ); // Ajout de la volum�trie dans les beans Iterator it = classResults.iterator(); McCabeQAClassMetricsBO bo = null; while ( it.hasNext() ) { // On adapte chaque bean issu du rapport bo = (McCabeQAClassMetricsBO) it.next(); bo.setAudit( mAudit ); bo.setTaskName( mTaskName ); // On nettoie le nom du composant si celui-ci a �t� mal remont� du rapport, // en effet, quand le s�parateur de valeur est la virgule et qu'une valeur contient // une virgule, alors cette valeur est plac�e entre guillemets bo.setComponentName( ToolsReportsUtility.clearReportName( bo.getComponentName() ) ); // Le bean est adapt�, c'est-�-dire qu'on le lie � son composant // Si il s'agit d'une page JSP, on a stocker une partie de // ses r�sulats dans la map mJspResults McCabeQAJspMetricsBO jspMetrics = (McCabeQAJspMetricsBO) mJspResults.get( bo.getComponentName() ); boolean isJSP = ( null != jspMetrics ); if ( isJSP ) { // On ne fait pas persister le bo en tant que Classe it.remove(); jspMetrics.setClassMetrics( bo ); if ( null != jspMetrics.getComponent() ) { mJspResults.put( bo.getComponentName(), jspMetrics ); } } else { // Sinon on l'adapte � une classe mNumberOfClasses++; mAdaptator.adaptClassResult( bo ); } if ( null == bo.getComponent() && !isJSP ) { // La classe n'a pu persister, on ne fait pas persister // le bo et on lance un warning it.remove(); LOGGER.warn( McCabeMessages.getString( "logs.warn.incorrect_class_name", bo.getComponentName() ) ); } } LOGGER.info( McCabeMessages.getString( "logs.debug.report_parsing_database" ) ); // On sauvegarde le mesures sur les classes MeasureDAOImpl.getInstance().saveAll( mSession, classResults ); // On sauvegarde le mesures sur les JSP si il y en a MeasureDAOImpl.getInstance().saveAll( mSession, mJspResults.values() ); mSession.commitTransactionWithoutClose(); mSession.beginTransaction(); LOGGER.info( McCabeMessages.getString( "logs.debug.report_parsing_end" ) ); return classResults.size(); } /** * Parse le rapport des m�triques de m�thodes. * * @param pFilename chemin du fichier rapport. * @param pDatas les donn�es temporaires * @throws Exception si un probl�me de parsing appara�t. * @return le nombre de r�sultats de niveau m�thode r�cup�r�s. * @roseuid 42B9761F015F */ public int parseMethodReport( final String pFilename, TaskData pDatas ) throws Exception { mReportFileName = pFilename; LOGGER.info( McCabeMessages.getString( "logs.debug.report_parsing_method" ) + mReportFileName ); // R�cup�rer les beans issus du rapport de m�thodes McCabe CSVParser csvparser = new CSVParser( McCabeMessages.getString( "csv.config.file" ) ); Collection methodResults = csvparser.parse( McCabeMessages.getString( "csv.template.method" ), pFilename ); McCabeQAMethodMetricsBO bo = null; String name = null; int count = 0; // On cr�e une nouvelle collection contenant les beans � faire effectivement persister List resultsToPersist = new ArrayList(); // Adaptation des beans Iterator it = methodResults.iterator(); while ( it.hasNext() ) { bo = (McCabeQAMethodMetricsBO) it.next(); it.remove(); name = bo.getComponentName(); // On nettoie le nom du composant si celui-ci a �t� mal remont� du rapport, // en effet, quand le s�parateur de valeur est la virgule et qu'une valeur contient // une virgule, alors cette valeur est plac�e entre guillemets name = ToolsReportsUtility.clearReportName( name ); bo.setComponentName( name ); String className = mParser.getParentName( name ); // On v�rifie que la m�thode n'est pas contenue dans les classes � exclure // Et que la classe n'est pas nulle (sinon c'est signe d'une d�faillance McCabe) bo.setAudit( mAudit ); String absoluteFileName = bo.getFilename(); // Le nom du fichier est mis en relatif par rapport � la racine du projet String viewPath = (String) pDatas.getData( TaskData.VIEW_PATH ); bo.setFilename( FileUtility.getRelativeFileName( absoluteFileName, viewPath ) ); bo.setTaskName( mTaskName ); // Le bean est adapt�, c'est-�-dire qu'on le lie � son composant // A un composant JSP si le nom du fichier se termine par .jsp if ( bo.getFilename().endsWith( JSP_EXTENSION ) && null != mJspPaths ) { String componentName = bo.getComponentName().replaceFirst( JSP_METHOD_REGEXP, "" ); // On nettoie le nom pour enlever le "_jsp" bo.setComponentName( ToolsReportsUtility.clearJspName( componentName ) ); McCabeQAJspMetricsBO jspMetrics = new McCabeQAJspMetricsBO( bo ); // On r�cup�re le r�pertoire racine contenant les JSP File rootDir = null; String relativeRootDir = null; int id = 0; for ( int i = 0; i < mJspPaths.size() && null == relativeRootDir; i++ ) { rootDir = new File( (String) mJspPaths.get( i ) ); if ( null != FileUtility.findFileWithPathSuffix( rootDir, absoluteFileName ) ) { relativeRootDir = FileUtility.getRelativeFileName( rootDir.getAbsolutePath(), viewPath ); id = i; } } if ( null != relativeRootDir ) { mAdaptator.adaptJspResult( jspMetrics, relativeRootDir, id ); } if ( null == jspMetrics.getComponent() ) { // On lance un warning car le composant n'a pu �tre pars� LOGGER.warn( McCabeMessages.getString( "logs.warn.incorrect_jsp_method_name", jspMetrics.getComponentName() ) ); } else { // On enregistre le nom du composant avant la suppression du "_jsp" // pour pouvoir comparer correctement. mJspResults.put( componentName, jspMetrics ); } } else { // A une m�thode java mAdaptator.adaptMethodResult( bo ); if ( null == bo.getComponent() ) { // On lance un warning car le composant n'a pu �tre pars� LOGGER.warn( McCabeMessages.getString( "logs.warn.incorrect_method_name", bo.getComponentName() ) ); } else { mNumberOfMethods++; count++; resultsToPersist.add( bo ); } } } // La collection des r�sultats de m�thodes est persist�e LOGGER.info( McCabeMessages.getString( "logs.debug.report_parsing_database" ) ); MeasureDAOImpl.getInstance().saveAll( mSession, resultsToPersist ); mSession.commitTransactionWithoutClose(); mSession.beginTransaction(); LOGGER.info( McCabeMessages.getString( "logs.debug.report_parsing_end" ) ); return methodResults.size(); } /** * Cr�e et fait persister les r�sultats de niveau projet. * * @roseuid 42E09E5201AB */ public void persistProjectResult() { LOGGER.info( McCabeMessages.getString( "logs.debug.project_database" ) ); McCabeQAProjectMetricsBO metrics = new McCabeQAProjectMetricsBO(); // Cr�ation des m�triques de niveau projet metrics.setComponent( mProject ); metrics.setAudit( mAudit ); metrics.setTaskName( mTaskName ); metrics.setNumberOfClasses( new Integer( mNumberOfClasses ) ); metrics.setNumberOfMethods( new Integer( mNumberOfMethods ) ); try { MeasureDAOImpl.getInstance().create( mSession, metrics ); } catch ( JrafDaoException e ) { LOGGER.error( e, e ); } } }