From 7f6f4e9035aee3f14a9ecc42361f9ad04e2ea385 Mon Sep 17 00:00:00 2001 From: Jess Sightler Date: Thu, 24 Sep 2015 09:58:41 -0400 Subject: [PATCH] WINDUP-766: Scan JSP's for potential migration issues --- .../ast/java/data/TypeReferenceLocation.java | 7 +- .../apps/javaee/model/JspSourceFileModel.java | 19 ++ .../rules/AnalyzeJSPFileRuleProvider.java | 174 +++++++++++ .../DiscoverEjbAnnotationsRuleProvider.java | 4 +- .../DiscoverJPAAnnotationsRuleProvider.java | 4 +- .../DiscoverJaxRsAnnotationsRuleProvider.java | 4 +- .../DiscoverJaxWSAnnotationsRuleProvider.java | 3 +- .../javaee/rules/DiscoverRmiRuleProvider.java | 3 +- .../rules/JspFileMappingRuleProvider.java | 35 +++ .../rules/apps/java/condition/JavaClass.java | 5 +- .../java/model/AbstractJavaSourceModel.java | 85 ++++++ .../apps/java/model/JavaSourceFileModel.java | 86 +----- .../java/scan/ast/JavaTypeReferenceModel.java | 3 +- .../jsptest/src/example-with-taglib.jsp | 7 + test-files/jsptest/src/health.jsp | 1 + test-files/jsptest/src/snoop.jsp | 283 ++++++++++++++++++ test-files/jsptest/src/test.jsp | 16 + .../WindupArchitectureJspTest.java | 114 +++++++ 18 files changed, 759 insertions(+), 94 deletions(-) create mode 100644 rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/model/JspSourceFileModel.java create mode 100644 rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/AnalyzeJSPFileRuleProvider.java create mode 100644 rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/JspFileMappingRuleProvider.java create mode 100644 rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/AbstractJavaSourceModel.java create mode 100644 test-files/jsptest/src/example-with-taglib.jsp create mode 100644 test-files/jsptest/src/health.jsp create mode 100644 test-files/jsptest/src/snoop.jsp create mode 100644 test-files/jsptest/src/test.jsp create mode 100644 tests/src/test/java/org/jboss/windup/tests/application/WindupArchitectureJspTest.java diff --git a/java-ast/addon/src/main/java/org/jboss/windup/ast/java/data/TypeReferenceLocation.java b/java-ast/addon/src/main/java/org/jboss/windup/ast/java/data/TypeReferenceLocation.java index 7e759df0ac..7a3b3ac15e 100644 --- a/java-ast/addon/src/main/java/org/jboss/windup/ast/java/data/TypeReferenceLocation.java +++ b/java-ast/addon/src/main/java/org/jboss/windup/ast/java/data/TypeReferenceLocation.java @@ -97,7 +97,12 @@ public enum TypeReferenceLocation * int foo = mypackage.MyConstants.FOO; * */ - VARIABLE_INITIALIZER("Variable Initializer"); + VARIABLE_INITIALIZER("Variable Initializer"), + + /** + * This is only relevant for JSP sources and represents the import of a taglib into the JSP source file. + */ + TAGLIB_IMPORT("Taglib Import"); private String readablePrefix; diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/model/JspSourceFileModel.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/model/JspSourceFileModel.java new file mode 100644 index 0000000000..6d13f8f3d7 --- /dev/null +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/model/JspSourceFileModel.java @@ -0,0 +1,19 @@ +package org.jboss.windup.rules.apps.javaee.model; + +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; + +import com.tinkerpop.frames.modules.typedgraph.TypeValue; + +/** + * Represents a JSP file on disk. + * + * @author Jesse Sightler + */ +@TypeValue(JspSourceFileModel.TYPE) +public interface JspSourceFileModel extends AbstractJavaSourceModel +{ + String UNPARSEABLE_JSP_CLASSIFICATION = "Unparseable JSP File"; + String UNPARSEABLE_JSP_DESCRIPTION = "This JSP file could not be parsed"; + + String TYPE = "JspSourceFile"; +} diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/AnalyzeJSPFileRuleProvider.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/AnalyzeJSPFileRuleProvider.java new file mode 100644 index 0000000000..d1da2a4dd1 --- /dev/null +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/AnalyzeJSPFileRuleProvider.java @@ -0,0 +1,174 @@ +package org.jboss.windup.rules.apps.javaee.rules; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.jboss.windup.ast.java.data.ClassReference; +import org.jboss.windup.ast.java.data.ResolutionStatus; +import org.jboss.windup.ast.java.data.TypeReferenceLocation; +import org.jboss.windup.config.AbstractRuleProvider; +import org.jboss.windup.config.GraphRewrite; +import org.jboss.windup.config.metadata.MetadataBuilder; +import org.jboss.windup.config.operation.iteration.AbstractIterationOperation; +import org.jboss.windup.config.phase.InitialAnalysisPhase; +import org.jboss.windup.config.query.Query; +import org.jboss.windup.graph.GraphContext; +import org.jboss.windup.reporting.service.ClassificationService; +import org.jboss.windup.rules.apps.java.model.JavaClassModel; +import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; +import org.jboss.windup.rules.apps.java.scan.ast.TypeInterestFactory; +import org.jboss.windup.rules.apps.java.service.JavaClassService; +import org.jboss.windup.rules.apps.java.service.TypeReferenceService; +import org.jboss.windup.rules.apps.javaee.model.JspSourceFileModel; +import org.ocpsoft.rewrite.config.Configuration; +import org.ocpsoft.rewrite.config.ConfigurationBuilder; +import org.ocpsoft.rewrite.context.EvaluationContext; + +/** + * Extracts type references from JSP files. + * + * @author Jesse Sightler + */ +public class AnalyzeJSPFileRuleProvider extends AbstractRuleProvider +{ + public AnalyzeJSPFileRuleProvider() + { + super(MetadataBuilder.forProvider(AnalyzeJSPFileRuleProvider.class) + .setPhase(InitialAnalysisPhase.class) + .setHaltOnException(true)); + } + + // @formatter:off + @Override + public Configuration getConfiguration(GraphContext context) + { + return ConfigurationBuilder.begin() + .addRule() + .when(Query.fromType(JspSourceFileModel.class)) + .perform(new ParseSourceOperation()); + } + // @formatter:on + + private class ParseSourceOperation extends AbstractIterationOperation + { + @Override + public void perform(GraphRewrite event, EvaluationContext context, JspSourceFileModel sourceFile) + { + + TypeReferenceService typeReferenceService = new TypeReferenceService(event.getGraphContext()); + + try + { + // Setup some basic details about the "Java Class" + // source root, is decompiled, javaclass. package name + sourceFile.setPackageName(""); + sourceFile.setDecompiled(false); + JavaClassService javaClassService = new JavaClassService(event.getGraphContext()); + JavaClassModel classModel = javaClassService.create(); + classModel.setPackageName(""); + classModel.setSimpleName(sourceFile.getFileName()); + classModel.setQualifiedName(sourceFile.getFileName()); + classModel.setExtends(javaClassService.getOrCreatePhantom("javax.servlet.http.HttpServlet")); + sourceFile.addJavaClass(classModel); + + Iterable references = getClassReferences(typeReferenceService, sourceFile); + for (ClassReference reference : references) + { + JavaTypeReferenceModel typeReference = typeReferenceService.createTypeReference(sourceFile, + reference.getLocation(), + reference.getResolutionStatus(), + reference.getLineNumber(), reference.getColumn(), reference.getLength(), + reference.getQualifiedName(), + reference.getLine()); + } + } + catch (Exception e) + { + ClassificationService classificationService = new ClassificationService(event.getGraphContext()); + classificationService.attachClassification(context, sourceFile, JspSourceFileModel.UNPARSEABLE_JSP_CLASSIFICATION, + JspSourceFileModel.UNPARSEABLE_JSP_DESCRIPTION); + } + } + } + + private Iterable getClassReferences(TypeReferenceService service, JspSourceFileModel sourceFile) throws IOException + { + String source = FileUtils.readFileToString(sourceFile.asFile()); + + List results = new ArrayList<>(); + results.addAll(findImports(source)); + results.addAll(findTaglib(source)); + return results; + } + + private List findImports(String source) + { + List results = new ArrayList<>(); + + Pattern jspImport = Pattern.compile("<%@\\s*page\\s+[^>]*\\s*import\\s*=\\s*['\"]([^'\"]+)['\"].*?%>", + Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + Matcher matcher = jspImport.matcher(source); + while (matcher.find()) + { + String matched = matcher.group(1); + if (StringUtils.isNotBlank(matched)) + { + String[] imports = StringUtils.split(matched, ","); + if (imports != null) + { + for (String imported : imports) + { + imported = StringUtils.trim(imported); + if (TypeInterestFactory.matchesAny(imported, TypeReferenceLocation.IMPORT)) + { + ClassReference reference = createClassReference(TypeReferenceLocation.IMPORT, source, imported, matcher.start()); + results.add(reference); + } + } + } + } + } + return results; + } + + private List findTaglib(String source) + { + List results = new ArrayList<>(); + + Pattern taglibPattern = Pattern.compile("<%@\\s*taglib\\s+[^>]*\\s*uri\\s*=\\s*['\"]([^'\"]+)['\"].*?%>", + Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + Matcher matcher = taglibPattern.matcher(source); + while (matcher.find()) + { + String matched = matcher.group(1); + if (StringUtils.isNotBlank(matched)) + { + if (TypeInterestFactory.matchesAny(matched, TypeReferenceLocation.TAGLIB_IMPORT)) + { + ClassReference reference = createClassReference(TypeReferenceLocation.TAGLIB_IMPORT, source, matched, matcher.start()); + results.add(reference); + } + } + } + return results; + } + + private ClassReference createClassReference(TypeReferenceLocation location, String source, String reference, int startPosition) + { + String subString = StringUtils.substring(source, 0, startPosition + 1); + String[] lines = subString.split("\r\n|\r|\n"); + + int lineNumber = lines.length; + int column = lines[lines.length - 1].indexOf(source.substring(startPosition)); + int length = reference.length(); + + return new ClassReference(reference, ResolutionStatus.UNKNOWN, location, lineNumber, column, length, + reference); + } + +} diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverEjbAnnotationsRuleProvider.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverEjbAnnotationsRuleProvider.java index 9e66a137ed..06ce09cd07 100644 --- a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverEjbAnnotationsRuleProvider.java +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverEjbAnnotationsRuleProvider.java @@ -14,8 +14,8 @@ import org.jboss.windup.graph.service.GraphService; import org.jboss.windup.graph.service.Service; import org.jboss.windup.rules.apps.java.condition.JavaClass; +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaClassModel; -import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel; import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationListTypeValueModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationLiteralTypeValueModel; @@ -197,7 +197,7 @@ else if (annotationTypeReferenceModel instanceof JavaAnnotationTypeReferenceMode private JavaClassModel getJavaClass(JavaTypeReferenceModel javaTypeReference) { JavaClassModel result = null; - JavaSourceFileModel javaSource = javaTypeReference.getFile(); + AbstractJavaSourceModel javaSource = javaTypeReference.getFile(); for (JavaClassModel javaClassModel : javaSource.getJavaClasses()) { // there can be only one public one, and the annotated class should be public diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJPAAnnotationsRuleProvider.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJPAAnnotationsRuleProvider.java index 88211f149a..59caa79312 100644 --- a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJPAAnnotationsRuleProvider.java +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJPAAnnotationsRuleProvider.java @@ -14,8 +14,8 @@ import org.jboss.windup.graph.model.WindupVertexFrame; import org.jboss.windup.graph.service.GraphService; import org.jboss.windup.rules.apps.java.condition.JavaClass; +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaClassModel; -import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel; import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationListTypeValueModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationLiteralTypeValueModel; @@ -202,7 +202,7 @@ private void addNamedQuery(GraphService namedQueryService, J private JavaClassModel getJavaClass(JavaTypeReferenceModel javaTypeReference) { JavaClassModel result = null; - JavaSourceFileModel javaSource = javaTypeReference.getFile(); + AbstractJavaSourceModel javaSource = javaTypeReference.getFile(); for (JavaClassModel javaClassModel : javaSource.getJavaClasses()) { // there can be only one public one, and the annotated class should be public diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxRsAnnotationsRuleProvider.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxRsAnnotationsRuleProvider.java index 3167b428d4..a2d232fcdc 100644 --- a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxRsAnnotationsRuleProvider.java +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxRsAnnotationsRuleProvider.java @@ -11,8 +11,8 @@ import org.jboss.windup.config.phase.InitialAnalysisPhase; import org.jboss.windup.graph.GraphContext; import org.jboss.windup.rules.apps.java.condition.JavaClass; +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaClassModel; -import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel; import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationLiteralTypeValueModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationTypeReferenceModel; @@ -93,7 +93,7 @@ private String getAnnotationLiteralValue(JavaAnnotationTypeReferenceModel model, private JavaClassModel getJavaClass(JavaTypeReferenceModel javaTypeReference) { JavaClassModel result = null; - JavaSourceFileModel javaSource = javaTypeReference.getFile(); + AbstractJavaSourceModel javaSource = javaTypeReference.getFile(); for (JavaClassModel javaClassModel : javaSource.getJavaClasses()) { // there can be only one public one, and the annotated class should be public diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxWSAnnotationsRuleProvider.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxWSAnnotationsRuleProvider.java index 6083f01f45..524e8e4c02 100644 --- a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxWSAnnotationsRuleProvider.java +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverJaxWSAnnotationsRuleProvider.java @@ -12,6 +12,7 @@ import org.jboss.windup.config.phase.InitialAnalysisPhase; import org.jboss.windup.graph.GraphContext; import org.jboss.windup.rules.apps.java.condition.JavaClass; +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaClassModel; import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel; import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; @@ -99,7 +100,7 @@ private void extractMetadata(GraphRewrite event, JavaTypeReferenceModel typeRefe private JavaClassModel getJavaClass(JavaTypeReferenceModel javaTypeReference) { JavaClassModel result = null; - JavaSourceFileModel javaSource = javaTypeReference.getFile(); + AbstractJavaSourceModel javaSource = javaTypeReference.getFile(); for (JavaClassModel javaClassModel : javaSource.getJavaClasses()) { // there can be only one public one, and the annotated class should be public diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverRmiRuleProvider.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverRmiRuleProvider.java index e9b8268096..18bddd602d 100644 --- a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverRmiRuleProvider.java +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/DiscoverRmiRuleProvider.java @@ -12,6 +12,7 @@ import org.jboss.windup.config.phase.MigrationRulesPhase; import org.jboss.windup.graph.GraphContext; import org.jboss.windup.rules.apps.java.condition.JavaClass; +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaClassModel; import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel; import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; @@ -116,7 +117,7 @@ public boolean isRemoteInterface(JavaClassModel jcm) private JavaClassModel getJavaClass(JavaTypeReferenceModel javaTypeReference) { JavaClassModel result = null; - JavaSourceFileModel javaSource = javaTypeReference.getFile(); + AbstractJavaSourceModel javaSource = javaTypeReference.getFile(); for (JavaClassModel javaClassModel : javaSource.getJavaClasses()) { diff --git a/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/JspFileMappingRuleProvider.java b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/JspFileMappingRuleProvider.java new file mode 100644 index 0000000000..b7a750a0b8 --- /dev/null +++ b/rules-java-ee/addon/src/main/java/org/jboss/windup/rules/apps/javaee/rules/JspFileMappingRuleProvider.java @@ -0,0 +1,35 @@ +package org.jboss.windup.rules.apps.javaee.rules; + +import org.jboss.windup.config.AbstractRuleProvider; +import org.jboss.windup.config.metadata.MetadataBuilder; +import org.jboss.windup.config.phase.ClassifyFileTypesPhase; +import org.jboss.windup.graph.GraphContext; +import org.jboss.windup.rules.apps.javaee.model.JspSourceFileModel; +import org.jboss.windup.rules.files.FileMapping; +import org.ocpsoft.rewrite.config.Configuration; +import org.ocpsoft.rewrite.config.ConfigurationBuilder; + +/** + * Insures that basic JSP file extensions are mapped to {@link JspSourceFileModel}. + * + * @author Jesse Sightler + */ +public class JspFileMappingRuleProvider extends AbstractRuleProvider +{ + + public JspFileMappingRuleProvider() + { + super(MetadataBuilder.forProvider(JspFileMappingRuleProvider.class) + .setPhase(ClassifyFileTypesPhase.class)); + } + + @Override + public Configuration getConfiguration(GraphContext context) + { + return ConfigurationBuilder.begin() + .addRule(FileMapping.from(".*\\.jsp$").to(JspSourceFileModel.class)) + .addRule(FileMapping.from(".*\\.jspx$").to(JspSourceFileModel.class)) + .addRule(FileMapping.from(".*\\.jsf$").to(JspSourceFileModel.class)) + .addRule(FileMapping.from(".*\\.xhtml$").to(JspSourceFileModel.class)); + } +} diff --git a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/condition/JavaClass.java b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/condition/JavaClass.java index 8f189cd04c..204661511e 100644 --- a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/condition/JavaClass.java +++ b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/condition/JavaClass.java @@ -29,6 +29,7 @@ import org.jboss.windup.config.query.QueryPropertyComparisonType; import org.jboss.windup.graph.model.WindupVertexFrame; import org.jboss.windup.graph.model.resource.FileModel; +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaClassFileModel; import org.jboss.windup.rules.apps.java.model.JavaClassModel; import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel; @@ -239,8 +240,8 @@ private boolean evaluate(GraphRewrite event, EvaluationContext context, Evaluati { FileModel fileModel = ((FileReferenceModel) frame).getFile(); Iterable javaClasses = null; - if (fileModel instanceof JavaSourceFileModel) - javaClasses = ((JavaSourceFileModel) fileModel).getJavaClasses(); + if (fileModel instanceof AbstractJavaSourceModel) + javaClasses = ((AbstractJavaSourceModel) fileModel).getJavaClasses(); else if (fileModel instanceof JavaClassFileModel) javaClasses = Arrays.asList(((JavaClassFileModel) fileModel).getJavaClass()); diff --git a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/AbstractJavaSourceModel.java b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/AbstractJavaSourceModel.java new file mode 100644 index 0000000000..3846663dde --- /dev/null +++ b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/AbstractJavaSourceModel.java @@ -0,0 +1,85 @@ +package org.jboss.windup.rules.apps.java.model; + +import org.jboss.windup.graph.Indexed; +import org.jboss.windup.graph.model.resource.FileModel; +import org.jboss.windup.graph.model.resource.SourceFileModel; + +import com.tinkerpop.blueprints.Direction; +import com.tinkerpop.frames.Adjacency; +import com.tinkerpop.frames.Property; +import com.tinkerpop.frames.modules.typedgraph.TypeValue; + +/** + * + * This represents Java source code as an abstract concept. This is useful for things that are not strictly ".java" source code, but are semantically + * very similar to Java source code. Generally files like this will have a 1-to-1 relationship with a generated .java file, but we may only have + * access to the original source at runtime. + * + * An example of this would be a JSP file, although there could be others. + * + * @author Jesse Sightler + */ +@TypeValue(AbstractJavaSourceModel.TYPE) +public interface AbstractJavaSourceModel extends FileModel, SourceFileModel +{ + String TYPE = "AbstractJavaSourceModel"; + String PACKAGE_NAME = "packageName"; + String JAVA_CLASS_MODEL = "javaClass"; + String ROOT_SOURCE_FOLDER = "rootSourceFolder"; + String IS_DECOMPILED = "decompiled"; + + /** + * This is the "root" directory for this source file. + * + * For example, if you have a file at "/project/src/main/java/org/example/Foo.java" then this would point the directory "/project/src/main/java". + * + */ + @Adjacency(label = ROOT_SOURCE_FOLDER, direction = Direction.OUT) + FileModel getRootSourceFolder(); + + /** + * This is the "root" directory for this source file. + * + * For example, if you have a file at "/project/src/main/java/org/example/Foo.java" then this would point the directory "/project/src/main/java". + * + */ + @Adjacency(label = ROOT_SOURCE_FOLDER, direction = Direction.OUT) + void setRootSourceFolder(FileModel fileModel); + + /** + * Contains the Java package name + */ + @Indexed + @Property(PACKAGE_NAME) + String getPackageName(); + + /** + * Contains the Java package name + */ + @Property(PACKAGE_NAME) + void setPackageName(String packageName); + + /** + * Lists the {@link JavaClassModel}s contained within this source file + */ + @Adjacency(label = JAVA_CLASS_MODEL, direction = Direction.OUT) + Iterable getJavaClasses(); + + /** + * Lists the {@link JavaClassModel}s contained within this source file + */ + @Adjacency(label = JAVA_CLASS_MODEL, direction = Direction.OUT) + void addJavaClass(JavaClassModel javaClassModel); + + /** + * Specifies if the given .java file was decompiled from a .class file + */ + @Property(IS_DECOMPILED) + Boolean isDecompiled(); + + /** + * Specifies if the given .java file was decompiled from a .class file + */ + @Property(IS_DECOMPILED) + void setDecompiled(boolean decompiled); +} diff --git a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/JavaSourceFileModel.java b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/JavaSourceFileModel.java index a8ef2adda4..192e922747 100644 --- a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/JavaSourceFileModel.java +++ b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/model/JavaSourceFileModel.java @@ -1,12 +1,5 @@ package org.jboss.windup.rules.apps.java.model; -import org.jboss.windup.graph.Indexed; -import org.jboss.windup.graph.model.resource.FileModel; -import org.jboss.windup.graph.model.resource.SourceFileModel; - -import com.tinkerpop.blueprints.Direction; -import com.tinkerpop.frames.Adjacency; -import com.tinkerpop.frames.Property; import com.tinkerpop.frames.modules.typedgraph.TypeValue; /** @@ -15,81 +8,10 @@ * @author Jesse Sightler */ @TypeValue(JavaSourceFileModel.TYPE) -public interface JavaSourceFileModel extends FileModel, SourceFileModel +public interface JavaSourceFileModel extends AbstractJavaSourceModel { - public static final String UNPARSEABLE_JAVA_CLASSIFICATION = "Unparseable Java File"; - public static final String UNPARSEABLE_JAVA_DESCRIPTION = "This Java file could not be parsed"; - - public static final String TYPE = "JavaSourceFileModel"; - public static final String PACKAGE_NAME = "packageName"; - public static final String JAVA_CLASS_MODEL = "javaClass"; - public static final String ROOT_SOURCE_FOLDER = "rootSourceFolder"; - public static final String IS_DECOMPILED = "decompiled"; - - /** - * This is the "root" directory for this source file. - * - * For example, if you have a file at "/project/src/main/java/org/example/Foo.java" then this would point the - * directory "/project/src/main/java". - * - */ - @Adjacency(label = ROOT_SOURCE_FOLDER, direction = Direction.OUT) - FileModel getRootSourceFolder(); - - /** - * This is the "root" directory for this source file. - * - * For example, if you have a file at "/project/src/main/java/org/example/Foo.java" then this would point the - * directory "/project/src/main/java". - * - */ - @Adjacency(label = ROOT_SOURCE_FOLDER, direction = Direction.OUT) - void setRootSourceFolder(FileModel fileModel); - - /** - * Contains the Java package name - */ - @Indexed - @Property(PACKAGE_NAME) - String getPackageName(); - - /** - * Contains the Java package name - */ - @Property(PACKAGE_NAME) - void setPackageName(String packageName); - - /** - * Contains the primary {@link JavaClassModel} in the class - */ - void setMainJavaClass(JavaClassModel javaClassModel); - - /** - * Contains the primary {@link JavaClassModel} in the class - */ - JavaClassModel getMainJavaClass(); - - /** - * Lists the {@link JavaClassModel}s contained within this source file - */ - @Adjacency(label = JAVA_CLASS_MODEL, direction = Direction.OUT) - Iterable getJavaClasses(); - - /** - * Lists the {@link JavaClassModel}s contained within this source file - */ - @Adjacency(label = JAVA_CLASS_MODEL, direction = Direction.OUT) - void addJavaClass(JavaClassModel javaClassModel); - - /** - * Specifies if the given .java file was decompiled from a .class file - */ - @Property(IS_DECOMPILED) - Boolean isDecompiled(); + String UNPARSEABLE_JAVA_CLASSIFICATION = "Unparseable Java File"; + String UNPARSEABLE_JAVA_DESCRIPTION = "This Java file could not be parsed"; - /** - * Specifies if the given .java file was decompiled from a .class file - */ - @Property(IS_DECOMPILED) - void setDecompiled(boolean decompiled); + String TYPE = "JavaSourceFileModel"; } \ No newline at end of file diff --git a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/scan/ast/JavaTypeReferenceModel.java b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/scan/ast/JavaTypeReferenceModel.java index a49f2420da..a7a75f3e78 100644 --- a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/scan/ast/JavaTypeReferenceModel.java +++ b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/scan/ast/JavaTypeReferenceModel.java @@ -4,6 +4,7 @@ import org.jboss.windup.ast.java.data.TypeReferenceLocation; import org.jboss.windup.graph.IndexType; import org.jboss.windup.graph.Indexed; +import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel; import org.jboss.windup.rules.files.model.FileLocationModel; @@ -32,7 +33,7 @@ public interface JavaTypeReferenceModel extends FileLocationModel */ @Override @Adjacency(label = FILE_MODEL, direction = Direction.OUT) - JavaSourceFileModel getFile(); + AbstractJavaSourceModel getFile(); /** * Gets the snippit referenced by this {@link FileLocationModel}. diff --git a/test-files/jsptest/src/example-with-taglib.jsp b/test-files/jsptest/src/example-with-taglib.jsp new file mode 100644 index 0000000000..3678f5dfe1 --- /dev/null +++ b/test-files/jsptest/src/example-with-taglib.jsp @@ -0,0 +1,7 @@ +<%@ taglib uri="http://www.example.com/custlib" prefix="mytag" %> + + + + + + diff --git a/test-files/jsptest/src/health.jsp b/test-files/jsptest/src/health.jsp new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/test-files/jsptest/src/health.jsp @@ -0,0 +1 @@ +1 diff --git a/test-files/jsptest/src/snoop.jsp b/test-files/jsptest/src/snoop.jsp new file mode 100644 index 0000000000..a112f626ee --- /dev/null +++ b/test-files/jsptest/src/snoop.jsp @@ -0,0 +1,283 @@ + + + JBossEAP6.0 JSP snoop page + <%@ page import="javax.servlet.http.HttpUtils,java.util.Enumeration" %> + <%@ page import="java.lang.management.*" %> + <%@ page import="java.util.*" %> + + + +

WebApp JSP Snoop page

+ + +

JVM Memory Monitor

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Memory MXBean

+
Heap Memory Usage +<%=ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()%> +
Non-Heap Memory Usage +<%=ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()%> +
+

Memory Pool MXBeans

+
+<% +Iterator iter = ManagementFactory.getMemoryPoolMXBeans().iterator(); +while (iter.hasNext()) { +MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next(); +%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
<%= item.getName() %>
Type<%= item.getType() %>
Usage<%= item.getUsage() %>
Peak Usage<%= item.getPeakUsage() %>
Collection Usage<%= item.getCollectionUsage() %>
+ + +<% +} +%> + +

Request information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Requested URL:<%= HttpUtils.getRequestURL(request) %>
Request method:<%= request.getMethod() %>
Request URI:<%= request.getRequestURI() %>
Request protocol:<%= request.getProtocol() %>
Servlet path:<%= request.getServletPath() %>
Path info:<%= request.getPathInfo() %>
Path translated:<%= request.getPathTranslated() %>
Query string:<% if(request.getQueryString()!=null) out.write(request.getQueryString().replaceAll("<", "<").replaceAll(">",">")); %>
Content length:<%= request.getContentLength() %>
Content type:<%= request.getContentType() %>
Server name:<%= request.getServerName() %>
Server port:<%= request.getServerPort() %>
Remote user:<%= request.getRemoteUser() %>
Remote address:<%= request.getRemoteAddr() %>
Remote host:<%= request.getRemoteHost() %>
Authorization scheme:<%= request.getAuthType() %>
+ +<% + Enumeration e = request.getHeaderNames(); + if(e != null && e.hasMoreElements()) { +%> +

Request headers

+ + + + + + +<% + while(e.hasMoreElements()) { + String k = (String) e.nextElement(); +%> + + + + +<% + } +%> +
Header:Value:
<%= k %><%= request.getHeader(k) %>
+<% + } +%> + + +<% + e = request.getParameterNames(); + if(e != null && e.hasMoreElements()) { +%> +

Request parameters

+ + + + + + +<% + while(e.hasMoreElements()) { + String k = (String) e.nextElement(); + String val = request.getParameter(k); + String vals[] = request.getParameterValues(k); +%> + + + + + +<% + } +%> +
Parameter:Value:Multiple values:
<%= k.replaceAll("<", "<").replaceAll(">",">") %><%= val.replaceAll("<", "<").replaceAll(">",">") %><% + for(int i = 0; i < vals.length; i++) { + if(i > 0) + out.print("
"); + out.print(vals[i].replaceAll("<", "<").replaceAll(">",">")); + } + %>
+<% + } +%> + + +<% + e = request.getAttributeNames(); + if(e != null && e.hasMoreElements()) { +%> +

Request Attributes

+ + + + + +<% + while(e.hasMoreElements()) { + String k = (String) e.nextElement(); + Object val = request.getAttribute(k); +%> + + + + +<% + } +%> +
Attribute:Value:
<%= k.replaceAll("<", "<").replaceAll(">",">") %><%= val.toString().replaceAll("<", "<").replaceAll(">",">") %>
+<% + } +%> + + +<% + e = getServletConfig().getInitParameterNames(); + if(e != null && e.hasMoreElements()) { +%> +

Init parameters

+ + + + + +<% + while(e.hasMoreElements()) { + String k = (String) e.nextElement(); + String val = getServletConfig().getInitParameter(k); +%> + + + + +<% + } +%> +
Parameter:Value:
<%= k %><%= val %>
+<% + } +%> + + + + diff --git a/test-files/jsptest/src/test.jsp b/test-files/jsptest/src/test.jsp new file mode 100644 index 0000000000..a8c4bab5e6 --- /dev/null +++ b/test-files/jsptest/src/test.jsp @@ -0,0 +1,16 @@ + + + JBossEAP6.0 JSP snoop page + <%@ page import="javax.servlet.http.HttpUtils,java.util.Enumeration" %> + <%@ page import="java.lang.management.*" %> + <%@ page import="java.util.*" %> + + + +

WebApp JSP Snoop page

+ +

This is a test.

+ +<%= 1 + 1 %> + + \ No newline at end of file diff --git a/tests/src/test/java/org/jboss/windup/tests/application/WindupArchitectureJspTest.java b/tests/src/test/java/org/jboss/windup/tests/application/WindupArchitectureJspTest.java new file mode 100644 index 0000000000..9415ccd9d4 --- /dev/null +++ b/tests/src/test/java/org/jboss/windup/tests/application/WindupArchitectureJspTest.java @@ -0,0 +1,114 @@ +package org.jboss.windup.tests.application; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.forge.arquillian.AddonDependencies; +import org.jboss.forge.arquillian.AddonDependency; +import org.jboss.forge.arquillian.archive.AddonArchive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.windup.ast.java.data.TypeReferenceLocation; +import org.jboss.windup.config.AbstractRuleProvider; +import org.jboss.windup.config.GraphRewrite; +import org.jboss.windup.config.metadata.MetadataBuilder; +import org.jboss.windup.config.operation.iteration.AbstractIterationOperation; +import org.jboss.windup.graph.GraphContext; +import org.jboss.windup.graph.model.resource.FileModel; +import org.jboss.windup.rules.apps.java.condition.JavaClass; +import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; +import org.jboss.windup.rules.apps.javaee.model.JspSourceFileModel; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ocpsoft.rewrite.config.Configuration; +import org.ocpsoft.rewrite.config.ConfigurationBuilder; +import org.ocpsoft.rewrite.context.EvaluationContext; + +@RunWith(Arquillian.class) +public class WindupArchitectureJspTest extends WindupArchitectureTest +{ + + @Deployment + @AddonDependencies({ + @AddonDependency(name = "org.jboss.windup.graph:windup-graph"), + @AddonDependency(name = "org.jboss.windup.reporting:windup-reporting"), + @AddonDependency(name = "org.jboss.windup.exec:windup-exec"), + @AddonDependency(name = "org.jboss.windup.rules.apps:windup-rules-java"), + @AddonDependency(name = "org.jboss.windup.rules.apps:windup-rules-java-ee"), + @AddonDependency(name = "org.jboss.windup.rules.apps:windup-rules-tattletale"), + @AddonDependency(name = "org.jboss.windup.tests:test-util"), + @AddonDependency(name = "org.jboss.windup.config:windup-config-groovy"), + @AddonDependency(name = "org.jboss.forge.furnace.container:cdi"), + }) + public static AddonArchive getDeployment() + { + return ShrinkWrap.create(AddonArchive.class) + .addBeansXML() + .addClass(WindupArchitectureTest.class); + } + + @Inject + private JspRulesProvider provider; + + @Test + public void testRunWindupJsp() throws Exception + { + final String path = "../test-files/jsptest"; + + try (GraphContext context = createGraphContext()) + { + super.runTest(context, path, false); + + Assert.assertEquals(1, provider.taglibsFound); + Assert.assertEquals(2, provider.enumerationRuleHitCount); + } + } + + @Singleton + public static class JspRulesProvider extends AbstractRuleProvider + { + private int taglibsFound = 0; + private int enumerationRuleHitCount = 0; + + public JspRulesProvider() + { + super(MetadataBuilder.forProvider(JspRulesProvider.class) + .setHaltOnException(true)); + } + + @Override + public Configuration getConfiguration(GraphContext context) + { + return ConfigurationBuilder.begin() + .addRule() + .when(JavaClass.references("http://www.example.com/custlib").at(TypeReferenceLocation.TAGLIB_IMPORT)) + .perform( + new AbstractIterationOperation() + { + @Override + public void perform(GraphRewrite event, EvaluationContext context, JavaTypeReferenceModel payload) + { + FileModel source = payload.getFile(); + if (!(source instanceof JspSourceFileModel)) + Assert.fail("File was not a jsp file!"); + taglibsFound++; + } + }) + .addRule() + .when(JavaClass.references("java.util.Enumeration").at(TypeReferenceLocation.IMPORT)) + .perform(new AbstractIterationOperation() + { + @Override + public void perform(GraphRewrite event, EvaluationContext context, JavaTypeReferenceModel payload) + { + FileModel source = payload.getFile(); + if (!(source instanceof JspSourceFileModel)) + Assert.fail("File was not a jsp file!"); + enumerationRuleHitCount++; + } + }); + } + } +}