Monday, November 18, 2019

Implementing PMD 6.x, CPD, Checkstyle 3.x, JavaSources 3.x, JavaDocs 3.x, Findbugs 3.x or SpotBugs 4.x using maven



We all know the importance of static code analysis in software development. Static code analysis checks the source code files of an application without actually running the application. It validates the coding standards and required code style. It is very helpful during code review as well.

There are several Open source tools available which does static code analysis. Most popular ones are PMD, CPD (combined with pmd), Checkstyle, Findbugs and many more.

I have been using using PMD 5.x, CPD 5.x (combined with pmd), Checkstyle 2.x and FindBugs 2.x in combination for past 4-5 years.

I have a post on PMD5.x here if you want to check it out:
https://javaworld-abhinav.blogspot.com/2016/02/implement-pmd-findbugs-code-coverage.html


Open source and code quality enthusiasts has been contributing for these tools over the years and these tools are now very much intelligent and helping in delivering good quality code.

PMD on the other has been revamped alot and has more granular rule-sets.

You can see more on PMD here: https://pmd.github.io/latest/#overview

We can configure all the plugins (PMD, CPD, FindBugs, JavaSources and JavaDocs) as part of build life (default) cycle as well as site life cycle. Here we will see both.

There are 3 standard life cycles in maven. Clean, Build and Site.

In general,

  1. clean (which includes pre-clean,clean and post-clean) life cycle is used to clean the build directory.
  2. build (the default) life cycle (which includes validate, initialize, generate-sources, compile, test, package, verify, install and deploy etc.) used to build artifacts. It is the default life cycle in maven.
  3. site (which includes pre-site,site-post-site and site-deploy) lifecycle is used to create fresh documentation to create reports, deploy site etc.

If you want to know more  about maven life-cycles then refer below given link:


Prerequisites: You will need following plug-ins in order to implement PMD, CPD, FindBugs, JavaDocs, JavaSources and Java code coverage.

  JavaDocs:
  1. maven-javadoc-plugin (version 3.1.1)
  JavaSources:
  1. maven-source-plugin (version 3.2.0)
  PMD:
  1. maven-jxr-plugin (version 3.0.0)
  2. maven-pmd-plugin (version 3.12.0)
  FindBugs (Below Java9):
  1. findbugs-maven-plugin (version 3.0.5)

 SpotBugs (Java9 onwards):
  1. spotbugs-maven-plugin (version 3.1.12.2)
  2. spotbugs (4.0.0-beta4)
Post java9, findbugs is no longer maintained and we need to use spotbugs. It is successor of findbugs.

 Checkstyles:
  1. maven-checkstyle-plugin (version 3.1.0)
 Other Plugins to support build and reporting:
  1. maven-resources-plugin (version 3.0.1)
  2. maven-project-info-reports-plugin (version 2.7)
  3. maven-surefire-report-plugin (version 3.0.0-M3)
  4. maven-site-plugin (version 3.8.2)
Note: Using latest version of maven-project-info-reports-plugin (i.e. 3.0.0) doesn't work. Seems there are some bugs as using these plugin versions you get 

java.lang.NoClassDefFoundError: org/apache/maven/doxia/siterenderer/DocumentContent

Optional Plugins:
  1. maven-compiler-plugin (version 3.8.1) -- we need to override the maven compiler plug-in to set JDK version if your code is written in JDK 7 and above

To execute all plugins together you can run following command: mvn install site

Note: If you are getting 'java.lang.OutOfMemoryError: PermGen space' during the build then you have to set "MAVEN_OPTS=-XX:MaxPermSize=1024m".

If you are using eclipse you can set argument in 'VM Arguments' while running the maven command.


Configuring Java Sources maven plug-in:

This plug-in will generate a jar file containing the source code.


<!-- Java sources plug-in-->
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-source-plugin</artifactId>
 <version>3.2.0</version>
 <executions>
  <execution>
   <id>attach-sources</id>
   <goals>
    <goal>jar-no-fork</goal>
   </goals>
  </execution>
 </executions>
</plugin>


Configuring Java Docs maven plug-in



<!-- JavaDocs configuration-->
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-resources-plugin</artifactId>
 <version>3.0.1</version>
 <executions>
  <execution>
   <id>copy static resource files</id>
   <phase>generate-sources</phase>
   <goals>
    <goal>resources</goal>
   </goals>
  </execution>
 </executions>
</plugin>

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-javadoc-plugin</artifactId>
 <version>3.1.1</version>
 <executions>
  <execution>
   <id>attach-javadocs</id>
   <goals>
    <goal>jar</goal>
   </goals>
  </execution>
 </executions>
</plugin>





Configuring FindBugs maven plugin (Use this if you are using java8 or below): 

Here we are configuring findbugs into build lifecycle under 'package' phage. See <phase> element inside <executions>/<execution> element. The <plugins> element is configured under <build> element which means the plugin will be executed during build (life cycle) process.

To run findbugs you can use following command:

mvn findbugs:findbugs 

If you want to run findbugs and want the build to fail if violations are found, then you can use following command:

mvn findbugs:check

To see usage details on findbugs you can refer below website:

http://gleclaire.github.io/findbugs-maven-plugin/usage.html


<!-- FindBugs Integration, you can also run it directly using mvn findbugs:findbugs or findbugs:check -->
<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>findbugs-maven-plugin</artifactId>
 <version>3.0.5</version>
 <configuration>
  <!-- FindBugs will show what is doing during analysis. -->
  <debug>false</debug>
  <!-- Enables analysis which takes more memory but finds more bugs. If 
      you run out of memory, changes the value of the effort element to 'min'. 
      Min|Default|Max are possible values. -->
  <effort>Min</effort>
  <!-- Reports all bugs (other values are High|Normal|Low|Exp|Ignore) -->
  <threshold>High</threshold>
  <xmlOutput>true</xmlOutput>
  <!-- Optional directory to save findbugs xdoc xml report -->
  <xmlOutputDirectory>${project.reporting.outputDirectory}</xmlOutputDirectory>
  <!-- Indicates to analyze only given java packages, We are allowing everything here. -->
  <!-- <onlyAnalyze>com.*</onlyAnalyze> -->  
  <failOnError>true</failOnError>
 </configuration>
 <executions>
  <execution>
   <phase>package</phase>
   <goals>
    <!-- This goal will check code and generate report -->
    <!--<goal>findbugs</goal>-->
    <!-- Fail the build if there were any findBugs violations in the source code. Uncomment if needed -->
    <!-- This goal includes both findbugs and check -->
    <goal>check</goal>
   </goals>
  </execution>
 </executions>
</plugin>


Configuring SpotBugs maven plugin (Use this if you are using Java9 or above): 

Post java9, findbugs is no longer maintained and we need to use spotbugs. It is successor of findbugs.
SpotBugs looks for bugs in Java programs. It is based on the concept of bug patterns. A bug pattern is a code idiom that is often an error. 

Bug patterns arise for a variety of reasons: 
- Difficult language features 
- Misunderstood API methods 
- Misunderstood invariants when code is modified during maintenance 
- Garden variety mistakes: typos, use of the wrong boolean operator

<plugin>
  <groupId>com.github.spotbugs</groupId>
  <artifactId>spotbugs-maven-plugin</artifactId>
  <version>3.1.12.2</version>
  <dependencies>
 <!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
 <dependency>
   <groupId>com.github.spotbugs</groupId>
   <artifactId>spotbugs</artifactId>
   <version>4.0.0-beta4</version>
 </dependency>
  </dependencies>
  <configuration>
 <!-- SpotBugs will show what is doing during analysis. -->
 <debug>false</debug>
 <!-- Enables analysis which takes more memory but finds more bugs. If 
  you run out of memory, changes the value of the effort element to 'min'. 
  Min|Default|Max are possible values. -->
 <effort>Min</effort>
 <!-- Reports all bugs (other values are High|Normal|Low|Exp|Ignore) -->
 <threshold>High</threshold>
 <xmlOutput>true</xmlOutput>
 <!-- Optional directory to save SpotBugs xdoc xml report -->
 <xmlOutputDirectory>${project.reporting.outputDirectory}</xmlOutputDirectory>
 <!-- Stops the build if violation found -->
 <failOnError>true</failOnError>
 <!-- Indicates to analyze only given java packages, We are allowing everything here. -->
 <!-- <onlyAnalyze>com.*</onlyAnalyze> -->  
 </configuration>
  <executions>
 <execution>
  <phase>package</phase>
  <goals>
   <!-- spotbugs goal analyses target project by SpotBugs -->
   <!-- <goal>spotbugs</goal> -->
   <!-- check goal runs analysis like spotbugs goal, and make the build failed if it found any bugs. -->
   <goal>check</goal>
  </goals>
 </execution>
  </executions>
</plugin>




Configuring PMD and CPD maven plug-in

Here we are configuring pmd into build lifecycle under 'package' phage. See <phase> element inside <executions>/<execution> element. The <plugins> element is configured under <build> element which means the plugin will be executed during build (life cycle) process.

To run pmd you can use following command: mvn pmd:pmd  


To run cpd you can use following command: mvn pmd:cpd

If you want to run pmd and want the build to fail if violations are found, then you can use following commandmvn pmd:check

If you want to run cpd and want the build to fail if violations are found, then you can use following command: mvn pmd:cpd-check

For more details on pmd configuration options you can look here:

https://maven.apache.org/plugins/maven-pmd-plugin/pmd-mojo.html

<!-- PMD Integration, you can also run it directly using mvn pmd:pmd or pmd:check -->
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-jxr-plugin</artifactId>
 <version>3.0.0</version>
 <executions>
  <execution>
   <phase>package</phase>
   <goals>
    <goal>jxr</goal>
   </goals>
  </execution>
 </executions>
</plugin>

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-pmd-plugin</artifactId>
 <version>3.12.0</version>
 <configuration>
  <!-- Run PMD on the tests. Default: false -->
  <includeTests>false</includeTests>

  <!-- Link the violation line numbers to the source xref. Links will 
    be created automatically if the jxr plugin is being used. Default: true -->
  <linkXRef>true</linkXRef>

  <!--Set the output format type, in addition to the HTML report. Must 
   be one of: "none", "csv", "xml", "txt" or the full class name of the PMD 
   renderer to use. See the net.sourceforge.pmd.renderers package javadoc for 
   available renderers. XML is required if the pmd:check goal is being used. 
   Default: xml -->
  <format>xml</format>

  <!-- Skip the PMD checks. Most useful on the command line via "-Dpmd.skip=true" -->
  <skip>false</skip>

  <!-- Print details of check failures to build output. -->
  <verbose>true</verbose>

  <!-- A list of files to include from checking. Can contain Ant-style 
    wildcards and double wildcards. Defaults to **\/*.java. -->
  <includes>
   <include>com/**/*.java</include>
  </includes>

  <!-- Fail build if there are high priority warnings during pmd:check. 
    Default value is 5 -->
  <failurePriority>1</failurePriority>

  <!-- A list of files to exclude from checking. Can contain Ant-style 
    wildcards and double wildcards. We are not excluding anything here. -->
  <!-- <excludes> 
    <exclude></exclude>
    </excludes> 
      -->

  <!-- The output directory for the final HTML report. -->
  <outputDirectory>${project.reporting.outputDirectory}</outputDirectory>

  <!-- The output directory for the intermediate XML report. -->
  <targetDirectory>${project.build.directory}</targetDirectory>

  <rulesets>
   <!-- Multiple rule set xmls can be included here. -->
   <ruleset>${basedir}/pmd_ruleset.xml</ruleset>
  </rulesets>
 </configuration>
 <executions>
  <execution>
   <phase>package</phase>
   <goals>
    <!-- Creates a PMD report. -->
    <!--<goal>pmd</goal> -->
    <!-- Fail the build if there were any PMD violations in the source code. -->
    <goal>check</goal>
    <!-- Creates a report for PMD's copy paste detector tool -->
    <goal>cpd</goal>
    <!-- Fail the build if there were any CPD violations in the source code. Uncomment if needed -->
    <!-- <goal>cpd-check</goal> -->
   </goals>
  </execution>
 </executions>
</plugin>



PMD Ruleset configuration as per version 6.13.0 (pmd_ruleset.xml):


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ruleset xmlns="http://pmd.sf.net/ruleset/1.0.0" name=""
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
 xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">
 <description>
  <![CDATA[
      This ruleset is as per version 6.13.0
      PMD Plugin preferences rule set
   Priority means: 1 – error, high priority, 2 – error,
   normal priority, 3 – warning, high priority, 4 – warning, normal priority and 5 – information.
  ]]>
 </description>
 <rule ref="category/java/codestyle.xml/PrematureDeclaration">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/ShortVariable">
  <priority>1</priority>
  <properties>
           <property name="minimum" value="3" />
  </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/LongVariable">
  <priority>4</priority>
  <properties>
      <property name="minimum" value="45" />
  </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/ShortMethodName">
  <priority>1</priority>
  <properties>
     <property name="minimum" value="3" />
  </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/FieldNamingConventions">
  <priority>1</priority>
  <properties>
         <property name="publicConstantPattern" value="[A-Z][A-Z_0-9]*" />
         <property name="constantPattern" value="[A-Z][A-Z_0-9]*" />
         <property name="enumConstantPattern" value="[A-Z][A-Z_0-9]*" />
         <property name="finalFieldPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="staticFieldPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="defaultFieldPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="exclusions" value="serialVersionUID|serialPersistentFields" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/LocalVariableNamingConventions">
  <priority>1</priority>
  <properties>
          <property name="localVarPattern" value="[a-z][a-zA-Z0-9]*" />
          <property name="finalVarPattern" value="[a-z][a-zA-Z0-9]*" />
          <property name="catchParameterPattern" value="[a-z][a-zA-Z0-9]*" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/FormalParameterNamingConventions">
  <priority>1</priority>
  <properties>
         <property name="methodParameterPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="finalMethodParameterPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="lambdaParameterPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="explicitLambdaParameterPattern" value="[a-z][a-zA-Z0-9]*" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/MethodNamingConventions">
  <priority>1</priority>
  <properties>
         <property name="methodPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="staticPattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="nativePattern" value="[a-z][a-zA-Z0-9]*" />
         <property name="junit3TestPattern" value="test[A-Z0-9][a-zA-Z0-9]*" />
         <property name="junit4TestPattern" value="[a-z][a-zA-Z0-9]*" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/ClassNamingConventions">
  <priority>1</priority>
  <properties>
         <property name="classPattern" value="[A-Z][a-zA-Z0-9]*" />
         <property name="abstractClassPattern" value="[A-Z][a-zA-Z0-9]*" />
         <property name="interfacePattern" value="[A-Z][a-zA-Z0-9]*" />
         <property name="enumPattern" value="[A-Z][a-zA-Z0-9]*" />
         <property name="annotationPattern" value="[A-Z][a-zA-Z0-9]*" />
         <property name="utilityClassPattern" value="(^Assocs$)|(^Prop$)|([A-Z][a-zA-Z0-9]+(Utils?|Utility?|Helper?|Constants?|Model?|Aspect?|Type?|Object?|Override?|Mandatory?))" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/ShortClassName">
  <priority>1</priority>
     <properties>
         <property name="minimum" value="4" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/LinguisticNaming">
  <priority>1</priority>
     <properties>
         <property name="ignoredAnnotations" value="java.lang.Override" />
         <property name="checkBooleanMethod" value="true" />
         <property name="checkGetters" value="true" />
         <property name="checkSetters" value="true" />
         <property name="checkPrefixedTransformMethods" value="true" />
         <property name="checkTransformMethods" value="false" />
         <property name="booleanMethodPrefixes" value="is|has|can|have|will|should" />
         <property name="transformMethodNames" value="to|as" />
         <property name="checkFields" value="true" />
         <property name="checkVariables" value="true" />
         <property name="booleanFieldPrefixes" value="is|has|can|have|will|should" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/GenericsNaming">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/IdenticalCatchBranches">
  <priority>1</priority>
 </rule> 
 <rule ref="category/java/codestyle.xml/CommentDefaultAccessModifier">
  <priority>1</priority>
  <![CDATA[
     final String stringValueBad = "some string value"; 
   /* default */ final String stringValueGood = "some string"; <-- should be this way
  ]]>
 </rule>
 <rule ref="category/java/codestyle.xml/AvoidDollarSigns">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/NoPackage">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/PackageCase">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/BooleanGetMethodName">
  <priority>1</priority>
  <properties>
           <property name="checkParameterizedMethods" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/UseUtilityClass">
  <priority>1</priority>
  <!-- Ignore check for spring boot application -->
  <properties>
       <property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration/preceding-sibling::Annotation/MarkerAnnotation/Name[@Image='SpringBootApplication']" />
  </properties>
 </rule>
 <rule ref="category/java/design.xml/SimplifyBooleanReturns">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/SimplifyBooleanExpressions">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/SimplifiedTernary">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/SwitchStmtsShouldHaveDefault">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/design.xml/AvoidDeeplyNestedIfStmts">
  <priority>3</priority>
  <properties>
         <property name="problemDepth" value="6" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/AvoidReassigningParameters">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/design.xml/SwitchDensity">
  <priority>3</priority>
  <properties>
           <property name="minimum" value="10.0"/>
         </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/AccessorClassGeneration">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/AccessorMethodGeneration" >
  <priority>3</priority>
 </rule>
 <rule ref="category/java/design.xml/FinalFieldCouldBeStatic">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/DefaultLabelNotLastInSwitchStmt">
  <priority>4</priority>
 </rule>
 <!-- Configure this rule when using PMD 6.16.0 -->
 <!-- <rule ref="category/java/bestpractices.xml/DoubleBraceInitialization">
  <priority>3</priority>
 </rule> -->
 <rule ref="category/java/bestpractices.xml/ForLoopCanBeForeach">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/ForLoopVariableCount">
  <priority>3</priority>
  <properties>
           <property name="maximumVariables" value="1" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/GuardLogStatement">
  <priority>3</priority>
     <properties>
      <!-- Allow info and isInfoEnabled to be ignored and rest of them will be checked -->
         <property name="logLevels" value="trace,debug,warn,error,log,finest,finer,fine,warning,severe" />
         <property name="guardsMethods" value="isTraceEnabled,isDebugEnabled,isWarnEnabled,isErrorEnabled,isLoggable" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/ImmutableField">
  <priority>1</priority>
  <properties>
         <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/LawOfDemeter">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/AvoidProtectedFieldInFinalClass">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/AvoidProtectedMethodInFinalClassNotExtending">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/AbstractClassWithoutAbstractMethod">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/SimplifyConditional">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/PositionLiteralsFirstInComparisons">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/PositionLiteralsFirstInCaseInsensitiveComparisons">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/UnnecessaryLocalBeforeReturn">
  <priority>1</priority>
  <properties>
         <property name="statementOrderMatters" value="true" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/ConstantsInInterface">
  <priority>1</priority>
  <properties>
          <property name="ignoreIfHasMethods" value="true" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml">
  <exclude name="ConfusingTernary" />
 </rule>
 <rule ref="category/java/codestyle.xml/ControlStatementBraces">
  <priority>1</priority>
     <properties>
         <property name="checkIfElseStmt" value="true" />
         <property name="checkSingleIfStmt" value="true" />
         <property name="checkWhileStmt" value="true" />
         <property name="checkForStmt" value="true" />
         <property name="checkDoWhileStmt" value="true" />
         <property name="checkCaseStmt" value="false" />
         <property name="allowEmptyLoop" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/UseCollectionIsEmpty">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UseTryWithResources">
  <priority>1</priority>
     <properties>
         <property name="closeMethods" value="close,closeQuietly" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/UseVarargs">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/WhileLoopWithLiteralBoolean">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/PreserveStackTrace">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/ClassWithOnlyPrivateConstructorsShouldBeFinal">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/EmptyMethodInAbstractClassShouldBeAbstract">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/SingularField">
  <priority>1</priority>
  <properties>
         <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor|lombok.experimental.Delegate" />
         <property name="checkInnerClasses" value="false" />
         <property name="disallowNotAssignment" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/AbstractClassWithoutAnyMethod">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/FieldDeclarationsShouldBeAtStartOfClass">
  <priority>1</priority>
  <properties>
         <property name="ignoreEnumDeclarations" value="true" />
         <property name="ignoreAnonymousClassDeclarations" value="true" />
         <property name="ignoreInterfaceDeclarations" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/SignatureDeclareThrowsException">
  <priority>3</priority>
  <properties>
         <property name="IgnoreJUnitCompletely" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/ExceptionAsFlowControl">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/design.xml/AvoidThrowingRawExceptionTypes">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/AvoidUncheckedExceptionsInSignatures">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/design.xml/AvoidThrowingNullPointerException">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/AvoidRethrowingException">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/DoNotExtendJavaLangError">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/AvoidThrowingNewInstanceOfSameException">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/AvoidCatchingGenericException">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UnusedPrivateField">
  <priority>1</priority>
     <properties>
         <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor|java.lang.Deprecated|javafx.fxml.FXML|lombok.experimental.Delegate" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/UnusedLocalVariable">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UnusedPrivateMethod">
  <priority>1</priority>
     <properties>
         <property name="ignoredAnnotations" value="java.lang.Deprecated" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/UnusedFormalParameter">
  <priority>1</priority>
  <properties>
          <property name="checkAll" value="true" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/SystemPrintln">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/AvoidPrintStackTrace">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/AvoidReassigningLoopVariables">
  <priority>1</priority>
     <properties>
         <property name="foreachReassign" value="deny" />
         <property name="forReassign" value="deny" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/AvoidStringBufferField">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/ReplaceVectorWithList">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/ReplaceHashtableWithMap">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/ReplaceEnumerationWithIterator">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnit4TestShouldUseBeforeAnnotation">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnit4TestShouldUseAfterAnnotation">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnit4TestShouldUseTestAnnotation">
  <priority>3</priority>
  <properties>
          <property name="testClassPattern" value="Test" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnit4SuitesShouldUseSuiteAnnotation">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnitUseExpected">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/MDBAndSessionBeanNamingConvention">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/RemoteSessionInterfaceNamingConvention">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/LocalInterfaceSessionNamingConvention">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/LocalHomeNamingConvention">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/RemoteInterfaceNamingConvention">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/MethodArgumentCouldBeFinal">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/LocalVariableCouldBeFinal">
  <priority>1</priority>
  <properties>
         <property name="ignoreForEachDecl" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/UnnecessaryReturn">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/UnnecessaryModifier">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/UseDiamondOperator">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/design.xml/UselessOverridingMethod">
  <priority>1</priority>
  <properties>
         <property name="ignoreAnnotations" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/UseObjectForClearerAPI">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/ForLoopShouldBeWhileLoop">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/CollapsibleIfStatements">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/AvoidUsingHardCodedIP">
  <priority>3</priority>
  <properties>
           <property name="checkAddressTypes" value="IPv4 mapped IPv6|IPv6|IPv4" />
       </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/CheckResultSet">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/ExtendsObject">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/MethodReturnsInternalArray">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/MissingOverride">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/ArrayIsStoredDirectly">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/OneDeclarationPerLine">
  <priority>1</priority>
     <properties>
         <property name="strictMode" value="false" />
     </properties>
 </rule>
 <!-- Configure this rule when using PMD 6.18.0 -->
 <!-- <rule ref="category/java/bestpractices.xml/AvoidMessageDigestField">
  <priority>3</priority>
 </rule> -->
 <rule ref="category/java/design.xml/CouplingBetweenObjects">
  <priority>3</priority>
  <properties>
         <property name="threshold" value="20" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/ExcessiveImports">
  <priority>3</priority>
  <properties>
         <property name="minimum" value="30.0" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/LooseCoupling">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/DuplicateImports">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/DontImportJavaLang">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UnusedImports">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/UnnecessaryFullyQualifiedName">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/TooManyStaticImports">
  <priority>3</priority>
  <properties>
         <property name="maximumStaticImports" value="10" />
     </properties>
 </rule>
 <rule ref="category/java/codestyle.xml/UnnecessaryAnnotationValueElement">
  <![CDATA[
      @TestClassAnnotation(value = "TEST")
   public class Foo {
       @TestMemberAnnotation(value = "TEST")
       private String y;
   
       @TestMethodAnnotation(value = "TEST")
       public void bar() {
           int x = 42;
           return;
       }
   }
   
   // should be
   @TestClassAnnotation("TEST")
   public class Foo {
       @TestMemberAnnotation("TEST")
       private String y;
   
       @TestMethodAnnotation("TEST")
       public void bar() {
           int x = 42;
           return;
       }
   }
  ]]>  
  <priority>1</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnitAssertionsShouldIncludeMessage">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnitTestContainsTooManyAsserts">
  <priority>3</priority>
     <properties>
         <property name="maximumAsserts" value="3" />
     </properties>
 </rule>
 <rule ref="category/java/bestpractices.xml/JUnitTestsShouldIncludeAssert">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UseAssertEqualsInsteadOfAssertTrue">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UseAssertSameInsteadOfAssertTrue">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UseAssertTrueInsteadOfAssertEquals">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/bestpractices.xml/UseAssertNullInsteadOfAssertTrue">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/design.xml/SimplifyBooleanAssertion">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/OnlyOneReturn">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/CallSuperInConstructor">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/UselessParentheses">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/DefaultPackage">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/UseUnderscoresInNumericLiterals">
  <priority>4</priority>
     <properties>
         <property name="acceptableDecimalLength" value="4" />
     </properties>
 </rule>
 <!-- Configure this rule when using PMD 6.15.0 -->
 <!-- <rule ref="category/java/codestyle.xml/UseShortArrayInitializer">
  <priority>3</priority>
 </rule> -->
 <rule ref="category/java/codestyle.xml/UselessQualifiedThis">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/codestyle.xml/AvoidUsingNativeCode">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/codestyle.xml">
  <exclude name="UnnecessaryConstructor" />
  <exclude name="AtLeastOneConstructor"/>
 </rule>
 <rule ref="category/java/design.xml/NPathComplexity">
  <priority>3</priority>
  <properties>
         <property name="reportLevel" value="200" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/ExcessiveClassLength">
  <priority>3</priority>
  <properties>
         <property name="minimum" value="2000.0" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/ExcessiveMethodLength">
  <priority>3</priority>
  <properties>
         <property name="minimum" value="150.0" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/ExcessiveParameterList">
  <priority>3</priority>
     <properties>
         <property name="minimum" value="10.0" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/CyclomaticComplexity">
  <priority>4</priority>
  <properties>
         <property name="classReportLevel" value="80" />
         <property name="methodReportLevel" value="10" />
         <property name="cycloOptions" value="" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/DataClass">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/design.xml/ExcessivePublicCount">
  <priority>3</priority>
  <properties>
         <property name="minimum" value="45.0" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/GodClass">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/design.xml/LogicInversion">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/design.xml/LoosePackageCoupling">
  <priority>4</priority>
  <!-- Configure allowed classes and packages here -->
     <!-- <properties>
         <property name="packages" value="" />
         <property name="classes" value="" />
     </properties> -->
 </rule>
 <rule ref="category/java/design.xml/TooManyFields">
  <priority>3</priority>
  <properties>
          <property name="maxfields" value="15" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/NcssCount">
  <priority>3</priority>
     <properties>
         <property name="methodReportLevel" value="60" />
         <property name="classReportLevel" value="1500" />
         <property name="ncssOptions" value="" />
     </properties>
 </rule>
 <rule ref="category/java/design.xml/TooManyMethods">
  <priority>3</priority>
  <properties>
          <property name="maxmethods" value="10" />
    </properties>
 </rule>
 <rule ref="category/java/documentation.xml/CommentContent">
  <priority>1</priority>
     <properties>
         <property name="caseSensitive" value="false" />
         <property name="disallowedTerms" value="idiot|jerk" />
     </properties>
 </rule>
 <rule ref="category/java/documentation.xml/CommentRequired">
  <priority>1</priority>
     <properties>
         <property name="methodWithOverrideCommentRequirement" value="Ignored" />
         <property name="accessorCommentRequirement" value="Ignored" />
         <property name="headerCommentRequirement" value="Required" />
         <property name="fieldCommentRequirement" value="Ignored" />
         <property name="publicMethodCommentRequirement" value="Required" />
         <property name="protectedMethodCommentRequirement" value="Required" />
         <property name="enumCommentRequirement" value="Required" />
         <property name="serialVersionUIDCommentRequired" value="Ignored" />
     </properties>
 </rule>
 <rule ref="category/java/documentation.xml/CommentSize">
  <priority>4</priority>
     <properties>
         <property name="maxLines" value="25" />
         <property name="maxLineLength" value="150" />
     </properties>
 </rule>
 <rule ref="category/java/documentation.xml/UncommentedEmptyConstructor">
  <priority>1</priority>
  <properties>
         <property name="ignoreExplicitConstructorInvocation" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/documentation.xml/UncommentedEmptyMethodBody">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/security.xml/HardCodedCryptoKey">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/security.xml/InsecureCryptoIv">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/AvoidSynchronizedAtMethodLevel">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/AvoidThreadGroup">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/AvoidUsingVolatile">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/DoNotUseThreads">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/DontCallThreadRun">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/DoubleCheckedLocking">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/NonThreadSafeSingleton">
  <priority>1</priority>
  <properties>
         <property name="checkNonStaticMethods" value="true" />
         <property name="checkNonStaticFields" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/multithreading.xml/UnsynchronizedStaticFormatter">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/multithreading.xml/UseConcurrentHashMap">
  <priority>3</priority>
 </rule>
  <rule ref="category/java/multithreading.xml/UseNotifyAllInsteadOfNotify">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AssignmentInOperand">
  <priority>4</priority>
  <properties>
         <property name="allowIf" value="false" />
         <property name="allowFor" value="false" />
         <property name="allowWhile" value="false" />
         <property name="allowIncrementDecrement" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/errorprone.xml/AssignmentToNonFinalStatic">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidAccessibilityAlteration">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidAssertAsIdentifier">
  <priority>1</priority>
 </rule>
    <rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop">
  <priority>1</priority>
  <properties>
          <property name="checkBreakLoopTypes" value="for|do|while" />
          <property name="checkContinueLoopTypes" value="for|do|while" />
          <property name="checkReturnLoopTypes" value="for|do|while" />
       </properties>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidCallingFinalize">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidCatchingNPE">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidCatchingThrowable">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidDecimalLiteralsInBigDecimalConstructor">
     <![CDATA[
      One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, 
      but it is actually equal to .1000000000000000055511151231257827021181583404541015625. 
      This is because 0.1 cannot be represented exactly as a double (or as a binary fraction of any finite length). 
      Thus, the long value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
      The (String) constructor, on the other hand, is perfectly predictable: ‘new BigDecimal("0.1")’ is exactly equal to 0.1,
      as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidDuplicateLiterals">
  <priority>1</priority>
  <properties>
   <property name="separator" value="," />
         <property name="maxDuplicateLiterals" value="4" />
         <property name="minimumLength" value="3" />
         <property name="skipAnnotations" value="true" />
         <property name="exceptionList" value="" />
  </properties>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidEnumAsIdentifier">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/MethodWithSameNameAsEnclosingClass">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/SuspiciousHashcodeMethodName">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidFieldNameMatchingTypeName">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidFieldNameMatchingMethodName">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidInstanceofChecksInCatchClause">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidLiteralsInIfCondition">
  <priority>2</priority>
     <properties>
         <property name="ignoreMagicNumbers" value="-1,0" />
     </properties>
 </rule>
 <rule ref="category/java/errorprone.xml">
    <exclude name="DataflowAnomalyAnalysis" />
 </rule>
 <rule ref="category/java/errorprone.xml/MisplacedNullCheck">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidLosingExceptionInformation">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidMultipleUnaryOperators">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/AvoidUsingOctalValues">
  <priority>3</priority>
  <properties>
         <property name="strict" value="false" />
     </properties>
 </rule>
 <rule ref="category/java/errorprone.xml/ClassCastExceptionWithToArray">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/BrokenNullCheck">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/BadComparison">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/BeanMembersShouldSerialize">
  <priority>3</priority>
  <properties>
         <property name="ignoredAnnotations" value="lombok.Data|lombok.Getter|lombok.Value" />
         <property name="prefix" value="" />
     </properties>
 </rule>
 <rule ref="category/java/errorprone.xml/CallSuperFirst">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/CallSuperLast">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/CloneMethodMustBePublic">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/CloneMethodMustImplementCloneable">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/CloneMethodReturnTypeMustMatchClassName">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/ProperCloneImplementation">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/CloneThrowsCloneNotSupportedException">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/CloseResource">
  <priority>1</priority>
  <properties>
         <property name="closeTargets" value="" />
         <property name="types" value="java.lang.AutoCloseable,java.sql.Connection,java.sql.Statement,java.sql.ResultSet" />
         <property name="closeAsDefaultTarget" value="true" />
         <!-- Configure allowed types when using PMD 6.16.0 -->
         <!-- <property name="allowedResourceTypes" value="java.io.ByteArrayOutputStream|java.io.ByteArrayInputStream|java.io.StringWriter|java.io.CharArrayWriter|java.util.stream.Stream" /> -->
     </properties>
 </rule>
 <rule ref="category/java/errorprone.xml/CompareObjectsWithEquals">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/ConstructorCallsOverridableMethod">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DetachedTestCase">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DoNotCallGarbageCollectionExplicitly">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DoNotCallSystemExit">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DoNotExtendJavaLangThrowable">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DoNotHardCodeSDCard">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DoNotThrowExceptionInFinally">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DontImportSun">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/DontUseFloatTypeForLoopIndices">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyCatchBlock">
  <priority>1</priority>
  <properties>
         <property name="allowCommentedBlocks" value="false" />
         <property name="allowExceptionNameRegex" value="^(ignored|expected)$" />
     </properties>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyFinalizer">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyFinallyBlock">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyIfStmt">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyWhileStmt">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyTryBlock">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptySwitchStatements">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptySynchronizedBlock">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyInitializer">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyStatementNotInLoop">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyInitializer">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EmptyStatementBlock">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/EqualsNull">
  <priority>1</priority>
 </rule>
    <rule ref="category/java/errorprone.xml/FinalizeDoesNotCallSuperFinalize">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/FinalizeOnlyCallsSuperFinalize">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/FinalizeOverloaded">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/FinalizeShouldBeProtected">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/IdempotentOperations">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/ImportFromSamePackage">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/InstantiationToGetClass">
  <priority>1</priority>
 </rule>
 <!-- Configure this rule when using PMD 6.19.0 -->
 <!-- <rule ref="category/java/errorprone.xml/InvalidLogMessageFormat">
  <priority>1</priority>
 </rule> -->
 <rule ref="category/java/errorprone.xml/JumbledIncrementer">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/JUnitSpelling">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/JUnitStaticSuite">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/ProperLogger">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/MissingBreakInSwitch">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/MissingSerialVersionUID">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/MissingStaticMethodInNonInstantiatableClass">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/MoreThanOneLogger">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/NonCaseLabelInSwitchStatement">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/NonStaticInitializer">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/NullAssignment">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/OverrideBothEqualsAndHashcode">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/ReturnEmptyArrayRatherThanNull">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/ReturnFromFinallyBlock">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/SimpleDateFormatNeedsLocale">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/SingleMethodSingleton">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/SingletonClassReturningNewInstance">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/StaticEJBFieldShouldBeFinal">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/StringBufferInstantiationWithChar">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/SuspiciousEqualsMethodName">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/SuspiciousOctalEscape">
  <priority>4</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/TestClassWithoutTestCases">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UnconditionalIfStatement">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UnnecessaryBooleanAssertion">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UnnecessaryCaseChange">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UnnecessaryConversionTemporary">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UnusedNullCheckInEquals">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UseCorrectExceptionLogging">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UseEqualsToCompareStrings">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UselessOperationOnImmutable">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UseLocaleWithCaseConversions">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/UseProperClassLoader">
  <![CDATA[
    In J2EE, the getClassLoader() method might not work as expected. 
    Use Thread.currentThread().getContextClassLoader() instead.
  ]]>
  <priority>3</priority>
 </rule>
 <rule ref="category/java/errorprone.xml/CheckSkipResult">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/performance.xml/AddEmptyString">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/AppendCharacterWithChar">
  <priority>3</priority>
 </rule>
 <rule ref="category/java/performance.xml/AvoidArrayLoops">
  <priority>2</priority>
 </rule>
 <rule ref="category/java/performance.xml/AvoidFileStream">
  <![CDATA[
    The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage collection pauses. 
    See JDK-8080225 for details. The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream, 
    again causing garbage collection issues while finalizer methods are called.
   -Use Files.newInputStream(Paths.get(fileName)) instead of new FileInputStream(fileName).
   -Use Files.newOutputStream(Paths.get(fileName)) instead of new FileOutputStream(fileName).
   -Use Files.newBufferedReader(Paths.get(fileName)) instead of new FileReader(fileName).
   -Use Files.newBufferedWriter(Paths.get(fileName)) instead of new FileWriter(fileName).
     Please note, that the java.nio API does not throw a FileNotFoundException anymore, 
     instead it throws a NoSuchFileException. If your code dealt explicitly with a FileNotFoundException, 
     then this needs to be adjusted. Both exceptions are subclasses of IOException, so catching that one covers both.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/AvoidInstantiatingObjectsInLoops">
        <![CDATA[
      for (int i = 0; i < 10; i++) {
             Foo f = new Foo(); // Avoid this whenever you can it's really expensive
         }
  ]]>
  <priority>3</priority>
 </rule>
 <rule ref="category/java/performance.xml/AvoidUsingShortType">
  <![CDATA[
   Java uses the ‘short’ type to reduce memory usage, not to optimize calculation. 
   In fact, the JVM does not have any arithmetic capabilities for the short type: the JVM must convert the short into an int,
   do the proper calculation and convert the int back to a short. 
   Thus any storage gains found through use of the ‘short’ type may be offset by adverse impacts on performance.
   ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/BigIntegerInstantiation">
  <![CDATA[
   Don’t create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) and for Java 1.5 onwards,
   BigInteger.TEN and BigDecimal (BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN)
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/BooleanInstantiation">
  <![CDATA[
   Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead.
   Note that new Boolean() is deprecated since JDK 9 for that reason.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/IntegerInstantiation">
  <![CDATA[
   Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(). 
   It makes use of an internal cache that recycles earlier instances making it more memory efficient. 
   Note that new Integer() is deprecated since JDK 9 for that reason.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/ByteInstantiation">
  <![CDATA[
   Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf(). 
   It makes use of an internal cache that recycles earlier instances making it more memory efficient. 
   Note that new Byte() is deprecated since JDK 9 for that reason.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/ShortInstantiation">
  <![CDATA[
      Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). 
      It makes use of an internal cache that recycles earlier instances making it more memory efficient. 
      Note that new Short() is deprecated since JDK 9 for that reason.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/LongInstantiation">
  <![CDATA[
      Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). 
      It makes use of an internal cache that recycles earlier instances making it more memory efficient. 
      Note that new Long() is deprecated since JDK 9 for that reason.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/SimplifyStartsWith">
  <![CDATA[
      boolean checkIt(String x) {
          return x.startsWith("a");   // suboptimal
      }
  
      boolean fasterCheckIt(String x) {
          return x.charAt(0) == 'a';  // faster approach
      }
  ]]>
  <priority>3</priority>
 </rule>
 <rule ref="category/java/performance.xml/UseStringBufferForStringAppends">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/UseArraysAsList">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/UnnecessaryWrapperObjectCreation">
  <![CDATA[
   public int convert(String s) {
       int i, i2;
   
       i = Integer.valueOf(s).intValue();  // this wastes an object
       i = Integer.parseInt(s);            // this is better
   
       i2 = Integer.valueOf(i).intValue(); // this wastes an object
       i2 = i;                             // this is better
   
       String s3 = Integer.valueOf(i2).toString(); // this wastes an object
       s3 = Integer.toString(i2);                  // this is better
   
       return i2;
   }
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/RedundantFieldInitializer">
  <![CDATA[
    public class C {
   // examples of redundant initializers
      boolean b   = false;    
      byte by     = 0;
      short s     = 0;
      char c      = 0;
      int i       = 0;
      long l      = 0;
      
      // examples of correct initializers
      boolean b1;    
      byte by1;
      short s1;
      char c1;
      int i1;
      long l1;
     }
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/OptimizableToArrayCall">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/TooFewBranchesForASwitchStatement">
  <priority>1</priority>
  <properties>
         <property name="minimumNumberCaseForASwitch" value="3" />
     </properties>
 </rule>
 <rule ref="category/java/performance.xml/StringInstantiation">
  <![CDATA[
   Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared.
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/StringToString">
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/InefficientStringBuffering">
  <![CDATA[
   Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers 
   will need to be be created and destroyed by the JVM.
   
   // Avoid this, two buffers are actually being created here
   StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir"));
   
   // do this instead
   StringBuffer sb = new StringBuffer("tmp = ");
   sb.append(System.getProperty("java.io.tmpdir"));
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/UseStringBufferLength">
  <![CDATA[
   Use StringBuffer.length() to determine StringBuffer length rather than using 
   StringBuffer.toString().equals("") or StringBuffer.toString().length() ==
   
   StringBuffer sb = new StringBuffer();
   if (sb.toString().equals("")) {}        // inefficient
   if (sb.length() == 0) {}                // preferred
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/ConsecutiveAppendsShouldReuse">
  <![CDATA[
   Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target object.
   This can improve the performance by producing a smaller bytecode, reducing overhead and improving inlining
   
   String foo = " ";
   StringBuffer buf = new StringBuffer();
   buf.append("Hello"); // poor
   buf.append(foo);
   buf.append("World");
   
   StringBuffer buf = new StringBuffer();
   buf.append("Hello").append(foo).append("World"); // good
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/ConsecutiveLiteralAppends">
  <![CDATA[
   Consecutively calling StringBuffer/StringBuilder.append(…) with literals should be avoided. 
   Since the literals are constants, they can already be combined into a single String literal and 
   this String can be appended in a single method call.
   
   StringBuffer buf = new StringBuffer();
   buf.append('h').append('e').append('l').append('l').append('o'); // poor
   buf.append("hello");                                             // good
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/UseIndexOfChar">
  <![CDATA[
   Use String.indexOf(char) when checking for the index of a single character; it executes faster.
   String s = "hello world";
   // avoid this
   if (s.indexOf("d") {}
   // instead do this
   if (s.indexOf('d') {}
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/InefficientEmptyStringCheck">
  <![CDATA[
   String.trim().length() == 0 (or String.trim().isEmpty() for the same reason) is an inefficient way to check 
   if a String is really blank, as it creates a new String object just to check its size.
   onsider creating a static function that loops through a string, checking Character.isWhitespace() 
   on each character and returning false if a non-whitespace character is found. 
   You can refer to Apache’s StringUtils#isBlank (in commons-lang), 
   Spring’s StringUtils#hasText (in the Spring framework) or 
   Google’s CharMatcher#whitespace (in Guava) for existing implementations 
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/InsufficientStringBufferDeclaration">
  <![CDATA[
   Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many times during runtime.
   This rule attempts to determine the total number the characters that are actually passed into StringBuffer.append(), 
   but represents a best guess "worst case" scenario. An empty StringBuffer/StringBuilder constructor initializes the object
   to 16 characters. This default is assumed if the length of the constructor can not be determined.
   
   StringBuffer bad = new StringBuffer();
   bad.append("This is a long string that will exceed the default 16 characters");
   
   StringBuffer good = new StringBuffer(41);
   good.append("This is a long string, which is pre-sized");
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/UselessStringValueOf">
  <![CDATA[
   public String convert(int i) {
       String s;
       s = "a" + String.valueOf(i);    // not required
       s = "a" + i;                    // preferred approach
       return s;
   }
  ]]>
  <priority>1</priority>
 </rule>
 <rule ref="category/java/performance.xml/UseArrayListInsteadOfVector">
  <![CDATA[
   ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.
  ]]>
  <priority>2</priority>
 </rule>
</ruleset>


Configuring Checkstyle maven plug-in

Here we are configuring checkstyle into build lifecycle under 'package' phage. See <phase> element inside <executions>/<execution> element. The <plugins> element is configured under <build> element which means the plugin will be executed during build (life cycle) process.

To run checkstyle you can use following command: mvn checkstyle:checkstyle

If you want to run checkstyle and want the build to fail if violations are found, then you can use following commandmvn checkstyle:check

Refer this page for more details:

<!-- Checkstyle integration -->
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-checkstyle-plugin</artifactId>
 <version>3.1.0</version>
 <executions>
  <execution>
   <id>checkstyle</id>
   <phase>package</phase>
   <goals>
    <goal>check</goal>
   </goals>
   <configuration>
    <!-- Fail build if violations found -->
    <failOnViolation>true</failOnViolation>
    <!-- External configuration file location -->
    <configLocation>${basedir}/checkstyle.xml</configLocation>
    <!-- Includes packages as per the given wild card config. -->
    <includes>com/**/*.java</includes>
    <!-- Excludes packages as per the given wild card config. -->
    <excludes>com/github/pojo/**/*.java,com/github/abhinavmishra14/**/*Test.java</excludes>
   </configuration>
  </execution>
 </executions>
</plugin>


Sample Checkstyle RuleSet as per version 3.1.0 (checkstyle.xml)
For more details on ruleset, visit: https://checkstyle.sourceforge.io/config.html

<!DOCTYPE module PUBLIC
    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">

<module name="Checker">
 <module name="TreeWalker">
  <module name="JavadocMethod" />
  <module name="JavadocType" />
  <module name="JavadocVariable">
   <property name="scope" value="private"/>
   <property name="excludeScope" value="protected"/>
  </module>
  <module name="JavadocStyle">
   <property name="checkFirstSentence" value="false"/>
  </module>
 </module>
 <module name="BeforeExecutionExclusionFileFilter">   <property name="fileNamePattern" value="package\-info\.java$"/> </module>
</module>


Configuring plugins for generating reports for PMD, FindBugs/SpotBugs and JUnit test:

When we use 'mvn site' command, it generate site for the project containing all the information of project such has dependencies used, plugins used, Unit test cases success/failure report, PMD report, FindBugs report etc.

To configure reporting we will put the above configurations under the <reporting> element inside pom.xml.


<reporting>
 <plugins>
  <!-- Latest version of site plugin for handling the project report -->
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-site-plugin</artifactId>
   <version>3.8.2</version>
  </plugin>

  <!-- Reporting plugin -->
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-project-info-reports-plugin</artifactId>
   <configuration>
    <argLine>-Xmx1024m</argLine>
   </configuration>
   <version>2.7</version>
  </plugin>

  <!-- To publish JUnit test results -->
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-report-plugin</artifactId>
   <version>3.0.0-M3</version>
  </plugin>

  <!-- Checkstyle plugin -->
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-checkstyle-plugin</artifactId>
   <version>3.1.0</version>
   <configuration>
    <failOnViolation>true</failOnViolation>
    <configLocation>${basedir}/checkstyle.xml</configLocation>
    <includes>com/**/*.java</includes>
    <!-- <excludes></excludes> -->
   </configuration>
  </plugin>

  <!-- JXR for PMD as supporting plugin -->
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-jxr-plugin</artifactId>
   <version>3.0.0</version>
  </plugin>

  <!-- PMD Plugin -->
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-pmd-plugin</artifactId>
   <version>3.12.0</version>
   <configuration>
    <includes>
     <include>com/**/*.java</include>
    </includes>
    <!-- <excludes>
       <exclude></exclude>
     </excludes> -->
    <outputDirectory>${project.reporting.outputDirectory}</outputDirectory>
    <targetDirectory>${project.build.directory}</targetDirectory>
    <rulesets>
     <ruleset>${basedir}/pmd_ruleset.xml</ruleset>
    </rulesets>
   </configuration>
  </plugin>

  <!-- Findbugs plugin -->
  <plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>findbugs-maven-plugin</artifactId>
   <version>3.0.5</version>
   <configuration>
    <debug>false</debug>
    <effort>Min</effort>
    <threshold>High</threshold>
    <xmlOutput>true</xmlOutput>
    <xmlOutputDirectory>${project.reporting.outputDirectory}</xmlOutputDirectory>
    <failOnError>true</failOnError>
    <!-- Indicates to analyze only given java packages, We are allowing everything here. -->
    <!-- <onlyAnalyze>com.*</onlyAnalyze> -->
   </configuration>
  </plugin>

  <!-- Javadocs plugin -->
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-javadoc-plugin</artifactId>
   <version>3.1.1</version>
  </plugin>

  <!-- Spotbugs plugin -->
  <plugin>
   <groupId>com.github.spotbugs</groupId>
   <artifactId>spotbugs-maven-plugin</artifactId>
   <version>3.1.12.2</version>
  </plugin>
</plugins> </reporting>


Once you will run 'mvn install site', a site folder will be created inside /target/site. You can open the 'index.html' generated by 'site' goal. You will see reports something like this(see screen below):























Friday, November 15, 2019

Alfresco 6.x with SDK4.x and docker command cheatsheet


# Alfresco Content Services 6.x AIO Demo Project using SDK 4.x

This is a demo project. This project provides sample project structure built on SDK 4.x (latest 4.0.0) and also provides samples of content model, action, behaviors, scheduled jobs, webscripts, aikau pages, surf pages, etc.


# Prerequisite

##### Understand the concept:
`https://docs.alfresco.com/6.0/concepts/deploy-concepts.html`

##### Required Tools and deployment:
Before starting with SDK4.x and docker based project, Install docker on your development environment.
Follow instructions given here: `https://docs.docker.com/install/`
You may have to create an account on docker hub.

Go to: `https://hub.docker.com/signup?next=%2F%3Foverlay%3Donboarding` to create an account.

Visit here for more details: `https://docs.alfresco.com/6.0/concepts/deploy-prereqs.html`


# Getting started

Run with `./run.sh build_start` or `./run.bat build_start` and verify that it

 * Runs Alfresco Content Service (ACS)
 * Runs Alfresco Share
 * Runs Alfresco Search Service (ASS)
 * Runs PostgreSQL database
 * Deploys the JAR assembled modules

All the services of the project are now run as docker containers. The run script offers the next tasks:

 * `build_start`. Build the whole project, recreate the ACS and Share docker images, start the dockerised environment composed by ACS, Share, ASS and PostgreSQL and tail the logs of all the containers.
 * `build_start_with_supportTools`. Build the whole project with OOTBee support tools, recreate the ACS and Share docker images, start the dockerised environment composed by ACS, Share, ASS and PostgreSQL and tail the logs of all the containers. This is a custom target, not available with OOTB SDK
 * `build_start_it_supported`. Build the whole project including dependencies required for IT execution, recreate the ACS and Share docker images, start the dockerised environment composed by ACS, Share, ASS and PostgreSQL and tail the logs of all the containers.
 * `build_start_it_supported_with_supportTools`. Build the whole project including dependencies required for IT execution along with OOTBee support tools, recreate the ACS and Share docker images, start the dockerised environment composed by ACS, Share, ASS and PostgreSQL and tail the logs of all the containers. This is a custom target, not available with OOTB SDK
 * `start`. Start the dockerised environment without building the project and tail the logs of all the containers.
 * `stop`. Stop the dockerised environment.
 * `purge`. Stop the dockerised container and delete all the persistent data (docker volumes).
 * `tail`. Tail the logs of all the containers.
 * `reload_share`. Build the Share module, recreate the Share docker image and restart the Share container.
 * `reload_share_with_supportTools`. Build the Share module with OOTBee support tools, recreate the Share docker image and restart the Share container. This is a custom target, not available with OOTB SDK
 * `reload_acs`. Build the ACS module, recreate the ACS docker image and restart the ACS container.
 * `reload_acs_with_supportTools`. Build the ACS module with OOTBee support tools, recreate the ACS docker image and restart the ACS container. This is a custom target, not available with OOTB SDK
 * `build_test`. Build the whole project, recreate the ACS and Share docker images, start the dockerised environment, execute the integration tests from the
 `integration-tests` module and stop the environment.
 * `test`. Execute the integration tests (the environment must be already started).

# How to run SDK's integration tests

Running the integration tests of a project generated from the Alfresco SDK 4.0 archetypes is pretty easy. Let's distinguish different cases of executing the
integration tests.

## Command line

If you want to run the integration tests from the command line you'll have to use the utility scripts provided by all the projects generated from the
archetypes. These are `run.sh` if you're on Unix systems or `run.bat` if you're on Windows systems.

If you want to spin up a new dockerised environment with ACS, run the integration tests and stop that environment, you'll use the `build_test` goal:

```
$ ./run.bat build_test
```

If you want all your previous data in the docker environment to be wiped out before the execution of the integration tests, remember to call the `purge` goal
before the `build_test` goal:

```
$ ./run.bat purge
$ ./run.bat build_test
```

The `build_test` goal will execute the next list of tasks:
* Stop any previous execution of the dockerised environment.
* Compile all the source code.
* Rebuild the custom Docker images of the project.
* Start a new dockerised environment.
* Execute the integration tests.
* Show the logs of the docker containers during the tests execution.
* Stop the dockerised environment.

If your dockerised environment is already started and you simply want to execute the integration tests against that existing ACS instance, then use the `test`
goal:

```
$ ./run.bat test
```

### Configuring a custom ACS endpoint location

If you want to run your integration tests against an ACS instance not exposed in `http://localhost:8080/alfresco` you'll need to modify a maven property
before executing the tests.

The maven property for the test ACS instance endpoint location is `acs.endpoint.path` and you can configure it in the `pom.xml` file in the root folder of your
project:

```
    <properties>
        ...
        <test.acs.endpoint.path>http://192.168.1.11:8080/alfresco</test.acs.endpoint.path>
        ..
    </properties>
```

This parameter is **specially important** if you're running your dockerised environment using [Docker Toolbox](https://docs.docker.com/toolbox/) instead of
[Docker Desktop](https://www.docker.com/products/docker-desktop). If that is the case, then the Docker container exposed ports are not mapped in the hosted
machine as `localhost` but as an assigned IP address (i.e. `192.168.1.11`).

## Eclipse IDE

If your project is available in Eclipse, you can easily run one or more of the integration tests directly from your IDE.

To run the integration tests:

1. In order to properly execute the integration tests the dockerised environment must be already up and running with IT support. So, before executing the tests
you must run the `build_start_it_supported` or the `start` goal of the `run` script.

2. Open the project using the IDE.

3. Select the classes for the integration tests (either one, some, or the whole package).

4. Right click and select `Run As ...`, then click `JUnit Test`.

Once the tests have completed (typically, after a few seconds), the results are presented.

## IntelliJ IDEA IDE

If your project is available in IntelliJ IDEA, you can easily run one or more of the integration tests directly from your IDE.

To run the integration tests:

1. In order to properly execute the integration tests the dockerised environment must be already up and running with IT support. So, before executing the tests
you must run the `build_start_it_supported` or the `start` goal of the `run` script.

2. Open the project using the IDE.

3. Select the classes for the integration tests (either one, some, or the whole package).

4. Right click and select `Run Tests`.

Once the tests have completed (typically, after a few seconds), the results are presented.
When using an IDE, the source code related to the integration tests is the one deployed directly on the platform side.

Debugging in Eclipse IDE

See: Remote debugging using Eclipse

Debugging in IntelliJ IDE

SeeRemote debugging using IntelliJ

# Some common docker commands:

- `docker -v (prints the version of docker)`
- `docker-compose -v (prints the version of docker compose)`
- `docker container ls (Lists are running containers)`
- `docker container stop <CONTAINER_ID> (To stop a container, where container_id is the id you would get when you execute above command)`
- `docker run (Runs a command in a new container)`
- `docker start (Starts one or more stopped containers)`
- `docker stop (Stops one or more running containers)`
- `docker build (Builds an image form a Docker file)`
- `docker pull (Pulls an image or a repository from a registry)`
- `docker push (Pushes an image or a repository to a registry)`
- `docker export (Exports a container’s filesystem as a tar archive)`
- `docker exec (Runs a command in a run-time container)`
- `docker search (Searches the Docker Hub for images)`
- `docker attach (Attaches to a running container)`
- `docker commit (Creates a new image from a container’s changes)`
- `docker restart (Restart one or more containers, e.g. docker restart <CONTAINER_NAME> or docker restart <CONTAINER_ID>)`


# Some common errors you may see while using docker:

#### Sometimes when you quit the docker service or stop it manually and start again, it may not login to docker hub repo properly and you may see this error: unauthorized: incorrect username or password

In my case i got this error: Pulling acs6-aio-demo-project-postgres (postgres:9.6)...
ERROR: Get https://registry-1.docker.io/v2/library/postgres/manifests/9.6: unauthorized: incorrect username or password

#####Remedy for the above error:
Try logout and login from docker using powershell. Refer this issue log for details: https://github.com/docker/hub-feedback/issues/1098

Login with your Docker ID. If you don't have a Docker ID, head over to https://hub.docker.com to create one.

- `docker logout`
- `docker login (Remember to use userId instead of your emailId)`

PS C:\EclipseWorkspace\acs6-aio-demo-project> docker logout
Not logged in to https://index.docker.io/v1/
PS C:\EclipseWorkspace\acs6-aio-demo-project> docker login
Authenticating with existing credentials...
Stored credentials invalid or expired
Username (xyz@gmail.com): xyz
Password:
Login Succeeded


#### Sometimes you may see error as: driver failed programming external connectivity on endpoint

In my case i got this error:

ERROR: for docker_acs6-aio-demo-project-postgres_1  Cannot start service acs6-aio-demo-project-postgres: driver failed programming external connectivity on endpoint docker_acs6-aio-demo-project-postgres_1 (3850d6992b6f9f6abb99b7494f0a605Creating docker_acs6-aio-demo-project-ass_1      ... error

Creating docker_acs6-aio-demo-project-share_1    ... error
0ef77510b6513fc5f2): Error starting userland proxy: mkdir /port/tcp:0.0.0.0:8983:tcp:172.20.0.3:8983: input/output error

ERROR: for docker_acs6-aio-demo-project-share_1  Cannot start service acs6-aio-demo-project-share: driver failed programming external connectivity on endpoint docker_acs6-aio-demo-project-share_1 (1f4a7e30e906106ff606b4bc9432bb9184c61b411dbdbe84f4c0b55b940fa1d4): Error starting userland proxy: mkdir /port/tcp:0.0.0.0:9898:tcp:172.20.0.4:8888: input/output error

ERROR: for acs6-aio-demo-project-postgres  Cannot start service acs6-aio-demo-project-postgres: driver failed programming external connectivity on endpoint docker_acs6-aio-demo-project-postgres_1 (3850d6992b6f9f6abb99b7494f0a6050bcf147f662adb78db6d25f77ee1cbdd4): Error starting userland proxy: mkdir /port/tcp:0.0.0.0:5432:tcp:172.20.0.2:5432: input/output error

ERROR: for acs6-aio-demo-project-ass  Cannot start service acs6-aio-demo-project-ass: driver failed programming external connectivity on endpoint docker_acs6-aio-demo-project-ass_1 (606d3bede53e3fb8fadf431fdc983db01fba680377fed00ef77510b6513fc5f2): Error starting userland proxy: mkdir /port/tcp:0.0.0.0:8983:tcp:172.20.0.3:8983: input/output error

ERROR: for acs6-aio-demo-project-share  Cannot start service acs6-aio-demo-project-share: driver failed programming external connectivity on endpoint docker_acs6-aio-demo-project-share_1 (1f4a7e30e906106ff606b4bc9432bb9184c61b411dbdbe84f4c0b55b940fa1d4): Error starting userland proxy: mkdir /port/tcp:0.0.0.0:9898:tcp:172.20.0.4:8888: input/output error
ERROR: Encountered errors while bringing up the project.

##### Remedy for the above error:
- ` Restart docker for desktop and try the operation again`

If it doesn't work, try finding if something is running on ports displayed in the error above.

Run following command: netstat -anon | findstr 8983
This will return the list of process which may be using the port number : 8983

You will see following result:
TCP    0.0.0.0:8983           0.0.0.0:0              LISTENING       9500
TCP    [::]:8983              [::]:0                 LISTENING       9500

Here 9500 is the process id, use the below command to kill this process:

taskkill /f /pid 9500

After killing the process, restart the docker for desktop again.

#### Docker images related commands:

- `docker images (For searching an image in the Docker Hub)`

##### Docker provides a single command that will clean up any resources — images, containers, volumes, and networks — that are dangling (not associated with a container):

- `docker system prune`

##### To additionally remove any stopped containers and all unused images (not just dangling images), add the -a flag to the command:

- `docker system prune -a`

##### Remove one or more specific images:

Use the docker images command with the -a flag to locate the ID of the images you want to remove. This will show you every image, including intermediate image layers. When you've located the images you want to delete, you can pass their ID or tag to docker rmi:

List:

- `docker images -a`

Remove:

- `docker rmi Image Image`


##### Remove dangling images:

Docker images consist of multiple layers. Dangling images are layers that have no relationship to any tagged images. They no longer serve a purpose and consume disk space. They can be located by adding the filter flag, -f with a value of dangling=true to the docker images command. When you're sure you want to delete them, you can use the docker images purge command:

Note: If you build an image without tagging it, the image will appear on the list of dangling images because it has no association with a tagged image. You can avoid this situation by providing a tag when you build, and you can retroactively tag an images with the docker tag command.

List:

- `docker images -f dangling=true`

Remove:

- `docker images purge`


##### Removing images according to a pattern
You can find all the images that match a pattern using a combination of docker images and grep. Once you're satisfied, you can delete them by using awk to pass the IDs to docker rmi. Note that these utilities are not supplied by Docker and are not necessarily available on all systems:

List:

- `docker images -a |  grep "pattern"`

Remove:

- `docker images -a | grep "pattern" | awk '{print $3}' | xargs docker rmi`

Remove all images
All the Docker images on a system can be listed by adding -a to the docker images command. Once you're sure you want to delete them all, you can add the -q flag to pass the Image ID to docker rmi:

List:

- `docker images -a`

Remove:

- `docker rmi $(docker images -a -q)`

##### Removing Containers

Remove one or more specific containers
Use the docker ps command with the -a flag to locate the name or ID of the containers you want to remove:

List:

- `docker ps -a`

Remove:

- `docker rm ID_or_Name ID_or_Name`

##### Remove a container upon exit

If you know when you’re creating a container that you won’t want to keep it around once you’re done, you can run docker run --rm to automatically delete it when it exits.

Run and Remove:

- `docker run --rm image_name`

##### Remove all exited containers

You can locate containers using docker ps -a and filter them by their status: created, restarting, running, paused, or exited. To review the list of exited containers, use the -f flag to filter based on status. When you've verified you want to remove those containers, using -q to pass the IDs to the docker rm command.

List:

- `docker ps -a -f status=exited`

Remove:

- `docker rm $(docker ps -a -f status=exited -q)`

##### Remove containers using more than one filter

Docker filters can be combined by repeating the filter flag with an additional value. This results in a list of containers that meet either condition. For example, if you want to delete all containers marked as either Created (a state which can result when you run a container with an invalid command) or Exited, you can use two filters:

List:

- `docker ps -a -f status=exited -f status=created`

Remove:

- `docker rm $(docker ps -a -f status=exited -f status=created -q)`

##### Remove containers according to a pattern

You can find all the containers that match a pattern using a combination of docker ps and grep. When you're satisfied that you have the list you want to delete, you can use awk and xargs to supply the ID to docker rmi. Note that these utilities are not supplied by Docker and not necessarily available on all systems:

List:

- `docker ps -a |  grep "pattern”`

Remove:

- `docker ps -a | grep "pattern" | awk '{print $3}' | xargs docker rmi`

##### Stop and remove all containers
You can review the containers on your system with docker ps. Adding the -a flag will show all containers. When you're sure you want to delete them, you can add the -q flag to supply the IDs to the docker stop and docker rm commands:

List:

- `docker ps -a`

Remove:

- `docker stop $(docker ps -a -q)`
- `docker rm $(docker ps -a -q)`

##### Removing Volumes

Remove one or more specific volumes - Docker 1.9 and later
Use the docker volume ls command to locate the volume name or names you wish to delete. Then you can remove one or more volumes with the docker volume rm command:

List:

- `docker volume ls`

Remove:

- `docker volume rm volume_name volume_name`

##### Remove dangling volumes - Docker 1.9 and later
Since the point of volumes is to exist independent from containers, when a container is removed, a volume is not automatically removed at the same time. When a volume exists and is no longer connected to any containers, it's called a dangling volume. To locate them to confirm you want to remove them, you can use the docker volume ls command with a filter to limit the results to dangling volumes. When you're satisfied with the list, you can remove them all with docker volume prune:

List:

- `docker volume ls -f dangling=true`

Remove:

- `docker volume prune`

##### Remove a container and its volume
If you created an unnamed volume, it can be deleted at the same time as the container with the -v flag. Note that this only works with unnamed volumes. When the container is successfully removed, its ID is displayed. Note that no reference is made to the removal of the volume. If it is unnamed, it is silently removed from the system. If it is named, it silently stays present.

Remove:

- `docker rm -v container_name`

#### To view all docker volume data use this command: 

\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes

#### You can also use this command to inspect the volume: 

docker inspect <container_id>

#### Docker volumes on windows can also be found here: 

'C:\Users\Username\AppData\Local\Docker\wsl', where username is your username that you use to login to your computer. For example: C:\Users\abhinav\AppData\Local\Docker\wsl

##### Get container name or short container id:

- `docker ps`

##### Get full container id:

- `docker inspect -f '{{.Id}}' CONTAINER_ID`

##### Copy file:

- `docker cp localFile FULLCONTAINER_ID:pathOnContainer`

Example:
- `docker cp C:\custom-log4j.properties ac23e51fd0b5c4cc11a12133ceea16d603e7f105d8d39873c75d7cfdd5942e40:/usr/local/tomcat/shared/classes/alfresco/extension`

##### SSH Into a docker image:

- `docker exec -t -i <containerName/Id> /bin/bash`

docker exec Options:
  -d, --detach               Detached mode: run command in the background
      --detach-keys string   Override the key sequence for detaching a container

  -e, --env list             Set environment variables

  -i, --interactive          Keep STDIN open even if not attached
      --privileged           Give extended privileges to the command

  -t, --tty                  Allocate a pseudo-TTY

  -u, --user string          Username or UID (format:
                             <name|uid>[:<group|gid>])

  -w, --workdir string       Working directory inside the container


Example (SSH into alfresco container):

- `docker exec -t -i docker_acs6-aio-demo-project-acs_1 /bin/bash`

Example (SSH into search service container):

- `docker exec -t -i docker_acs6-aio-demo-project-ass_1 /bin/bash`

Example (SSH into share container):

- `docker exec -t -i docker_acs6-aio-demo-project-share_1 /bin/bash`

##### Get list of docker machines:

- `docker-machine ls`

##### Create new docker machines:

- `docker-machine create <aName>`

#### Find MobyLinux docker VM settings (windows 10)

- `VM settings file can be found at: C:\Users\<userID>\AppData\Roaming\Docker`

- `Here userID is the user which you have used to login to windows. e.g.: C:\Users\abhinavmishra\AppData\Roaming\Docker\settings.json`

- `Content of settings.json will be something like this:`

  {
    "settingsVersion":  1,
    "autoStart":  false,
    "checkForUpdates":  false,
    "analyticsEnabled":  false,
    "displayedWelcomeWhale":  true,
    "displayed14393Deprecation":  false,
    "displayRestartDialog":  true,
    "displaySwitchWinLinContainers":  true,
    "latestBannerKey":  "",
    "debug":  false,
    "memoryMiB":  2048,
    "swapMiB":  1024,
    "cpus":  2,
    "diskPath":  null,
    "diskSizeMiB":  64000000000,
    "networkCIDR":  "10.1.85.0/24",
    "proxyHttpMode":  false,
    "overrideProxyHttp":  "",
    "overrideProxyHttps":  "",
    "overrideProxyExclude":  "",
    "useDnsForwarder":  true,
    "dns":  "8.8.8.8",
    "kubernetesEnabled":  false,
    "showKubernetesSystemContainers":  false,
    "kubernetesInitialInstallPerformed":  false,
    "cliConfigCreationDate":  null,
    "linuxDaemonConfigCreationDate":  null,
    "windowsDaemonConfigCreationDate":  null,
    "versionPack":  "default",
    "sharedDrives":  {

                     },
    "executableDate":  "",
    "useWindowsContainers":  false,
    "swarmFederationExplicitlyLoggedOut":  false,
    "activeOrganizationName":  null,
    "exposeDockerAPIOnTCP2375":  false
}

#### Recreate MobyLinux VM provided by docker for desktop (windows 10)

Follow the steps below:

1- `Exit the application and Quit docker desktop (you can do it by clicking quitting from windows system tray)`

2- `Go to start menu > run > services.msc`

3- `Find service 'com.docker.service' (Docker Desktop Service) and stop it`

4- `Launch the windows power shell, "Run as Administrator"`

5- `Set the location as: "C:\Program Files\Docker\Docker\resources". This is the place where all docker related resources are places and the ps scripts`

    e.g. PS C:\WINDOWS\system32> Set-Location "C:\Program Files\Docker\Docker\resources"

Note: Do not use "cd" to navigate to C:\Program Files\Docker\Docker\resources. Follow the exact step as given above.

6- `Run following command: .\MobyLinux.ps1 -Destroy`

    - `If you get an error saying: 'MobyLinux.ps1 cannot be loaded because the execution of scripts is disabled on this system' then try running following command:
 
      `PS C:\Program Files\Docker\Docker\resources> Set-ExecutionPolicy RemoteSigned`
 
    - `See here for more details: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-6`
    - `Try running '.\MobyLinux.ps1 -Destroy' command again`
 
e.g.:
PS C:\Program Files\Docker\Docker\resources> .\MobyLinux.ps1 -Destroy

Script started at 16:56:04.455

Modules loaded at 16:56:05.780

VM MobyLinuxVM is stopped

Destroying Switch DockerNAT...

Removing VM MobyLinuxVM...

Delete VHD C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MobyLinuxVM.vhdx
 
7- `Check that the VHDX file (C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MobyLinuxVM.vhdx) is removed`

8- `Once VHDX file is deleted, then re-create it by running following command: '.\MobyLinux.ps1 -Create'`

e.g.:
PS C:\Program Files\Docker\Docker\resources> .\MobyLinux.ps1 -Create

Script started at 16:58:58.218

Modules loaded at 16:58:58.246

Creating Switch: DockerNAT...

Switch created.

Set IP address on switch

Creating VM MobyLinuxVM...

Setting CPUs to 2 and Memory to 2048 MB

Creating dynamic VHD: C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MobyLinuxVM.vhdx

Attach VHD C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MobyLinuxVM.vhdx

Connect Internal Switch DockerNAT

Attach DVD .\docker-for-win.iso

Disabled Guest Service Interface

Enabled Heartbeat

Disabled Key-Value Pair Exchange

Enabled Shutdown

Enabled Time Synchronization

Disabled VSS

VM created.


9- `New VM will be created again`


#### Change the VM path from 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\' to a different location

Follow the steps below:

1- `Open notepad and copy paste below power shell code into it, name it as: CustomMobyLinux.ps`


$CustomLinxImageStoragePath = "D:\DockerStorage\VMs"

##### Make sure that com.docker.service is Stopped and 'Docker For Windows.exe' and 'dockerd.exe' are not running
try {
    $DockerService = Get-Service com.docker.service -ErrorAction Stop

    if ($DockerService.Status -ne "Stopped") {
        $DockerService | Stop-Service -Force
    }
}
catch {
    Write-Error $_
    $global:FunctionResult = "1"
    return
}

try {
    $DockerForWindowsProcess = Get-Process "Docker For Windows" -ErrorAction SilentlyContinue
    if ($DockerForWindowsProcess) {
        $DockerForWindowsProcess | Stop-Process -Force
    }

    $DockerDProcess = Get-Process "dockerd" -ErrorAction SilentlyContinue
    if ($DockerDProcess) {
        $DockerDProcess | Stop-Process -Force
    }
}
catch {
    Write-Error $_
    $global:FunctionResult = "1"
    return
}

######## Make sure the MobyLinuxVM is Off
$MobyLinuxVMInfo = Get-VM -Name MobyLinuxVM

if ($MobyLinuxVMInfo.State -ne "Off") {
    try {
        Stop-VM -VMName MobyLinuxVM -TurnOff -Confirm:$False -Force -ErrorAction Stop
    }
    catch {
        Write-Error $_
        $global:FunctionResult = "1"
        return
    }
}

$DockerSettings = Get-Content "$env:APPDATA\Docker\settings.json" | ConvertFrom-Json
$DockerSettings.MobyVhdPathOverride = "$CustomLinuxImageStoragePath\MobyLinuxVM.vhdx"
$DockerSettings | ConvertTo-Json | Out-File "$env:APPDATA\Docker\settings.json"

######## Turn On Docker Again
try {
    $DockerService = Get-Service com.docker.service -ErrorAction Stop

    if ($DockerService.Status -eq "Stopped") {
        $DockerService | Start-Service
        Write-Host "Sleeping for 30 seconds to give the com.docker.service service time to become ready..."
        Start-Sleep -Seconds 30
    }

    $MobyLinuxVMInfo = Get-VM -Name MobyLinuxVM
    if ($MobyLinuxVMInfo.State -ne "Running") {
        Write-Host "Manually starting MobyLinuxVM..."
        Start-VM -Name MobyLinuxVM
    }

    & "C:\Program Files\Docker\Docker\Docker For Windows.exe"
}
catch {
    Write-Error $_
    $global:FunctionResult = "1"
    return
}


2- `Save the file in this directory: C:\Program Files\Docker\Docker\resources`

3- `Exit the application and Quit docker desktop (you can do it by clicking quitting from windows system tray)`

4- `Go to start menu > run > services.msc`

5- `Find service 'com.docker.service' (Docker Desktop Service) and stop it`

6- `Launch the windows power shell, "Run as Administrator"`

7- `Set the location as: "C:\Program Files\Docker\Docker\resources". This is the place where all docker related resources are places and the ps scripts`

    e.g. PS C:\WINDOWS\system32> Set-Location "C:\Program Files\Docker\Docker\resources"

Note: Do not use "cd" to navigate to C:\Program Files\Docker\Docker\resources. Follow the exact step as given above.

8- `Run following command: .\CustomMobyLinux.ps`

    - `If you get an error: 'CustomMobyLinux.ps cannot be loaded because the execution of scripts is disabled on this system' then try running following command:
 
      `PS C:\Program Files\Docker\Docker\resources> Set-ExecutionPolicy RemoteSigned`
 
    - `See here for more details: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-6`
    - `Try running '.\CustomMobyLinux.ps' command again`

 
# Some common docker compose commands:

TO Get the version and help related to docker-compose use below commands:

  - `docker-compose help               (Get help on a command)`
  - `docker-compose version            (Show the Docker-Compose version information)`

Before executing the commands, Navigate to the folder where the docker-compose.yml file is located. Once you located the file, execute the command in below given format:
 
   docker-compose -f <PATH>/docker-compose.yml <INSTRUCTION>
 
   For example: docker-compose -f ./docker-compose.yml up
   

  - `docker-compose -f ./docker-compose.yml up                 (Create and start containers)`
  - `docker-compose -f ./docker-compose.yml down               (Stop and remove containers, networks, images, and volumes)`
  - `docker-compose -f ./docker-compose.yml start              (Start services)`
  - `docker-compose -f ./docker-compose.yml stop               (Stop services)`
  - `docker-compose -f ./docker-compose.yml restart            (Restart services)`
  - `docker-compose -f ./docker-compose.yml top                (Display the running processes)`
  - `docker-compose -f ./docker-compose.yml build              (Build or rebuild services)`
  - `docker-compose -f ./docker-compose.yml bundle             (Generate a Docker bundle from the Compose file)`
  - `docker-compose -f ./docker-compose.yml config             (Validate and view the Compose file)`
  - `docker-compose -f ./docker-compose.yml create             (Create services)`
  - `docker-compose -f ./docker-compose.yml events             (Receive real time events from containers)`
  - `docker-compose -f ./docker-compose.yml exec               (Execute a command in a running container)`
  - `docker-compose -f ./docker-compose.yml images             (List images)`
  - `docker-compose -f ./docker-compose.yml kill               (Kill containers)`
  - `docker-compose -f ./docker-compose.yml logs               (View output from containers)`
  - `docker-compose -f ./docker-compose.yml pause              (Pause services)`
  - `docker-compose -f ./docker-compose.yml unpause            (Unpause services)`
  - `docker-compose -f ./docker-compose.yml port               (Print the public port for a port binding)`
  - `docker-compose -f ./docker-compose.yml ps                 (List containers)`
  - `docker-compose -f ./docker-compose.yml pull               (Pull service images)`
  - `docker-compose -f ./docker-compose.yml push               (Push service images)`
  - `docker-compose -f ./docker-compose.yml rm                 (Remove stopped containers)`
  - `docker-compose -f ./docker-compose.yml run                (Run a one-off command)`
  - `docker-compose -f ./docker-compose.yml scale              (Set number of containers for a service)`

  Here -f ./docker-compose.yml is an optional parameter if you are executing the commands where docker-compose.yml file is located. Else you must provide the file with exact path.
  For example: docker-compose -f c:\Alfresco\6.1\docker-compose.yml up

##### You can also specify multiple docker-compose.yml files:

 - `docker-compose -f docker-compose.yml -f docker-compose.admin.yml run backup_db`

   Here backup_db is a service defined in your docker-compose.yml file.

##### You can also execute multiple instructions at same time:

  - `docker-compose down && docker-compose build --no-cache && docker-compose up`
 
   This command will turn down all the services, build and turn them up.
 
  - `docker-compose down acs6-aio-demo-project-acs && docker-compose build acs6-aio-demo-project-acs --no-cache && docker-compose up acs6-aio-demo-project-acs`
 
   This command will turn down acs6-aio-demo-project-acs services, build and turn them up.
 

### Removing/Uninstalling the ACS
When we are finished with the test, PoC, etc. then we can remove the ACS from the computer in an easy way with the following Docker Compose command (this is not necessary if you did docker-compose down):


- `docker-compose rm`

Going to remove docker_acs6-aio-demo-project-share_1, docker_acs6-aio-demo-project-acs_1, docker_acs6-aio-demo-project-postgres_1, docker_acs6-aio-demo-project-ass_1

Are you sure? [yN] y

Removing docker_acs6-aio-demo-project-share_1 ... done

Removing docker_acs6-aio-demo-project-acs_1 ... done

Removing docker_acs6-aio-demo-project-postgres_1    ... done

Removing docker_acs6-aio-demo-project-ass_1    ... done

##### List the running and stopped containers to make sure they are gone:

$ docker container ls -a

CONTAINER ID        IMAGE              COMMAND CREATED           STATUS PORTS        NAMES