How to implement a new tool in Squale ?

How does Squalix run?

Squalix is the batch part of the main application which executes the audits planed in Squale-Web. As explained in the architecture part, the whole application is composed of three main parts. * Squale-web : in charge of configuring the audits and returning the results (the web portal) * Squale-core : in charge of the main aggregations * Squalix : in charge of the batch part [] In Squale an audit concerns an application. Each application could contain one or more projects. Squale audits the first project of the first planned application then the second one and so on. Please refer to the illustration bellow.



For Squalix, an audit on a project is a succession of tasks beginning from analysis tasks and ending with termination tasks. The tasks that squalix has to complete for an audit on a project depend on :

  • The profile chosen for the project.
  • The kind of source recovery chosen for the projet.

Profile and source recovery mode are configured by the user in squale-web for each project. The list of tasks that have to be completed for a profile and a source recovery can be found (and modified) in the file : squalix-config.xml ( Squale-core : src/main/config/). Only administrator can upload into Squale a new squalix-config.xml.

Each tool implemented in Squalix defines an analysis task and/or a termination task. Termination task is the part of the task which should be done after all analysis task. Example :

  • The scm source recovery tool has an analysis task and a termination task. The analysis task do the recovering of the source. The termination task suppress the source code. The suppression should be done after all analysis tasks have been done.
  • The java compilation tool compiles the recovered source code. It has an analysis task which does the compilation. It also has a termination task which suppresses the compiled code. (This task should be done after all analysis tasks)
  • The javancss tool executes the software javancss on the code that has to be audited and pushes the results in the database. It only has an analysis task.

In general, analysis tasks represent the core part of a task, completing the main part of the job. The termination tasks complete the cleaning part.

Now we know how Squalix runs, let's see how to implement a new tool in Squale.

Implementation of a new tool in Squale

To implement a new tool, obviously you have to create an analysis task and/or a termination task and a bit more regarding the kind of task you wish to implement.

  1. What do we need ?

    First answer this short list of questions, for each task :

    • Define the name of the task (hereafter taskName).
    • Which configuration informations do we need in order to run the task ?
      • List those given/configured by the user (you will need a jsp interface for that).
      • List those recovered from a configuration file in squalix.
    • Does this task recover metric informations ?
      • If yes : list all the metrics and their level (class, package...) that you need to push in the database (you will use these measurement in the audit result in a later stage)
      • If no, is there some informations you want to push in the database ?
        • If yes list these informations

    Now let's see how create a task.

  2. Create the task

    If you create a task to recover metric informations go to part II.1. Else go directly to part II.2.

    1. You create a task to recover metric informations

      List all the metric you want to recover and their level ( method, class, package, project, ...).

      Then you should create a class tree like this scheme :



      For the class tree :

      • The classes should be created in squale-core : src/main/java/org/squale/squalecommon/enterpriselayer/businessobject/result/taskName
      • The name of your classes should finish by MetricsBO
      • The classes should extends MeasureBO (directly or not)
      • You should have at least one class by level of result (method, class, ...)

      Contents of these classes ?

      All these classes extends MeasureBO.java which contains a map. The main aim of these classes is to put elements into this map. Example :

          private static final  String  SUMVG = "sumVg";
          
      
          public JavancssClassMetricsBO()
          {
              super();
              
                      // getMetric() recover the map define in MeasureBO
                      // We put element in this map
                       
              getMetrics().put( CLASSES, new IntegerMetricBO() );
              getMetrics().put( METHODS, new IntegerMetricBO() );
              getMetrics().put( MAXVG, new IntegerMetricBO() );
              getMetrics().put( SUMVG, new IntegerMetricBO() );
          }
          
       
          public Integer getSumVg()
          {
              return (Integer) ( (IntegerMetricBO) getMetrics().get( SUMVG ) ).getValue();
          }
      
          
          public void setSumVg( int pSumVg )
          {
              ( (IntegerMetricBO) getMetrics().get( SUMVG ) ).setValue( pSumVg );
          }
              

      You should define :

      • One final static variable for each metric you want put in database.
      • A constructor which initializes the add to the map. Each element added to the map has for key the name of a metric ( the final static variable define above ) and for value, the value of the metric. Each value should be put in a BO (in our example above it's an IntegerMetrciBO).
      • Define getters and setters associated to each metric in order to modify the value in the map.
      • Don't forget to write the xdoclet comments and to regenerate the mapping in order to make sure relations between database and BO work correctly.

      Now we could create the task.

    2. Create the structure of the task
      1. Where should the class for the tool be created ?

        All the tasks are in the package src/main/java/org/squale/squalix/tools/

        In this package create a new package which name will be taskName. (In general the name of the task is the name of the tool which will compute the metrics). Put in this package all the classes you created especially for this task.

        To create an analysis task go to part II.2.b. To create a termination task go to part II.2.c.

      2. Structure of Analysis_Task

        For an analysis task you should create a class.

        • The name of this class is taskNameTask
        • This class should extend AbstractTask.java
        • This class should have the method execute(). It is by this method that the task is launched. (Thanks to the inheritance this method should already exist).
        • This class should have a constructor with no argument where the variable mName is initiated to taskNameTask.

        In the following of the document mName correspond to : taskNameTask.

      3. Structure of the termination task

        For a termination task, you should create a class.

        • The name of this class is taskNameyyyTask where yyy correspond to "termination", "cleaner", ...
        • This class should extend AbstractTask.java. If this task is a source recovering task, then it should extend AbstractsourceterminationTask.
        • This class should have the method execute(). It is by this method that the task is launched. (Thanks to the inheritance this method should already exist).
        • This class should have a constructor with no argument where the variable mName is initiated to taskNameyyyTask.

        Bellow in the document the reference mName correspond to : taskNameyyyTask.

      4. Running of the task

        We recommend that a task work in three separate step

        • First : Recovering the informations of configuration and initialization
        • Second : execution of the tool
        • Third : (if needed) push in the database some result which come from the second step

        see part I.3 for more information on specification regarding the execution of the task.

      5. Note

        How Squalix know that a class correspond to an analysis task and another correspond to a termination task ?

        In fact this is defined in the squalix-config.xml file.

    3. Specification of task running

      A complete specification on how to create more generic tools (especially tools which do recover metrics) is in progress. More detail soon

      1. Initialization and recovering of configuration information

        In this part you will recover all informations of configuration.

        • The internal information of configuration are in general in a xml file that you have to create (you have also to create its dtd). That xml file should be put in : squalix/src/assembly/resources/config with a name : taskName-config.xml. The associate DTD should be put in : squalix/src/main/resources/config with a name : taskName-config.dtd. You could use the system of filter in that xml file (it's usefull when the parameter depend of the server). You can find the filter in : squalix/src/filters
        • For the informations of configuration given by the user (entered with the web interface see part III), you could recover the information by using this type of code :
          //Recovering of the map of parameter
                  
            MapParameterBO taskParam = (MapParameterBO) mProject.getParameter( ParametersConstants.SCM );
          
          
          //Recovering of the parameters
          
            ListParameterBO pathToAudit =
                   (ListParameterBO) taskParam.getParameters().get( ParametersConstants.SCMLOCATION );
                          
            StringParameterBO password =
                   (StringParameterBO) pTaskParam.getParameters().get( ParametersConstants.SCMPASSWORD );

        More informations on the static variables of ParametersConstants used here in the part III.4

      2. Execution of the tool

        This part of the code is the one which does the job. Example for a source recovering tool, it's in this part that we will recover the code. We encourage you to use already existent code. For example if for the software you want use, an ant task exists, then try to use this ant task, than to rewrite a launcher.

        For task which does recover metrics that will be pushed in the database, results should be saved in a file (xml, csv).

        We advise against do the execution and push in the database in the same time without pass by a file result.

      3. Push results in the database

        This part is dedicated to task which recovers metrics. This part should, if possible, run separately from the previous step. This part should take a result file ( file which comes from the execution or is external ) and parse it.

        It's here, that we will use the xxxMetricBO that we have created above. We fill it by using informations from the parsing operation.

        To search and create the componentBO (applicationBO, packageBO, classBO, methodBO ) use the code already existent in Squale.

        // Completion of the package level BO and recording of new components
                /* With the parsing we have create an arraylist of JavancssPackageMetricsBO 
                 * fill with the information from the parse.
                 */
                        
                ArrayList packageResults = parsingResult.getPackageResult();
            for ( int i = 0; i < packageResults.size(); i++ )
            {
                 JavancssPackageMetricsBO packageMetrics = 
                        (JavancssPackageMetricsBO) packageResults.get( i );
                    
                /* We create the packageBO corresponding to the component name 
                 * include in the JavancssPackageMetricsBO
                 */
                 PackageBO packBO = parser.getPackage( packageMetrics.getComponentName() );
                 
                 packageMetrics.setAudit( getAudit() );
                
                    
                 /* repository.persisteComponent( packBO ) permit to persit the packageBO 
                  * (and its parents) if is(are) not already exist.
                  */
                
                 packageMetrics.setComponent( repository.persisteComponent( packBO ) );
                    
                 packageMetrics.setTaskName( getName() );
             }
                
                
        
        // Recording of the package level results.
            MeasureDAOImpl.getInstance().saveAll( getSession(), parsingResult.getPackageResult() );
        
    4. Modify squalix-config.xml

      A generic squalix-config.xml file could be found in : squale-core/src/main/config.

      Define in Squalix-config.xml the new task, and modify the profile define in this file to take into account new tasks.

      Only administrator has the needed authorisation to put into squale the new squalix-config file.

  3. Create the configuration interface :

    We need the list of informations of configuration that the user should enter.

    The new jsp that we create, will be called by config_project.jsp (Squale-web/src/main/webapp/jsp/admin/project). Config_project.jsp will include our jsp in a dropdown panel by using a <jsp:include> tag.

    Extract of code of config_project.jsp.

    <logic:iterate id="task" scope="session" name="createProjectForm" property="advancedTasks">
            
            <bean:define name="task" property="name" id="taskName"  type="String" />
            
            <%expanded = false;%>
            <logic:equal name="toolBean" value="<%=taskName%>">
                    <%expanded = true; %>
            </logic:equal>
                                            
                    <%
            // recuperation des clés
            String keyTask = "task." + taskName.toLowerCase() + ".configuration";
            
            // récupération de la page
            String pageTask = "add_project_" + taskName.toLowerCase() + "_conf.jsp";%>
    
            <af:dropDownPanel titleKey="<%=keyTask%>"
                    headerStyle="padding-left:20px;" contentStyle="padding:5px;"
                    lazyLoading="false" expanded="<%=expanded%>">
    
                    <c:import url="/${taskName}.do?action=fill&${org.squale.squaleweb.
                            applicationlayer.action.accessRights.BaseDispatchAction.DO_NOT_RESET_FORM}=true" />
                            
                    <div id="conteneur"><jsp:include page="<%=pageTask%>" /></div>
                            
            </af:dropDownPanel>
            
    </logic:iterate>
                            
    1. Create the form bean

      Steps to create the form bean class :

      • Create the form bean in squale-web : src/main/java/org/squale/squaleweb/applicationlayer/formbean/component/parameters
      • The name of the class should be taskNameForm.
      • This class should extend AbstractParameterForm.
      • One private variable and its public accessors for each parameter of configuration that has to be recovered.

      Now creation of the jsp.

    2. Create the jsp for configuration :

      That JSP will be used in a <jsp:include> tag in the jsp config_project.jsp (See extract of the code above)

      • The jsp for configuration should be create in Squale-web/src/main/webapp/jsp/admin/project
      • The name has to be : add_project_mName_conf.jsp and mName should be in lower case. This name format is needed in config_project.jsp (squale-web : src/main/webapp/jsp/admin/project). See the extract of code above.
      • Add tag <af:field> for each parameter.
         
        // For one parameter :
                                
                        <tr class="fondClair">
                                <af:field key="project_creation.field.login" name="scmForm"
                                        property="login" isRequired="false" styleClassLabel="td1" size="60"
                                        disabled="<%=disabled%>" />
                        </tr>
        
        
        
        // For a list of parameter (here paths to the sources ; we could have more one path) :
        
                        <tr>
                                <af:field styleClassLabel="td1"
                                        key="project_creation.field.pathToAudit" property="location"
                                        value="" size="60" />
                        </tr>
                        <squale:iteratePaths name="scmForm"
                                key="project_creation.field.pathToAudit" property="location"
                                isRequired="true" disabled="<%=disabled%>" />
                                
      • Don't forget to define the variable "disabled" in the jsp. When a user who is only a reader access to the page then that variable take the value "true". So the field become disabled and then the user can't modify the parameters.
                <%-- Readers can't update the configuration --%>
                <bean:define id="userProfile"
                        name="<%=org.squale.welcom.struts.util.WConstants.USER_KEY%>"
                        property='<%="profile("+applicationId+")"%>' />
                <%-- All the fields --%>
                <%boolean disabled = false; // Used to grant writing %>
                <logic:equal name="userProfile"
                        value="<%=ProfileBO.READER_PROFILE_NAME%>">
                        <%disabled = true;%>
                </logic:equal>
        

      For all details, take example on the already existent jsp (ex : add_project_scmTask_conf.jsp ) to create yours.

    3. Create the action

      Steps to create the action class

      • Create the class action associate to the JSP under squale-web : src/main/java/org/squale/squaleweb/applicationlayer/action/component/parameters
      • The name of the class should be CreatetaskNameParametersAction
      • That class should extend CreateParametersAction

      Let's see the ParametersConstants

    4. Add parameter to the ParametersConstants

      For each parameter of configuration that has to be recovered, create a new public static final variable in the class ParametersConstants (squale-core/src/main/java/org/squale/squalecommon/enterpriselayer/businessobject/component/parameters).

    5. Create the transformer

      Steps to create the transformer :

      • Create the transformer in squale-web : src/main/java/org/squale/squaleweb/transformer/component/parameters/... .
      • The name of the class should be taskNameConfTransformer
      • The class implements WITransformer
      • Use the static variables created in ParametersConstants
                public WActionForm objToForm( Object[] pObject )
                throws WTransformerException
            {
                ScmForm scmForm = new ScmForm();
                objToForm( pObject, scmForm );
                return scmForm;
            }
            
            
            
            public void objToForm( Object[] pObject, WActionForm pForm )
                throws WTransformerException
            {
                MapParameterDTO projectParams = (MapParameterDTO) pObject[0];
                MapParameterDTO params = 
                        (MapParameterDTO) projectParams.getParameters().get( ParametersConstants.SCM );
                if ( params != null )
                {
                    // Fill the form
                    ScmForm scmForm = (ScmForm) pForm;
                    Map ccParams = params.getParameters();
        
                    // User profile to connect to the remote repository
                    StringParameterDTO login = 
                        (StringParameterDTO) ccParams.get( ParametersConstants.SCMLOGIN );
                        
                    scmForm.setLogin( login.getValue() );
                    
                    // Location of paths to audit
                    ListParameterDTO locationsDTO = 
                        (ListParameterDTO) ccParams.get( ParametersConstants.SCMLOCATION );
                        
                    List locationsList = locationsDTO.getParameters();
                    Iterator it = locationsList.iterator();
                    String[] locations = new String[locationsList.size()];
                    int index = 0;
                    while ( it.hasNext() )
                    {
                        StringParameterDTO location = (StringParameterDTO) it.next();            
                        if (location.getValue() == null) {
                            locations[index] = " ";                    
                        } else {
                            locations[index] = location.getValue();
                        }
        
                        index++;
                    }
                    scmForm.setLocation( locations );
                }
            }
        
    6. Modify struts-config.xml

      Add <form-bean> and <action> taggs in struts-config.xml

      For the action, the name should be mName . This means that we call the action with : mName.do. This is necessary in config_project.jsp (squale-web : src/main/webapp/jsp/admin/project). See the extract of code above.

    7. Modify ApplicationRessources.properties

      Add the new keys used in the JSP in the document ApplicationRessource.properties, do not forget to translate the key/value couple in English/French and is derivative in different language (squale-web : src/main/java/org/squale/squaleweb/ressources/). Warning some of this key need a special name. See the extract of code above.

  4. Use of the measures in the audit results

    Now we have recovered the metric informations and pushed them in the database. But it's not enough, we want to use these informations in the results of the audit.

    For this :

    1. Create a new quality grid

      A new grid quality which take the new metrics into account should be wrote. This quality grid for Squale is an xml file which uses the dtd : org/squale/squalecommon/dtd/grid-1.1.dtd. Example of quality grid could be found in squale-core/src/main/config.

      Only administrator can put into squale the new grid.

    2. Modify squalix-config.xml

      Squalix-config.xml should be modified in order to take into account the new quality grid. A generic squalix-config.xml file could be found in : squale-core/src/main/config.

      Only administrator can put into squale the new squalix-config file.

    3. Messages.xml

      Labels for the new measures appearing in the squale results page. Add the new elements needed in the messages.xml (Squale-core : src/main/config/).

    4. Modify the file Mapping.java ( squale-core : src/main/java/org/squale/squalecommon/util/mapping/ )