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

cdc.io.tools.XmlCheckClassRefs Maven / Gradle / Ivy

There is a newer version: 0.52.1
Show newest version
package cdc.io.tools;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import cdc.io.data.Attribute;
import cdc.io.data.Element;
import cdc.io.data.paths.SPath;
import cdc.io.data.xml.XmlDataReader;
import cdc.util.cli.AbstractMainSupport;
import cdc.util.lang.CollectionUtils;
import cdc.util.lang.FailureReaction;
import cdc.util.refs.ClassRef;
import cdc.util.refs.LazyClassRef;
import cdc.util.refs.ResolutionStatus;

/**
 * Utility used to check existence of classes in an XML file.
 *
 * @author Damien Carbonne
 *
 */
public final class XmlCheckClassRefs {
    protected static final Logger LOGGER = LogManager.getLogger(XmlCheckClassRefs.class);
    private final MainArgs margs;
    private final Set classes = new HashSet<>();
    private final Map done = new HashMap<>();

    public static class MainArgs {
        public final List input = new ArrayList<>();

        /** Set of attributes and elements to analyze. */
        public final Set paths = new HashSet<>();

        public final List jarFiles = new ArrayList<>();
    }

    private XmlCheckClassRefs(MainArgs margs) {
        this.margs = margs;
    }

    private void execute() throws IOException {
        for (final File jar : margs.jarFiles) {
            LOGGER.info("Analyze jar '{}'", jar);
            listJarClasseNames(jar);
        }

        for (final File file : margs.input) {
            LOGGER.info("Analyze xml '{}'", file);
            final Element root = XmlDataReader.loadRoot(file);
            analyze(file, root);
        }

        LOGGER.info("Valid classes");
        for (final String className : CollectionUtils.toSortedList(done.keySet())) {
            final boolean success = done.get(className);
            if (success) {
                LOGGER.info("   {}", className);
            }
        }

        LOGGER.info("Invalid classes");
        for (final String className : CollectionUtils.toSortedList(done.keySet())) {
            final boolean success = done.get(className);
            if (!success) {
                LOGGER.info("   {}", className);
            }
        }
    }

    private void listJarClasseNames(File jar) {
        LOGGER.debug("listJarClasseNames({})", jar);
        try (final ZipFile archive = new ZipFile(jar)) {
            final Enumeration iter = archive.entries();
            while (iter.hasMoreElements()) {
                final ZipEntry entry = iter.nextElement();
                final String name = entry.getName();
                if (name.endsWith(".class")) {
                    final String className = name.substring(0, name.length() - 6).replace("/", ".");
                    LOGGER.debug("   {}", className);
                    classes.add(className);
                }
            }
        } catch (final IOException e) {
            LOGGER.catching(e);
        }
    }

    private void analyze(File file,
                         Element element) {
        for (final SPath path : margs.paths) {
            if (path.matchesElement(element)) {
                final String s = element.getText(null);
                checkClassName(s, file, element.getQName());
            }
            for (final Attribute att : element.getAttributes()) {
                if (path.matchesAttribute(element, att.getName())) {
                    final String s = att.getValue();
                    checkClassName(s, file, element.getQName() + "/@" + att.getName());
                }
            }
        }
        for (final Element child : element.getElements()) {
            analyze(file, child);
        }
    }

    private void checkClassName(String className,
                                File file,
                                String location) {
        LOGGER.debug("checkClassName({}, {})", className, location);
        Boolean success = done.get(className);
        if (success == null) {
            success = resolve(className);
            done.put(className, success);
        }
        if (success != null && success) {
            LOGGER.info("{}: {}: {}: valid class name\"", file, location, className);
        } else {
            LOGGER.info("{}: {}: {}: invalid class name\"", file, location, className);
        }
    }

    /**
     * Returns {@code true} when a class name can be resolved.
     * 

* Class name is first searched in referenced jars.
* If not found, it is searched in class path. * * @param className The class name. * @return {@code true} when {@code className} can be resolved. */ private boolean resolve(String className) { if (classes.contains(className)) { return true; } else { final ClassRef ref = new LazyClassRef(className); ref.get(FailureReaction.DEFAULT); return ref.getResolutionStatus() == ResolutionStatus.SUCCESS; } } public static void execute(MainArgs margs) throws IOException { final XmlCheckClassRefs instance = new XmlCheckClassRefs(margs); instance.execute(); } public static void main(String[] args) { final MainSupport support = new MainSupport(); support.main(args); } private static class MainSupport extends AbstractMainSupport { private static final String JAR_FILE = "jar"; public MainSupport() { super(XmlCheckClassRefs.class, LOGGER); } @Override protected String getVersion() { return Config.VERSION; } @Override protected void addSpecificOptions(Options options) { options.addOption(Option.builder() .longOpt(INPUT) .desc("XML input URL(s).") .hasArgs() .required() .build()); options.addOption(Option.builder() .longOpt(JAR_FILE) .desc("Jar file(s) where classes must be searched, in addition to classes that can be accessed with class path.") .hasArgs() .build()); options.addOption(Option.builder() .longOpt(PATH) .desc("Path(s) of attributes and elements to analyze in input files.\n" + "They must match elt-name(/elt-name)* or (elt-name(/elt-name)*)@att-name.\n" + "Examples: foo, foo1/foo2, @bar, foo@bar, foo1/foo2@bar") .hasArgs() .required() .build()); } @Override protected MainArgs analyze(CommandLine cl) throws ParseException { final MainArgs margs = new MainArgs(); if (cl.getOptionValues(JAR_FILE) != null) { for (final String s : cl.getOptionValues(JAR_FILE)) { margs.jarFiles.add(new File(s)); } } if (cl.getOptionValues(INPUT) != null) { for (final String s : cl.getOptionValues(INPUT)) { margs.input.add(new File(s)); } } if (cl.hasOption(PATH)) { for (final String s : cl.getOptionValues(PATH)) { margs.paths.add(new SPath(s)); } } return margs; } @Override protected Void execute(MainArgs margs) throws Exception { XmlCheckClassRefs.execute(margs); return null; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy