
net.jakubholy.jeeutils.jsfelcheck.JsfStaticAnalyzer Maven / Gradle / Ivy
Show all versions of static-jsfexpression-validator-jsf12 Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.jakubholy.jeeutils.jsfelcheck;
import net.jakubholy.jeeutils.jsfelcheck.beanfinder.InputResource;
import net.jakubholy.jeeutils.jsfelcheck.beanfinder.ManagedBeanFinder;
import net.jakubholy.jeeutils.jsfelcheck.beanfinder.jsf12.Jsf12FacesConfigXmlBeanFinder;
import net.jakubholy.jeeutils.jsfelcheck.expressionfinder.impl.facelets.JsfElValidatingFaceletsParser;
import net.jakubholy.jeeutils.jsfelcheck.expressionfinder.impl.facelets.jsf12.MyFaces12ValidatingFaceletsParser;
import net.jakubholy.jeeutils.jsfelcheck.expressionfinder.pagenodes.PageNodeListener;
import net.jakubholy.jeeutils.jsfelcheck.validator.ValidatingElResolver;
import net.jakubholy.jeeutils.jsfelcheck.validator.jsf12.Jsf12ValidatingElResolver;
import org.apache.el.parser.AstAnd;
import java.io.File;
import java.util.Collection;
/**
* JavaDoc copied from {@link net.jakubholy.jeeutils.jsfelcheck.AbstractJsfStaticAnalyzer}; version for JSF 1.2.
*
* The validator analyses JSF pages implemented with Facelets or JSP and validates that all EL
* expressions reference only existing managed beans and their properties/action
* methods. See the example below and
* examples in the test webapps.
* Of course you will need one of the JSF version specific subclasses, namely
* net.jakubholy.jeeutils.jsfelcheck.JsfStaticAnalyzer
.
*
* Usage example
*
* You create the analyzer, tell it where it can find your managed beans and run it on your webapp:
*
*
* {@code
* JsfStaticAnalyzer jsfStaticAnalyzer = JsfStaticAnalyzer.forFacelets();
* jsfStaticAnalyzer.withManagedBeansAndVariablesConfiguration(
* ManagedBeansAndVariablesConfiguration
* .fromClassesInPackages("net.jakubholy.jeeutils.jsfelcheck.webtest.jsf20.test.annotated")
* .annotatedWith(Named.class, "value")
* .config());
*
* File webappRoot = new File("src/main/webapp");
*
* CollectedValidationResults results = jsfStaticAnalyzer.validateElExpressions(
* webappRoot,
* new File(webappRoot, "tests/annotated"));
*
* assertEquals("There shall be no invalid JSF EL expressions; check System.err.out for details. FAILURE " + results.failures()
* , 0, results.failures().size());
* }
*
* See the test-webapp-jsf* projects that are part of this project to see examples of usage with different
* versions o JSF and different configurations. You can
* see them at GitHub or
* download from Maven Central.
*
* Configuration
*
* You usually need to configure the validator, f.ex. tell it where to find your managed beans, inform it about
* the types of JSF local variables and properties that it cannot detect automatically etc.
* You might prefer to just look at the examples and start using the validator over reading this
* documentation and only come back to it if you find out that you need to know more.
*
*
* See the with*
methods - if they take an object then you usually can create it via a static
* method on the object's class - it works best with static imports.
*
*
* Managed Beans and Other (Top-Level) Variables
*
* You always have to inform the validator where to find your managed beans - in faces-config, Spring
* application configuration XML, or as annotated beans on the classpath.
*
*
* If there are some EL variables aside of managed beans and the local variables you can declare them to the
* validator via {@link net.jakubholy.jeeutils.jsfelcheck.config.ManagedBeansAndVariablesConfiguration#withExtraVariable(String, Object)}.
*
*
* Local Variables
*
* For local variables, such as the var
produced by h:dataTable
, you
* must declare of what type they are as this cannot be determined based
* on the code, see
* {@link net.jakubholy.jeeutils.jsfelcheck.config.LocalVariableConfiguration#withLocalVariable(String, Class)}.
*
*
* If there are other tags than h:dataTable for JSP or ui:repeat for Facelets that can create local variables then you
* must create and register an appropriate "resolver" (a class that can extract the local variable name and type from
* the tag info) for them as is done with the
* dataTable - see {@link net.jakubholy.jeeutils.jsfelcheck.config.LocalVariableConfiguration#withCustomDataTableTagAlias} and
* {@link net.jakubholy.jeeutils.jsfelcheck.config.LocalVariableConfiguration#withResolverForVariableProducingTag}.
*
* See {@link net.jakubholy.jeeutils.jsfelcheck.expressionfinder.variables.DataTableVariableResolver} for an example.
*
*
* Declaration of Types of Elements in Collections and Maps
*
* You can also help the validator by telling it what is the type of elements in collection/maps
* via {@link #withPropertyTypeOverride(String, Class)}. (This is necessary even for maps/collections using
* generics as the Java compiler removes the type information; you can alternatively try to play with this
*
* experimental generics type extractor based on the Java Compiler API.)
*
*
* How it works
* We use "fake value resolversIn" for a real JSF resolver; those resolversIn do not retrieve
* variables and property values from the context as JSF normally does but instead produce
* a new fake value of the expected type using Mockito - thus we can check that expressions are
* valid. When the type of a variable/property cannot be determined (which is often the case for
* Collections, which can contain nay Object) and isn't defined via property override etc. then
* we use {@link net.jakubholy.jeeutils.jsfelcheck.validator.MockObjectOfUnknownType} -
* if you see it in a failed JSF EL check then you need
* to declare the type to use.
*
* Limitations
*
* @author jakubholy.net
*
* @see #validateElExpressions(java.io.File, java.io.File)
* @see #withManagedBeansAndVariablesConfiguration(net.jakubholy.jeeutils.jsfelcheck.config.ManagedBeansAndVariablesConfiguration)
* @see CollectedValidationResults#failures()
*
*/
public class JsfStaticAnalyzer extends AbstractJsfStaticAnalyzer {
/** Instance for validation of JSP pages. */
public static JsfStaticAnalyzer forJsp() {
return new JsfStaticAnalyzer(ViewType.JSP);
}
/** Instance for validation of Facelets pages. */
public static JsfStaticAnalyzer forFacelets() {
return new JsfStaticAnalyzer(ViewType.FACELETS);
}
/** For tests only */
JsfStaticAnalyzer() {
this(ViewType.JSP);
}
private JsfStaticAnalyzer(ViewType viewType) {
super(viewType);
LOG.info("Created JSF 1.2 JsfStaticAnalyzer");
}
public static void main(String[] args) throws Exception { // SUPPRESS CHECKSTYLE (no javadoc)
AbstractJsfStaticAnalyzer.main(new JsfStaticAnalyzer(), args);
}
@Override
protected ValidatingElResolver createValidatingElResolver() {
if (! new AstAnd(0).toString().startsWith("HACKED BY JSFELCHECK ")) {
handleUnhackedElImplementationLoaded("jasper-el"); // JSF 2.0: tomcat-jasper-el
}
return new Jsf12ValidatingElResolver();
}
@Override
protected JsfElValidatingFaceletsParser createValidatingFaceletsParser(File webappRoot, PageNodeListener pageNodeValidator) {
return new MyFaces12ValidatingFaceletsParser(webappRoot, pageNodeValidator);
}
@Override
protected ManagedBeanFinder createManagedBeanFinder(
Collection facesConfigFilesToRead) {
return Jsf12FacesConfigXmlBeanFinder.forResources(facesConfigFilesToRead);
}
}