/** * 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.macker; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import org.squale.jraf.commons.exception.JrafDaoException; import org.squale.jraf.spi.persistence.ISession; import org.squale.squalecommon.enterpriselayer.businessobject.component.AbstractComponentBO; import org.squale.squalecommon.enterpriselayer.businessobject.component.ClassBO; import org.squale.squalecommon.enterpriselayer.businessobject.component.ProjectBO; import org.squale.squalecommon.enterpriselayer.businessobject.result.rulechecking.RuleCheckingTransgressionBO; import org.squale.squalecommon.enterpriselayer.businessobject.result.rulechecking.RuleCheckingTransgressionItemBO; import org.squale.squalecommon.enterpriselayer.facade.macker.RuleFactory; import org.squale.squalix.util.file.FileUtility; import org.squale.squalix.util.parser.JavaParser; import org.squale.squalix.util.repository.ComponentRepository; import net.innig.macker.event.AccessRuleViolation; import net.innig.macker.event.ListenerException; import net.innig.macker.event.MackerEvent; import net.innig.macker.event.MackerEventListener; import net.innig.macker.event.MackerIsMadException; import net.innig.macker.rule.RuleSet; /** * R�cup�re toutes les transgressions des r�gles Macker */ public class JavaStorageListener implements MackerEventListener { /** S�parateur pour la classe concern� par la transgression */ public static final String FROM_SEPARATOR = " : "; /** S�parateur pour la classe en relation avec la transgression */ public static final String TO_SEPARATOR = " -> "; /** La liste des chemins absolus vers les sources */ protected List mPaths; /** La liste des fichiers inclus */ protected List mIncludedFiles; /** Le chemin de la vue */ protected String mViewPath; /** Contient le d�tails des transgressions */ protected HashMap mDetails; /** Contient le nombre de transgressions par r�gle */ protected HashMap mNbOcc; /** Les .class a analyser */ protected HashSet mFilesToAnalyse; /** Parser java */ protected JavaParser mParser; /** Aide � la cr�ation de composants */ protected ComponentRepository mRepository; /** * Constructeur par d�faut * * @param pSession la session * @param pProject le projet � auditer * @param pConfiguration la configuration Macker */ public JavaStorageListener( ISession pSession, ProjectBO pProject, MackerConfiguration pConfiguration ) { mIncludedFiles = pConfiguration.getIncludedFiles(); mViewPath = pConfiguration.getRoot(); mFilesToAnalyse = pConfiguration.getFilesToAnalyze(); mParser = new JavaParser( pProject ); mRepository = new ComponentRepository( pProject, pSession ); mNbOcc = new HashMap(); mDetails = new HashMap(); mPaths = pConfiguration.getSources(); } /** * @return le nombre de transgressions par r�gles */ public HashMap getNbOcc() { return mNbOcc; } /** * @return les d�tails des transgressions */ public HashMap getDetails() { return mDetails; } /** * {@inheritDoc} * * @see net.innig.macker.event.MackerEventListener#mackerStarted(net.innig.macker.rule.RuleSet) */ public void mackerStarted( RuleSet arg0 ) throws ListenerException { } /** * {@inheritDoc} * * @see net.innig.macker.event.MackerEventListener#mackerFinished(net.innig.macker.rule.RuleSet) */ public void mackerFinished( RuleSet arg0 ) throws MackerIsMadException, ListenerException { } /** * {@inheritDoc} * * @see net.innig.macker.event.MackerEventListener#mackerAborted(net.innig.macker.rule.RuleSet) */ public void mackerAborted( RuleSet arg0 ) { } /** * {@inheritDoc} * * @see net.innig.macker.event.MackerEventListener#handleMackerEvent(net.innig.macker.rule.RuleSet, * net.innig.macker.event.MackerEvent) */ public void handleMackerEvent( RuleSet pRuleSet, MackerEvent pEvent ) throws MackerIsMadException, ListenerException { // L'erreur est un acc�s ill�gal if ( pEvent instanceof AccessRuleViolation ) { // On r�cup�re l'�v�nement AccessRuleViolation violation = (AccessRuleViolation) pEvent; // On r�cup�re les classes en relation avec la transgression // si elles existent AbstractComponentBO from = null; AbstractComponentBO to = null; try { from = getComponent( violation.getFrom().getFullName() ); to = getComponent( violation.getTo().getFullName() ); } catch ( JrafDaoException e ) { throw new ListenerException( this, e.toString() ); } catch ( IOException e ) { throw new ListenerException( this, e.toString() ); } // Si la classe from n'est pas nulle (donc existe dans les sources // non exclues du projet), on ajoute la transgression: if ( null != from ) { // On r�cup�re le code de la r�gle si il existe sinon on met le code // par d�faut String code = RuleFactory.CODE; String message = RuleFactory.CODE; Iterator it = violation.getMessages().iterator(); if ( it.hasNext() ) { // Delete all spaces in message for future comparison message = ((String) it.next()).trim(); code = violation.getAccessRule().getMessage().trim(); } // On r�cup�re le nombre de transgression pour cette r�gle Integer nbOcc = (Integer) mNbOcc.get( code ); if ( null == nbOcc ) { nbOcc = new Integer( 0 ); } // On ajoute une occurence nbOcc = new Integer( nbOcc.intValue() + 1 ); // On enregistre la modification ou la cr�ation mNbOcc.put( code, nbOcc ); /* On ajoute le d�tail de cette transgression � la liste des d�tails */ RuleCheckingTransgressionItemBO item = new RuleCheckingTransgressionItemBO(); item.setComponent( from ); // On modifie le composant en relation avec la transgression item.setComponentInvolved( to ); // On concat�ne le nom des classes concern�es par la transgression // au message avec des s�parateurs universels pour pouvoir les r�cup�rer // par la suite pour l'affichage web. message += FROM_SEPARATOR + violation.getFrom().getFullName(); message += TO_SEPARATOR + violation.getTo().getFullName(); item.setMessage( message ); // On r�cup�re les items li�s � la r�gle ArrayList items = (ArrayList) mDetails.get( code ); if ( null == items ) { items = new ArrayList(); } // On ajoute le nouvel item � la liste seulement si le nombres des items // pour la r�gle est < 100 if ( items.size() < RuleCheckingTransgressionBO.MAX_DETAILS ) { items.add( item ); } // On ajoute la liste des items dans la map mDetails.put( code, items ); } } } /** * Cr�er et fait persister la classe dont le nom absolu est <code>pFullName</code> si celle-ci appartient au * projet � auditer et n'appartient pas � un des r�pertoires exclus. * * @param pFullName le nom absolu de la classe * @throws IOException si erreur de flux * @throws JrafDaoException si erreur de persistance * @return le composant persist� */ protected AbstractComponentBO getComponent( String pFullName ) throws IOException, JrafDaoException { ClassBO classBO = null; // On r�cup�re le nom relatif du fichier source si il est pr�sent // dans les sources. String relativeFileName = isInclude( pFullName ); if ( null != relativeFileName ) { // La classe appartient bien au projet � auditer // On r�cup�re la classe classBO = mParser.getClass( pFullName, relativeFileName ); // On fait persister la classe et on construit la mesure ckjm associ�e classBO = (ClassBO) mRepository.persisteComponent( classBO ); } return classBO; } /** * Le nom relatif du fichier dans lequel la classe est d�finis si il fait parti des fichiers inclus, null sinon * * @param pFullName le nom absolu de la classe * @return le nom relatif du fichier dans lequel la classe est d�finie * @throws IOException si erreur de flux */ protected String isInclude( String pFullName ) throws IOException { String relativeFileName = null; // On r�cup�re le fichier compil� associ� � la classe String classFileName = FileUtility.getClassFileName( mFilesToAnalyse, pFullName ); if ( null != classFileName ) { // On a trouv� le .class associ� // Le nom du fichier source dans lequel se trouve la d�finition de la classe String fileName = FileUtility.getFileName( classFileName ); // On v�rifie que la classe n'appartient pas � un r�pertoire exclu String packageName = mParser.getAbsolutePackage( pFullName ); // On construit le chemin relatif du fichier source de la classe String endOfFileName = FileUtility.buildEndOfFileName( packageName, fileName ); // On r�cup�re le nom absolu du fichier source si il est pr�sent // dans les param�tres. String absoluteFileName = FileUtility.getAbsoluteFileName( mPaths, endOfFileName ); if ( mIncludedFiles.contains( absoluteFileName ) ) { relativeFileName = FileUtility.getRelativeFileName( absoluteFileName, mViewPath ); } } return relativeFileName; } }