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

com.buschmais.jqassistant.plugin.common.api.scanner.AbstractContainerScannerPlugin Maven / Gradle / Ivy

The newest version!
package com.buschmais.jqassistant.plugin.common.api.scanner;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.buschmais.jqassistant.core.scanner.api.Scanner;
import com.buschmais.jqassistant.core.scanner.api.ScannerContext;
import com.buschmais.jqassistant.core.scanner.api.Scope;
import com.buschmais.jqassistant.plugin.common.api.model.FileContainerDescriptor;
import com.buschmais.jqassistant.plugin.common.api.model.FileDescriptor;
import com.buschmais.jqassistant.plugin.common.api.scanner.filesystem.Resource;
import com.google.common.base.Stopwatch;

/**
 * Abstract base implementation for scanner plugins that handle containers of
 * elements like directories, archives, etc.
 * 
 * @param 
 *            The container type.
 * @param 
 *            The element type.
 * @param 
 *            The descriptor type.
 */
public abstract class AbstractContainerScannerPlugin extends AbstractResourceScannerPlugin {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractContainerScannerPlugin.class);

    @Override
    public final D scan(I container, String path, Scope scope, Scanner scanner) throws IOException {
        ScannerContext context = scanner.getContext();
        D containerDescriptor = getContainerDescriptor(container, context);
        String containerPath = getContainerPath(container, path);
        containerDescriptor.setFileName(containerPath);
        LOGGER.info("Entering {}", containerPath);
        ContainerFileResolver fileResolverStrategy = new ContainerFileResolver(containerDescriptor);
        context.push(FileResolver.class, fileResolverStrategy);
        enterContainer(container, containerDescriptor, scanner.getContext());
        Stopwatch stopwatch = Stopwatch.createStarted();
        try {
            Iterable entries = getEntries(container);
            for (E entry : entries) {
                String relativePath = getRelativePath(container, entry);
                try (Resource resource = getEntry(container, entry)) {
                    LOGGER.debug("Scanning {}", relativePath);
                    FileDescriptor descriptor = scanner.scan(resource, relativePath, scope);
                    if (descriptor != null) {
                        fileResolverStrategy.put(relativePath, descriptor);
                    }
                }
            }
        } finally {
            leaveContainer(container, containerDescriptor, scanner.getContext());
            context.pop(FileResolver.class);
        }
        fileResolverStrategy.flush();
        LOGGER.info("Leaving {} ({} entries, {} ms)", containerPath, fileResolverStrategy.size(), stopwatch.elapsed(MILLISECONDS));
        return containerDescriptor;
    }

    /**
     * Return the descriptor representing the artifact.
     * 
     * @param container
     *            The container.
     * @param scannerContext
     *            The scanner context.
     * @return The artifact descriptor.
     */
    protected abstract D getContainerDescriptor(I container, ScannerContext scannerContext);

    /**
     * Return an iterable which delivers the entries of the container.
     * 

* The entries must not contain the relative root element, i.e. "/". *

* * @param container * The container. * @return The iterable of entries. * @throws IOException * If the entries cannot be determined. */ protected abstract Iterable getEntries(I container) throws IOException; /** * Return the normalized path to the container. * * @param container * The container. * @return The normalized path. */ protected abstract String getContainerPath(I container, String path); /** * Return the relative path of an element within the container. *

* The following conditions must be considered: *

    *
  • The separator to use is "/".
  • *
  • The path must start with "/".
  • *
  • The path must not end with "/".
  • *
* *

* * @param container * The container. * @param entry * The entry. * @return The relative path. */ protected abstract String getRelativePath(I container, E entry); /** * Create a scope depending on the container type, e.g. a JAR file should * return classpath scope. * * @param container * The container. * @param containerDescriptor * The container descriptor. * @param scannerContext * The scanner context. */ protected abstract void enterContainer(I container, D containerDescriptor, ScannerContext scannerContext) throws IOException; /** * Destroy the container dependent scope. * * @param container * The container. * @param containerDescriptor * The container descriptor * @param scannerContext * The scanner context. */ protected abstract void leaveContainer(I container, D containerDescriptor, ScannerContext scannerContext) throws IOException; /** * Return a {@link Resource} representing an entry. * * @param container * The container. * @param entry * The entry. * @return The * {@link com.buschmais.jqassistant.plugin.common.api.scanner.filesystem.FileResource} * . */ protected abstract Resource getEntry(I container, E entry); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy