Skip to content

Commit

Permalink
🐛 Add annotation inspection support (#659)
Browse files Browse the repository at this point in the history
This PR adds support for inspecting annotations.

:green_circle: Things that can be done now:
- Check for annotations that are annotating specific
`FIELD_DECLARATION`, `METHOD_DECLARATION` or `TYPE`
- Match against `METHOD_DECLARATION`

:red_circle: Things that cannot be done **yet**:
- Match `location: ANNOTATION` and inspect its values.
- Inspect on annotations on `location: CONSTRUCTOR`.

Depends on:
- konveyor/java-analyzer-bundle#104

Fixes:
- #460
- #467

---------

Signed-off-by: Juan Manuel Leflet Estrada <[email protected]>
  • Loading branch information
jmle committed Jul 22, 2024
1 parent 43879b3 commit 4fdf5e5
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 4 deletions.
42 changes: 42 additions & 0 deletions demo-output.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,48 @@
kind: Field
name: repository
package: io.konveyor.demo.ordermanagement.service
java-annotation-inspection-01:
description: |
This rule looks for a given class annotated with a given annotation
category: mandatory
incidents:
- uri: file:///examples/customers-tomcat-legacy/src/main/java/io/konveyor/demo/ordermanagement/config/PersistenceConfig.java
message: Annotation instpection 01
codeSnip: "17 import org.springframework.transaction.annotation.EnableTransactionManagement;\n18 \n19 import io.konveyor.demo.config.ApplicationConfiguration;\n20 \n21 @Configuration\n22 @EnableJpaRepositories(basePackages = {\n23 \"io.konveyor.demo.ordermanagement.repository\"\n24 })\n25 @EnableTransactionManagement\n26 @EnableSpringDataWebSupport\n27 public class PersistenceConfig {\n28 \n29 \n30 \t@Bean\n31 public LocalContainerEntityManagerFactoryBean entityManagerFactory() {\n32 final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();\n33 em.setDataSource(dataSource());\n34 em.setPackagesToScan(\"io.konveyor.demo.ordermanagement.model\");\n35 em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());\n36 em.setJpaProperties(additionalProperties());\n37 "
lineNumber: 27
variables:
file: file:///examples/customers-tomcat-legacy/src/main/java/io/konveyor/demo/ordermanagement/config/PersistenceConfig.java
kind: Class
name: PersistenceConfig
package: io.konveyor.demo.ordermanagement.config
java-annotation-inspection-02:
description: |
This rule looks for a given method annotated with a given annotation
category: mandatory
incidents:
- uri: file:///examples/customers-tomcat-legacy/src/main/java/io/konveyor/demo/ordermanagement/config/PersistenceConfig.java
message: Annotation instpection 02
codeSnip: "46 dataSource.setUrl(config.getProperty(\"jdbc.url\"));\n47 dataSource.setUsername(config.getProperty(\"jdbc.user\"));\n48 dataSource.setPassword(config.getProperty(\"jdbc.password\"));\n49 \n50 return dataSource;\n51 }\n52 \n53 @Bean\n54 public PlatformTransactionManager transactionManager() {\n55 final JpaTransactionManager transactionManager = new JpaTransactionManager();\n56 transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());\n57 return transactionManager;\n58 }\n59 \n60 @Bean\n61 public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {\n62 return new PersistenceExceptionTranslationPostProcessor();\n63 }\n64 \n65 final Properties additionalProperties() {\n66 \tApplicationConfiguration config = new ApplicationConfiguration();"
lineNumber: 56
variables:
file: file:///examples/customers-tomcat-legacy/src/main/java/io/konveyor/demo/ordermanagement/config/PersistenceConfig.java
kind: Method
name: transactionManager
package: io.konveyor.demo.ordermanagement.config
java-annotation-inspection-03:
description: |
This rule looks for a given field annotated with a given annotation
category: mandatory
incidents:
- uri: file:///examples/customers-tomcat-legacy/src/main/java/io/konveyor/demo/ordermanagement/controller/CustomerController.java
message: Annotation instpection 03
codeSnip: "11 import org.springframework.web.bind.annotation.GetMapping;\n12 import org.springframework.web.bind.annotation.PathVariable;\n13 import org.springframework.web.bind.annotation.RequestMapping;\n14 import org.springframework.web.bind.annotation.RestController;\n15 \n16 @RestController\n17 @RequestMapping(\"/customers\")\n18 public class CustomerController {\n19 \t\n20 \t@Autowired\n21 \tprivate CustomerService customerService;\n22 \t\n23 \tprivate static Logger logger = Logger.getLogger( CustomerController.class.getName() );\n24 \t\n25 \t@GetMapping(value = \"/{id}\", produces = MediaType.APPLICATION_JSON_VALUE)\n26 public Customer getById(@PathVariable(\"id\") Long id) {\n27 \t\tCustomer c = customerService.findById(id);\n28 \t\tif (c == null) {\n29 \t\t\tthrow new ResourceNotFoundException(\"Requested order doesn't exist\");\n30 \t\t}\n31 \t\tlogger.debug(\"Returning element: \" + c);"
lineNumber: 21
variables:
file: file:///examples/customers-tomcat-legacy/src/main/java/io/konveyor/demo/ordermanagement/controller/CustomerController.java
kind: Field
name: customerService
package: io.konveyor.demo.ordermanagement.controller
java-downloaded-maven-artifact:
description: |
This rule tests the application downloaded from maven artifact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ var locationToCode = map[string]int{
"type": 10,
"package": 11,
"field": 12,
"method": 13,
}

type javaProvider struct {
Expand All @@ -86,8 +87,19 @@ type javaCondition struct {
}

type referenceCondition struct {
Pattern string `yaml:"pattern"`
Location string `yaml:"location"`
Pattern string `yaml:"pattern"`
Location string `yaml:"location"`
Annotated annotated `yaml:"annotated,omitempty" json:"annotated,omitempty"`
}

type annotated struct {
Pattern string `yaml:"pattern" json:"pattern"`
Elements []element `yaml:"elements,omitempty" json:"elements,omitempty"`
}

type element struct {
Name string `yaml:"name" json:"name"`
Value string `yaml:"value" json:"value"` // can be a (java) regex pattern
}

func NewJavaProvider(log logr.Logger, lspServerName string, contextLines int) *javaProvider {
Expand Down Expand Up @@ -296,6 +308,7 @@ func (p *javaProvider) Init(ctx context.Context, log logr.Logger, config provide
"-Djava.net.useSystemProxies=true",
"-configuration",
"./",
//"--jvm-arg=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:1044",
"-data",
workspace,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"os/exec"
"path/filepath"
"reflect"
"regexp"
"strings"
"sync"
Expand Down Expand Up @@ -54,7 +55,7 @@ func (p *javaServiceClient) Evaluate(ctx context.Context, cap string, conditionI
if cond.Referenced.Pattern == "" {
return provider.ProviderEvaluateResponse{}, fmt.Errorf("provided query pattern empty")
}
symbols, err := p.GetAllSymbols(ctx, cond.Referenced.Pattern, cond.Referenced.Location)
symbols, err := p.GetAllSymbols(ctx, cond.Referenced.Pattern, cond.Referenced.Location, cond.Referenced.Annotated)
if err != nil {
p.log.Error(err, "unable to get symbols", "symbols", symbols, "cap", cap, "conditionInfo", cond)
return provider.ProviderEvaluateResponse{}, err
Expand Down Expand Up @@ -86,6 +87,8 @@ func (p *javaServiceClient) Evaluate(ctx context.Context, cap string, conditionI
incidents, err = p.filterDefault(symbols)
case 12:
incidents, err = p.filterDefault(symbols)
case 13:
incidents, err = p.filterDefault(symbols)
default:

}
Expand All @@ -105,7 +108,7 @@ func (p *javaServiceClient) Evaluate(ctx context.Context, cap string, conditionI
}, nil
}

func (p *javaServiceClient) GetAllSymbols(ctx context.Context, query, location string) ([]protocol.WorkspaceSymbol, error) {
func (p *javaServiceClient) GetAllSymbols(ctx context.Context, query, location string, annotation annotated) ([]protocol.WorkspaceSymbol, error) {
// This command will run the added bundle to the language server. The command over the wire needs too look like this.
// in this case the project is hardcoded in the init of the Langauge Server above
// workspace/executeCommand '{"command": "io.konveyor.tackle.ruleEntry", "arguments": {"query":"*customresourcedefinition","project": "java"}}'
Expand All @@ -116,6 +119,10 @@ func (p *javaServiceClient) GetAllSymbols(ctx context.Context, query, location s
"analysisMode": string(p.config.AnalysisMode),
}

if !reflect.DeepEqual(annotation, annotated{}) {
argumentsMap["annotationQuery"] = annotation
}

if p.includedPaths != nil && len(p.includedPaths) > 0 {
argumentsMap[provider.IncludedPathsConfigKey] = p.includedPaths
p.log.V(5).Info("setting search scope by filepaths", "paths", p.includedPaths)
Expand Down
37 changes: 37 additions & 0 deletions rule-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,40 @@
java.referenced:
pattern: io.konveyor.demo.ordermanagement.repository.CustomerRepository
location: FIELD

- category: mandatory
description: |
This rule looks for a given class annotated with a given annotation
message: "Annotation instpection 01"
ruleID: java-annotation-inspection-01
when:
java.referenced:
pattern: io.konveyor.demo.ordermanagement.config.PersistenceConfig
location: TYPE
annotated:
pattern: org.springframework.data.jpa.repository.config.EnableJpaRepositories
elements:
- name: basePackages
value: "io.konveyor.demo.ordermanagement.repository"
- category: mandatory
description: |
This rule looks for a given method annotated with a given annotation
message: "Annotation instpection 02"
ruleID: java-annotation-inspection-02
when:
java.referenced:
pattern: entityManagerFactory()
location: METHOD_DECLARATION
annotated:
pattern: org.springframework.context.annotation.Bean
- category: mandatory
description: |
This rule looks for a given field annotated with a given annotation
message: "Annotation instpection 03"
ruleID: java-annotation-inspection-03
when:
java.referenced:
pattern: io.konveyor.demo.ordermanagement.service.CustomerService
location: FIELD
annotated:
pattern: org.springframework.beans.factory.annotation.Autowired

0 comments on commit 4fdf5e5

Please sign in to comment.