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

src.gov.nasa.worldwind.formats.rpf.RPFCrawler Maven / Gradle / Ivy

/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.formats.rpf;

import gov.nasa.worldwind.util.Logging;

import java.io.*;
import java.util.*;
import java.util.concurrent.locks.*;
import static java.util.logging.Level.FINE;

/**
 * @author dcollins
 * @version $Id: RPFCrawler.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class RPFCrawler
{
    public static final String RPF_DIRECTORY = "RPF";
    public static final String RPF_OVERVIEW_EXTENSION = ".OVR";
    public static final String RPF_TOC_EXTENSION = ".TOC";

    public static interface RPFCrawlerListener
    {
        void fileFound(File file, boolean isTOCFile);

        void finished();
    }

    public abstract static class RPFGrouper implements RPFCrawlerListener
    {
        private final RPFFrameProperty groupType;

        public RPFGrouper(RPFFrameProperty groupType)
        {
            if (groupType == null)
            {
                String message = Logging.getMessage("nullValue.RPFFramePropertyTypeIsNull");
                Logging.logger().fine(message);
                throw new IllegalArgumentException(message);
            }
            this.groupType = groupType;
        }

        public abstract void addToGroup(Object groupKey, File rpfFile, RPFFrameFilename rpfFrameFilename);

        public void fileFound(File file, boolean isTOCFile)
        {
            if (isTOCFile)
                fileFoundTOC(file);
            else
                fileFoundRPF(file);
        }

        private void fileFoundTOC(File file)
        {
            RPFTOCFile rpftocFile = null;
            try
            {
                rpftocFile = RPFTOCFile.load(file);
            }
            catch (IOException e)
            {
                Logging.logger().fine(e.getMessage());
            }

            if (rpftocFile == null)
                return;

            List rpfRecords = extractRPFRecords(rpftocFile);
            if (rpfRecords == null || rpfRecords.isEmpty())
                return;

            RPFFrameFilename firstFrameFilename = null;
            try
            {
                firstFrameFilename = RPFFrameFilename.parseFilename(rpfRecords.get(0).getFrameFileName());
            }
            catch (Exception e)
            {
                String message = Logging.getMessage("RPFCrawler.ExceptionParsingFilename", file.getPath());
                Logging.logger().log(FINE, message, e);
            }

            if (firstFrameFilename == null)
                return;

            Object groupKey = this.groupType.getValue(firstFrameFilename);
            for (RPFFrameFileIndexSection.RPFFrameFileIndexRecord record : rpfRecords)
            {
                String filePath = createAbsolutePath(file.getParentFile().getAbsolutePath(), record.getPathname(),
                    record.getFrameFileName());
                RPFFrameFilename rpfFrameFilename = rpfFrameFilenameFor(file);
                this.addToGroup(groupKey, new File(filePath), rpfFrameFilename);
            }
        }

        private void fileFoundRPF(File file)
        {
            RPFFrameFilename rpfFrameFilename = rpfFrameFilenameFor(file);
            if (rpfFrameFilename == null)
                return;
            Object groupKey = this.groupType.getValue(rpfFrameFilename);
            this.addToGroup(groupKey, file, rpfFrameFilename);
        }

        public void finished()
        {
        }

        private RPFFrameFilename rpfFrameFilenameFor(File file)
        {
            RPFFrameFilename rpfFrameFilename = null;
            try
            {
                rpfFrameFilename = RPFFrameFilename.parseFilename(file.getName().toUpperCase());
            }
            catch (Exception e)
            {
                String message = Logging.getMessage("RPFCrawler.ExceptionParsingFilename", file.getPath());
                Logging.logger().log(FINE, message, e);
            }
            return rpfFrameFilename;
        }
    }

    private static class RPFRunner implements Runnable
    {
        private final RPFCrawler context;
        private final File directory;
        private final RPFCrawlerListener listener;
        private final boolean tocFileSearch;

        public RPFRunner(RPFCrawler context, File directory, RPFCrawlerListener listener, boolean tocFileSearch)
        {
            this.context = context;
            this.directory = directory;
            this.listener = listener;
            this.tocFileSearch = tocFileSearch;
        }

        public void run()
        {
            this.context.process(this.directory, listener, tocFileSearch, true);
            this.context.threadLock.lock();
            try
            {
                if (this.context.thread != this.context.deadThread)
                {
                    listener.finished();
                    this.context.thread = this.context.deadThread;
                }
            }
            finally
            {
                this.context.threadLock.unlock();
            }
        }
    }

    private final Thread deadThread = new Thread();
    private final Lock threadLock = new ReentrantLock();
    private volatile Thread thread = null;

    public RPFCrawler()
    {
    }

    private static String createAbsolutePath(String... pathElem)
    {
        StringBuilder sb = new StringBuilder();
        for (String str : pathElem)
        {
            if (str != null && str.length() > 0)
            {
                int startIndex = 0;
                if (str.startsWith("./") || str.startsWith(".\\"))
                    startIndex = 1;
                else if (!str.startsWith("/") && !str.startsWith("\\"))
                    sb.append(File.separatorChar);
                int endIndex;
                if (str.endsWith("/") || str.endsWith("\\"))
                    endIndex = str.length() - 1;
                else
                    endIndex = str.length();
                sb.append(str, startIndex, endIndex);
            }
        }
        if (sb.length() <= 0)
            return null;
        return sb.toString();
    }

    private static List extractRPFRecords(RPFTOCFile tocFile)
    {
        List rpfFiles
            = new LinkedList();
        if (tocFile != null
            && tocFile.getFrameFileIndexSection() != null
            && tocFile.getFrameFileIndexSection().getFrameFileIndexTable() != null
            && tocFile.getFrameFileIndexSection().getFrameFileIndexTable().size() > 0)
        {
            for (RPFFrameFileIndexSection.RPFFrameFileIndexRecord frameFileIndexRecord
                : tocFile.getFrameFileIndexSection().getFrameFileIndexTable())
            {
                if (frameFileIndexRecord != null
                    && frameFileIndexRecord.getFrameFileName() != null
                    && !frameFileIndexRecord.getFrameFileName().toUpperCase().endsWith(RPF_OVERVIEW_EXTENSION))
                {
                    rpfFiles.add(frameFileIndexRecord);
                }
            }
        }
        return rpfFiles;
    }

    private static boolean isRPFDirectory(File file)
    {
        return RPF_DIRECTORY.compareToIgnoreCase(file.getName()) == 0;
    }

    private static boolean isRPFFile(File file)
    {
        return RPFFrameFilename.isFilename(file.getName().toUpperCase());
    }

    private static boolean isTOCFile(File file)
    {
        return file.getName().toUpperCase().endsWith(RPF_TOC_EXTENSION);
    }

    private void process(File file, RPFCrawlerListener listener, boolean tocFileSearch, boolean inOwnThread)
    {
        this.threadLock.lock();
        try
        {
            if (inOwnThread && this.thread == deadThread)
                return;
        }
        finally
        {
            this.threadLock.unlock();
        }

        File[] children = file.listFiles();
        if (tocFileSearch)
        {
            if (children == null)
                return;
            if (isRPFDirectory(file))
                this.searchForTOC(children, listener, inOwnThread);
            else
                this.searchForDirectory(children, listener, true, inOwnThread);
        }
        else
        {
            if (RPFFrameFilename.isFilename(file.getName().toUpperCase()))
                listener.fileFound(file, false);
            if (children == null)
                return;
            this.searchForRPF(children, listener, inOwnThread);
        }
    }

    private void searchForTOC(File[] contents, RPFCrawlerListener listener, boolean inOwnThread)
    {
        for (File file : contents)
        {
            this.threadLock.lock();
            try
            {
                if (inOwnThread && this.thread == deadThread)
                    return;
            }
            finally
            {
                this.threadLock.unlock();
            }

            if (isTOCFile(file))
                listener.fileFound(file, true);
        }
    }

    private void searchForDirectory(File[] contents, RPFCrawlerListener listener, boolean tocFileSearch,
        boolean inOwnThread)
    {
        for (File file : contents)
        {
            this.threadLock.lock();
            try
            {
                if (inOwnThread && this.thread == deadThread)
                    return;
            }
            finally
            {
                this.threadLock.unlock();
            }

            if (file.isDirectory())
                this.process(file, listener, tocFileSearch, inOwnThread);
        }
    }

    private void searchForRPF(File[] contents, RPFCrawlerListener listener, boolean inOwnThread)
    {
        for (File file : contents)
        {
            this.threadLock.lock();
            try
            {
                if (inOwnThread && this.thread == deadThread)
                    return;
            }
            finally
            {
                this.threadLock.unlock();
            }

            if (isRPFFile(file))
                listener.fileFound(file, false);
            else if (file.isDirectory())
                this.process(file, listener, false, inOwnThread);
        }
    }

    public File[] invoke(File directory, boolean tocFileSearch)
    {
        File validDir = this.validateDirectory(directory);
        final Collection results = new ArrayList();
        this.process(validDir, new RPFCrawlerListener()
        {
            public void fileFound(File file, boolean isTOCFile)
            {
                if (file.exists())
                    results.add(file);
            }

            public void finished()
            {
            }
        }, tocFileSearch, false);
        File[] tocFileArray = new File[results.size()];
        results.toArray(tocFileArray);
        return tocFileArray;
    }

    public void invoke(File directory, RPFCrawlerListener listener, boolean tocFileSearch)
    {
        File validDir = this.validateDirectory(directory);
        this.process(validDir, listener, tocFileSearch, false);
    }

    public void start(File directory, RPFCrawlerListener listener, boolean tocFileSearch)
    {
        this.threadLock.lock();
        try
        {
            if (this.thread != null || this.thread == deadThread)
            {
                String message = Logging.getMessage("RPFCrawler.BadStart");
                Logging.logger().fine(message);
                throw new IllegalStateException(message);
            }
            File validDir = this.validateDirectory(directory);
            this.thread = new Thread(new RPFRunner(this, validDir, listener, tocFileSearch));
            this.thread.start();
        }
        finally
        {
            this.threadLock.unlock();
        }
    }

    public void stop()
    {
        this.threadLock.lock();
        try
        {
            this.thread = deadThread;
        }
        finally
        {
            this.threadLock.unlock();
        }
    }

    private File validateDirectory(File directory)
    {
        if (directory == null)
        {
            String message = Logging.getMessage("nullValue.FileIsNull");
            Logging.logger().fine(message);
            throw new IllegalArgumentException(message);
        }
        String path = directory.getAbsolutePath();
        if (!path.endsWith("/") && !path.endsWith("\\"))
        {
            path = path + File.separatorChar;
            directory = new File(path);
        }
        if (!directory.exists())
        {
            String message = Logging.getMessage("generic.FileNotFound", directory.getPath());
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        return directory;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy