/** @see org.squale.squalix.util.process.ProcessOutputHandler#processOutput(java.lang.String) */ public void processOutput(String pOutputLine) { // On filtre une erreur connue "Can't create directory '/OUTILS/McCabe/current/repos'." // qui ne gêne en rien le bon déroulement de McCabe. if (mConfiguration != null && !mConfiguration.ignoreMsg(pOutputLine)) { // On ajoute le nom du fichier au message s'il le faut mConfiguration.addFileNameToMsg(pOutputLine, mCurrentComponent); // CAS ERREUR if (pOutputLine.startsWith("ERR")) { // On teste si le message d'erreur ne fait pas parti des messages à considérer comme warning if (mConfiguration.changeErrorMsgToWarning(pOutputLine)) { // On log un warning initError(pOutputLine, ErrorBO.CRITICITY_WARNING); } else { // Il s'agit d'une erreur initError(pOutputLine, ErrorBO.CRITICITY_FATAL); mStatus = FAILED; } // CAS WARNING } else if (pOutputLine.startsWith("WARN")) { initError(pOutputLine, ErrorBO.CRITICITY_WARNING); } else if (pOutputLine.matches( "cli: Processing " + (String) mData.getData(TaskData.VIEW_PATH) + ".*")) { // On récupère le nom du fichier en coupant la chaîne du début et le viewPath mCurrentComponent = pOutputLine.replaceFirst( "cli: Processing " + (String) mData.getData(TaskData.VIEW_PATH), ""); } // On ne récupère pas les autres traces } }
/** * Génère un rapport de métriques McCabe. * * @param pReport le nom de rapport à générer. * @throws Exception si un problème d'exécution apparaît. */ protected void createReport(final String pReport) throws Exception { LOGGER.info(McCabeMessages.getString("logs.create.report", pReport)); // Lancement de la création de tous les rapports String reportFileName = computeReportFileName(pReport); ArrayList params = new ArrayList(); params.add(mConfiguration.getCliCommand()); String param = null; for (int j = 0; j < mConfiguration.getMetricsCommand().length; j++) { // Remplacer les paramètres configurables (%...%), ce sont des paramètres // qui remplacent des clés dans les paramètres de configuration // des analyses McCabe (classpath pour Java,...) param = mConfiguration.getMetricsCommand()[j].replaceAll( McCabeMessages.getString("key.substition.report_name"), pReport); param = param.replaceAll(McCabeMessages.getString("key.substition.report_out"), reportFileName); params.add(param); } String type[] = new String[0]; String modifiedParams[] = (String[]) params.toArray(type); mProcess = createProcessManager( modifiedParams, mConfiguration.getSubWorkspace(), mConfiguration.getLogger()); // On veut gérer les informations lancées par le processus en sortie mProcess.setOutputHandler(this); int resultMetrics = mProcess.startProcess(this); if (resultMetrics != 0) { throw new McCabeException( McCabeMessages.getString("error.processing") + " #" + resultMetrics); } }
/** @see org.squale.squalix.util.process.ProcessErrorHandler#processError(java.lang.String) */ public void processError(String pErrorMessage) { // cette méthode n'est effectué que si le message n'est pas à ignorer if (!mConfiguration.ignoreMsg(pErrorMessage)) { LOGGER.error(McCabeMessages.getString("logs.error.tools_error") + pErrorMessage); // Certaines erreurs sonst connues, on va alors essayer de les mapper avec // un message plus explicite ErrorBO error = new ErrorBO(); error.setInitialMessage(pErrorMessage); // On modifie le message en remplaçant par un message plus explicite si il est défini error.setMessage(mConfiguration.getReplacingMsg(pErrorMessage)); // sinon on met un message générique if (pErrorMessage.equals(error.getMessage())) { error.setMessage(McCabeMessages.getString("error.processing")); } error.setLevel(ErrorBO.CRITICITY_FATAL); if (!mConfiguration.ignoreMsg(pErrorMessage) && !mConfiguration.changeErrorMsgToWarning(pErrorMessage)) { mErrors.add(error); } // Et on insère la chaîne dans le fichir de log des erreurs si le buffer a été crée if (mErrorWriter != null) { try { mErrorWriter.write(pErrorMessage + "\n"); } catch (IOException e) { // On log juste l'erreur LOGGER.warn(e); } } } }
/** * Parse les fichiers sources afin d'en extraire les métriques. * * @return le résultat du process de parsing. * @throws Exception si un problème de parsing apparaît. */ protected int parseSource() throws Exception { // Execute le parsing des sources avec McCabe String[] parseCommand = new String[mConfiguration.getParserCommand().length + 1]; parseCommand[0] = mConfiguration.getCliCommand(); for (int i = 1; i < parseCommand.length; i++) { // On met en forme la liste des paramètres pour la passer au process parseCommand[i] = mConfiguration.getParserCommand()[i - 1]; } LOGGER.info( McCabeMessages.getString( "logs.running_parsing", new Object[] {mProject.getParent().getName(), mProject.getName()})); mProcess = createProcessManager( parseCommand, mConfiguration.getSubWorkspace(), mConfiguration.getLogger()); // On veut gérer les informations lancées par le processus en sortie mProcess.setOutputHandler(this); // On cherche à avoir un comportement synchrone pour être sûr de ne pas // avoir un état des données incohérent int resultParse = mProcess.startProcess(this); LOGGER.info( McCabeMessages.getString( "logs.return_parsing", new Object[] { mProject.getParent().getName(), mProject.getName(), new Integer(resultParse) })); return resultParse; }
/** * Crée le fichier contenant le chemin vers les modèles de rapports McCabe et celui avec les * paramètres spéciaux utilisateurs. * * @param pConfiguration configuration à utiliser. * @throws IOException Si un problème d'écriture du fichier apparaît. */ protected void createSpcFile(final McCabeConfiguration pConfiguration) throws IOException { String spcFileName = pConfiguration.getSubWorkspace().getAbsolutePath() + File.separator + McCabeMessages.getString("reports_db.name"); BufferedWriter bw = new BufferedWriter(new FileWriter(spcFileName)); bw.write(McCabeMessages.getString("spc.header")); bw.write(pConfiguration.getReportsPath().getAbsolutePath()); bw.close(); String userFileName = pConfiguration.getSubWorkspace().getAbsolutePath() + File.separator + McCabeMessages.getString("user_def.name"); bw = new BufferedWriter(new FileWriter(userFileName)); bw.write(McCabeMessages.getString("file.user.def.header")); bw.write(pConfiguration.getReposDir().getAbsolutePath()); bw.newLine(); bw.close(); }
/** * Prépare l'environnement d'exécution de l'analyse : * * <ul> * <li>Création du dossier destination des résultats du parsing * <li>Création du fichier config.pcf * </ul> * * @exception Exception si un probleme d'initialisation apparait */ protected void initialize() throws Exception { // On récupère la configuration du module McCabe, personnalisée // avec les paramètres du projet mConfiguration = McCabeConfiguration.build( mProject, McCabeMessages.getString("configuration.file"), getData()); try { // On tente de le créer si il n'existe pas mConfiguration.getErrorLogger().getParentFile().mkdirs(); mErrorWriter = new BufferedWriter(new FileWriter(mConfiguration.getErrorLogger())); } catch (IOException ioe) { // On log l'erreur LOGGER.warn( "Erreur sur le fichier de log des erreurs : " + mConfiguration.getErrorLogger().getAbsolutePath()); LOGGER.warn(ioe); } File workspace = mConfiguration.getWorkspace(); if (!workspace.exists() || !workspace.isDirectory() || !workspace.canWrite() || !workspace.canRead()) { // On va vérifier que le workspace est disponible throw new Exception(McCabeMessages.getString("exception.no_workspace")); } // On crée le fichier de description de l'analyse dans le workspace McCabePCFFile pcfFile = new McCabePCFFile(mConfiguration, getData()); createProjectConfigurationFile(pcfFile); // On crée une instance de persisteur et du template utilisant la session déjà ouverte setParser(); setPersistor(); LOGGER.info( McCabeMessages.getString("logs.initialized") + mProject.getParent().getName() + " - " + mProject.getName()); }
/** * L'analyse complète consiste en : * * <ul> * <li>Lancement du parsing sur l'application * <li>Création des rapports * <li>Création des beans à partir des rapports * <li>Transformation des beans en beans persistants * <li>Persistance des beans * </ul> * * A la fin de l'analyse on effectue les opérations de cloture de tache * * @throws TaskException Si un problème d'exécution apparaît. */ public void execute() throws TaskException { try { initialize(); LOGGER.info( McCabeMessages.getString("logs.analyzing") + mProject.getParent().getName() + " - " + mProject.getName()); int resultParse = parseSource(); if (0 == resultParse) { // Si le parsing s'est bien déroulé, on génère les rapports // Creation de la base de rapports createSpcFile(mConfiguration); String reportName = null; for (int i = 0; i < mConfiguration.getReports().size(); i++) { // Pour chaque nom de rapport configurés dans le fichier de configuration // McCabe, on va le créer, le parser et le mapper sur les objets reportName = (String) mConfiguration.getReports().get(i); createReport(reportName); } // On parse maintenant les rapports for (int i = 0; i < mConfiguration.getReports().size(); i++) { // Pour chaque nom de rapport configurés dans le fichier de configuration // McCabe, on va le créer, le parser et le mapper sur les objets reportName = (String) mConfiguration.getReports().get(i); parseReport(reportName); } // Une fois que tous les rapports ont été générés et parsés, // on peut générer les résultats de niveau projet persistProjectResult(); } // positionne les données sur la taille du file System affectFileSystemSize(mConfiguration.getSubWorkspace(), true); // Lance les opérations de cloture de la tâche FileUtility.deleteRecursively(mConfiguration.getSubWorkspace()); if (0 != resultParse) { // Si le parsing ne s'est pas bien déroulé, on lance une exception throw new Exception(McCabeMessages.getString("exception.parsing_error")); } if (mErrorWriter != null) { mErrorWriter.close(); } } catch (Exception e) { throw new TaskException(e); } }
/** * Détermination du fichier de rapport * * @param pReport rapport * @return nom complet du rapport * @throws IOException si erreur */ protected String computeReportFileName(final String pReport) throws IOException { String reportFileName = pReport + McCabeMessages.getString("reports_extension"); reportFileName = mConfiguration.getSubWorkspace().getCanonicalPath() + File.separator + reportFileName; return reportFileName; }
/** * Création du fichier de configuration McCabe Ce fichier de configuration contient la liste des * fichiers * * @param pFile fichier * @throws Exception si erreur */ protected void createProjectConfigurationFile(McCabePCFFile pFile) throws Exception { pFile.build(); // On copie le PCF sous le nom <projet>.pcf si le nombre de fichiers .pcf dans le workspace // est < 10 File backupDir = new File( mConfiguration.getWorkspace() + File.separator + McCabeMessages.getString("pcf.log.dir")); backupDir.mkdirs(); File[] backupDirFiles = backupDir.listFiles(); if (backupDirFiles != null) { // On tri selon le nom du fichier décroissant pour ne pas écraser les fichiers qui porte sur // le // même projet. List files = Arrays.asList(backupDirFiles); Collections.sort(files); Collections.reverse(files); // On renomme tous les fichiers avec l'extension ext+1 String fileName; String newFileName; File backUpFile = null; int ext; for (int i = 0; i < files.size(); i++) { fileName = ((File) files.get(i)).getName(); // Si un fichier porte l'extension max, on le supprime if (fileName.matches(".*\\." + (McCabeConfiguration.MAX_PCF_SAVED - 1))) { ((File) files.get(i)).delete(); } else { ext = 0; // On récupère l'extension int lastDot = fileName.lastIndexOf("."); if (lastDot > 0) { try { ext = Integer.parseInt(fileName.substring(lastDot + 1)) + 1; // On renomme le fichier newFileName = fileName.substring(0, lastDot + 1) + ext; ((File) files.get(i)) .renameTo( new File( backupDirFiles[i].getParentFile().getAbsoluteFile() + File.separator + newFileName)); } catch (NumberFormatException nbfe) { // On renommera le fichier avec l'extension 1 (pour ne pas écraser celui // qui existe) backUpFile = (File) files.get(i); } } } } // On copie le fichier pcf dans le répertoire de sauvegarde String backupName = backupDir.getAbsolutePath() + File.separator + mProject.getName() + ".pcf"; // On renomme le fichier extension.1 si il existe if (backUpFile != null) { backUpFile.renameTo(new File(backUpFile.getAbsolutePath() + ".1")); } FileUtility.copyFile(pFile.getPcfFile(), new File(backupName)); } }