All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.is24.deadcode4j.analyzer.ServletContainerInitializerAnalyzer Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
package de.is24.deadcode4j.analyzer;

import com.google.common.collect.Maps;
import de.is24.deadcode4j.Analyzer;
import de.is24.deadcode4j.AnalysisContext;
import de.is24.deadcode4j.IntermediateResult;
import de.is24.deadcode4j.Module;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Map;

import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.isEmpty;

/**
 * Analyzes both web.xml and class files: looks for implementations of
 * {@link javax.servlet.ServletContainerInitializer} if the metadata-complete attribute of the
 * web-app element is missing or set to "false".
 *
 * @since 1.5
 */
public class ServletContainerInitializerAnalyzer extends AnalyzerAdapter {
    private final String depender;
    private final Analyzer classFinder;
    private final Analyzer webXmlAnalyzer = new XmlAnalyzer("web.xml") {
        @Nonnull
        @Override
        protected DefaultHandler createHandlerFor(@Nonnull final AnalysisContext analysisContext) {
            return new DefaultHandler() {
                @Override
                public void startElement(String uri, String localName, String qName, Attributes attributes)
                        throws StopParsing {
                    if ("web-app".equals(localName) && "true".equals(attributes.getValue("metadata-complete"))) {
                        ((ServletContainerInitializerAnalysisContext) analysisContext).setMetadataComplete();
                    }
                    throw new StopParsing();
                }
            };
        }
    };
    private ServletContainerInitializerAnalysisContext context;

    /**
     * Creates a new instance of ServletContainerInitializerAnalyzer.
     *
     * @param dependerId                 a description of the depending entity with which to
     *                                   call {@link de.is24.deadcode4j.AnalysisContext#addDependencies(String, Iterable)}
     * @param fqcnOfInitializerInterface the fqcn of the interface whose implementations represent a
     *                                   ServletContainerInitializer or something comparable
     */
    protected ServletContainerInitializerAnalyzer(String dependerId, String fqcnOfInitializerInterface) {
        this.depender = dependerId;
        this.classFinder = new InterfacesAnalyzer("ServletContainerInitializer-implementation", fqcnOfInitializerInterface) {
        };
    }

    public ServletContainerInitializerAnalyzer() {
        this("JEE-ServletContainerInitializer", "javax.servlet.ServletContainerInitializer");
    }

    @Override
    public void doAnalysis(@Nonnull AnalysisContext analysisContext, @Nonnull File fileName) {
        if (this.context == null) {
            this.context = new ServletContainerInitializerAnalysisContext(analysisContext.getModule());
            this.context.setOriginalContext(analysisContext);
        }
        this.webXmlAnalyzer.doAnalysis(this.context, fileName);
        this.classFinder.doAnalysis(this.context, fileName);
    }

    @Override
    public void finishAnalysis(@Nonnull AnalysisContext analysisContext) {
        ServletContainerInitializerAnalysisContext localContext = this.context;
        this.context = null;
        if (localContext == null) {
            return;
        }
        if (localContext.isMetadataComplete()) {
            logger.debug("Found web.xml with completed metadata; " +
                    "ServletContainerInitializer implementations are treated as dead code");
            return;
        }
        Iterable initializerClasses = concat(localContext.getAnalyzedCode().getCodeDependencies().values());
        if (!isEmpty(initializerClasses)) {
            analysisContext.addDependencies(depender, initializerClasses);
        }
    }

    private static class ServletContainerInitializerAnalysisContext extends AnalysisContext {

        private AnalysisContext originalContext;
        private boolean metadataComplete = false;

        private ServletContainerInitializerAnalysisContext(Module module) {
            super(module, Maps.newHashMap());
        }

        @Nonnull
        @Override
        public Map getCache() {
            return this.originalContext.getCache();
        }

        @Nullable
        @Override
        public IntermediateResult getIntermediateResult(@Nonnull Object key) {
            return this.originalContext.getIntermediateResult(key);
        }

        @Override
        public void addAnalyzedClass(@Nonnull String clazz) {
            this.originalContext.addAnalyzedClass(clazz);
        }

        public void setMetadataComplete() {
            this.metadataComplete = true;
        }

        public boolean isMetadataComplete() {
            return metadataComplete;
        }

        public void setOriginalContext(AnalysisContext analysisContext) {
            this.originalContext = analysisContext;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy