Package org.geotools.gce.imagemosaic

Source Code of org.geotools.gce.imagemosaic.ImageMosaicWalker

package org.geotools.gce.imagemosaic;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageIO;
import javax.imageio.spi.ImageInputStreamSpi;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;

import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.FilenameUtils;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.coverage.grid.io.UnknownFormat;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.factory.Hints;
import org.geotools.image.io.ImageIOExt;
import org.geotools.util.Utilities;

/**
* This class is responsible for walking through the files inside a directory (and its children directories) which respect a specified wildcard.
*
* <p>
* Its role is basically to simplify the construction of the mosaic by implementing a visitor pattern for the files that we have to use for the index.
*
* <p>
* It is based on the Commons IO {@link DirectoryWalker} class.
*
* @author Simone Giannecchini, GeoSolutions SAS
* @author Daniele Romagnoli, GeoSolutions SAS
* @author Carlo Cancellieri, GeoSolutions SAS
*
*/
abstract class ImageMosaicWalker implements Runnable {

    /** Default Logger * */
    final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(ImageMosaicWalker.class);

    private DefaultTransaction transaction;

    private static Set<String> logExcludes = new HashSet<String>();

    static {
        logExcludes.add("xml");
        logExcludes.add("properties");
    }

    /**
     * Proper way to stop a thread is not by calling Thread.stop() but by using a shared variable that can be checked in order to notify a terminating
     * condition.
     */
    private volatile boolean stop = false;

    protected final ImageMosaicConfigHandler configHandler;

    protected final Hints excludeMosaicHints = new Hints(Utils.EXCLUDE_MOSAIC, true);

    private AbstractGridFormat cachedFormat;

    /**
     * index of the file being processed
     */   
    private int fileIndex = 0;

    /** Number of files to process. */
    private int numFiles = 1;

    protected final ImageMosaicEventHandlers eventHandler;

    /**
     * @param updateFeatures if true update catalog with loaded granules
     * @param imageMosaicConfigHandler TODO
     */
    public ImageMosaicWalker(ImageMosaicConfigHandler configHandler,
            ImageMosaicEventHandlers eventHandler) {
        Utilities.ensureNonNull("config handler", configHandler);
        Utilities.ensureNonNull("event handler", eventHandler);
       
        this.configHandler = configHandler;
        this.eventHandler = eventHandler;

    }

    public boolean getStop() {
        return stop;
    }

    public void stop() {
        stop = true;
    }

    protected boolean checkFile(final File fileBeingProcessed) {
        if (!fileBeingProcessed.exists() || !fileBeingProcessed.canRead()
                || !fileBeingProcessed.isFile()) {
            return false;
        }
        return true;
    }

    protected void handleFile(final File fileBeingProcessed) throws IOException {

        // increment counter
        fileIndex++;

        //
        // Check that this file is actually good to go
        //
        if (!checkFile(fileBeingProcessed))
            return;

        // replacing chars on input path
        String validFileName;
        String extension;
        try {
            validFileName = fileBeingProcessed.getCanonicalPath();
            validFileName = FilenameUtils.normalize(validFileName);
            extension = FilenameUtils.getExtension(validFileName);
        } catch (IOException e) {
            eventHandler.fireFileEvent(
                    Level.FINER,
                    fileBeingProcessed,
                    false,
                    "Exception occurred while processing file " + fileBeingProcessed + ": "
                            + e.getMessage(), ((fileIndex * 100.0) / numFiles));
            eventHandler.fireException(e);
            return;
        }
        validFileName = FilenameUtils.getName(validFileName);
        eventHandler.fireEvent(Level.INFO, "Now indexing file " + validFileName,
                ((fileIndex * 100.0) / numFiles));
        GridCoverage2DReader coverageReader = null;
        try {
            // STEP 1
            // Getting a coverage reader for this coverage.
            //
            final AbstractGridFormat format;
            if (cachedFormat == null) {
                // When looking for formats which may parse this file, make sure to exclude the ImageMosaicFormat as return
                format = (AbstractGridFormat) GridFormatFinder.findFormat(fileBeingProcessed,
                        excludeMosaicHints);
            } else {
                if (cachedFormat.accepts(fileBeingProcessed)) {
                    format = cachedFormat;
                } else {
                    format = new UnknownFormat();
                }
            }
            if ((format instanceof UnknownFormat) || format == null) {
                if (!logExcludes.contains(extension)) {
                    eventHandler.fireFileEvent(Level.INFO, fileBeingProcessed, false, "Skipped file "
                            + fileBeingProcessed + ": File format is not supported.",
                            ((fileIndex * 99.0) / numFiles));
                }
                return;
            }
            cachedFormat = format;

            final Hints configurationHints = configHandler.getRunConfiguration().getHints();
            coverageReader = (GridCoverage2DReader) format.getReader(fileBeingProcessed,
                    configurationHints);

            // Setting of the ReaderSPI to use
            if(configHandler.getCachedReaderSPI() == null){
                // Get the URL associated to the file
                URL granuleUrl = DataUtilities
                        .fileToURL(fileBeingProcessed);
                // Get the ImageInputStreamSPI associated to the URL
                ImageInputStreamSpi inStreamSpi = Utils.getInputStreamSPIFromURL(granuleUrl);
                // Ensure that the ImageInputStreamSPI is available
                if(inStreamSpi==null){
                    throw new IllegalArgumentException("no inputStreamSPI available!");
                }
                ImageInputStream inStream=null;
                try{
                    // Get the ImageInputStream from the SPI
                    inStream = inStreamSpi
                            .createInputStreamInstance(granuleUrl, ImageIO.getUseCache(),
                                    ImageIO.getCacheDirectory());
                    // Throws an Exception if the ImageInputStream is not present
                    if(inStream == null){
                        if(LOGGER.isLoggable(Level.WARNING)){
                            LOGGER.log(Level.WARNING,Utils.getFileInfo(fileBeingProcessed));
                        }
                        throw new IllegalArgumentException("Unable to get an input stream for the provided file "+granuleUrl.toString());
                    }
                    // Selection of the ImageReaderSpi from the Stream
                    ImageReaderSpi spi = Utils.getReaderSpiFromStream(null, inStream);
                    // Setting of the ImageReaderSpi to the ImageMosaicConfigHandler in order to set it inside the indexer properties
                    configHandler.setCachedReaderSPI(spi);
                }finally{
                    if(inStream!=null){
                        inStream.close();
                    }
                }

            }

            // Getting available coverageNames from the reader
            String[] coverageNames = coverageReader.getGridCoverageNames();

            for (String cvName : coverageNames) {

                configHandler.updateConfiguration(coverageReader, cvName, fileBeingProcessed,
                        fileIndex, numFiles, transaction);

                // fire event
                eventHandler.fireFileEvent(Level.FINE, fileBeingProcessed, true, "Done with file "
                        + fileBeingProcessed, (((fileIndex + 1) * 99.0) / numFiles));

            }
        } catch (Exception e) {
            eventHandler.fireException(e);
            return;
        } finally {
            //
            // STEP 5
            //
            // release resources
            //
            try {
                if (coverageReader != null)
                    // release resources
                    coverageReader.dispose();
            } catch (Throwable e) {
                // ignore exception
                if (LOGGER.isLoggable(Level.FINEST))
                    LOGGER.log(Level.FINEST, e.getLocalizedMessage(), e);
            }
        }

    }
   
    /**
     * Create a transaction for being used in this walker
     */
    public void startTransaction(){
        if(transaction!=null){
            throw new IllegalStateException("Transaction already open!");
        }
        this.transaction = new DefaultTransaction("MosaicCreationTransaction"+ System.nanoTime());
    }
   
    public void rollbackTransaction() throws IOException{
        transaction.rollback();
    }
   
    public void commitTransaction() throws IOException{
        transaction.commit();
    }
   
    public void closeTransaction(){
        transaction.close();
    }

    protected boolean checkStop() {
        if (getStop()) {
            eventHandler.fireEvent(Level.INFO, "Stopping requested at file  " + fileIndex
                    + " of " + numFiles + " files", ((fileIndex * 100.0) / numFiles));
            return false;
        }
        return true;
    }

    /**
     * @return the fileIndex
     */
    public int getFileIndex() {
        return fileIndex;
    }

    /**
     * @return the numFiles
     */
    public int getNumFiles() {
        return numFiles;
    }

    /**
     * @param fileIndex the fileIndex to set
     */
    public void setFileIndex(int fileIndex) {
        this.fileIndex = fileIndex;
    }

    /**
     * @param numFiles the numFiles to set
     */
    public void setNumFiles(int numFiles) {
        this.numFiles = numFiles;
    }

    /**
     * Warn this walker that we skip the provided path
     * @param path the path to the file to skip
     *
     */
    public void skipFile(String path) {
        LOGGER.log(Level.INFO,"Unable to use path: "+path+" - skipping it.");
        fileIndex++;
       
    }

}
TOP

Related Classes of org.geotools.gce.imagemosaic.ImageMosaicWalker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.