com.ilscipio.scipio.common.FileListener.java Source code

Java tutorial

Introduction

Here is the source code for com.ilscipio.scipio.common.FileListener.java

Source

/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package com.ilscipio.scipio.common;

import java.io.IOException;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.commons.io.FilenameUtils;
import org.ofbiz.base.concurrent.ExecutionPool;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilURL;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.DelegatorFactory;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ServiceContainer;

/**
 * Scipio File Listener
 * 
 * Implementes WatchService for specific directories and triggers service based on events
 *
 */
public class FileListener {

    public static final String module = FileListener.class.getName();
    private static final ThreadGroup FILE_LISTENER_THREAD_GROUP = new ThreadGroup("WatchServices");
    private static final Delegator delegator = DelegatorFactory.getDelegator("default");
    private static final LocalDispatcher dispatcher = ServiceContainer
            .getLocalDispatcher(delegator.getDelegatorName(), delegator);

    /**
     *  Start a file listener (WatchService) and run a service of a given name and writes the result to the database
     *  Can be used to implements EECAs to auto-update information based on file changes
     **/
    public static void startFileListener(String name, String location) {

        try {
            if (UtilValidate.isNotEmpty(name) && UtilValidate.isNotEmpty(location)) {

                if (getThreadByName(name) != null) {
                    Debug.logInfo("Filelistener " + name + " already started. Skipping...", module);
                } else {
                    URL resLocation = UtilURL.fromResource(location);
                    Path folderLocation = Paths.get(resLocation.toURI());
                    if (folderLocation == null) {
                        throw new UnsupportedOperationException("Directory not found");
                    }

                    final WatchService folderWatcher = folderLocation.getFileSystem().newWatchService();
                    // register all subfolders
                    Files.walkFileTree(folderLocation, new SimpleFileVisitor<Path>() {
                        @Override
                        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                                throws IOException {
                            dir.register(folderWatcher, StandardWatchEventKinds.ENTRY_CREATE,
                                    StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
                            return FileVisitResult.CONTINUE;
                        }
                    });

                    // start the file watcher thread below
                    ScipioWatchQueueReader fileListener = new ScipioWatchQueueReader(folderWatcher, name, location);
                    ScheduledExecutorService executor = ExecutionPool.getScheduledExecutor(
                            FILE_LISTENER_THREAD_GROUP, "filelistener-startup",
                            Runtime.getRuntime().availableProcessors(), 0, true);
                    try {
                        executor.submit(fileListener, name);
                    } finally {
                        executor.shutdown();
                    }
                    Debug.logInfo("Starting FileListener thread for " + name, module);
                }
            }
        } catch (Exception e) {
            Debug.logError("Could not start FileListener " + name + " for " + location + "\n" + e, module);

        }
    }

    /**
     * Runnable used to listen for file changes and interpret the result
     * 
     * */
    private static class ScipioWatchQueueReader implements Runnable {

        private WatchService scipioWatcher;
        private String eventName, eventRoot;

        public ScipioWatchQueueReader(WatchService scipioWatcher, String eventName, String eventRoot) {
            this.scipioWatcher = scipioWatcher;
            this.eventName = eventName;
            this.eventRoot = eventRoot;
        }

        @Override
        public void run() {
            try {
                WatchKey key = scipioWatcher.take();
                while (key != null) {
                    for (WatchEvent<?> event : key.pollEvents()) {
                        GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin")
                                .where("userLoginId", "system").queryOne();
                        final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) event;
                        final Path filename = watchEventPath.context();
                        Path dir = (Path) key.watchable();
                        Path fullPath = dir.resolve(filename);
                        String fileType = Files.probeContentType(fullPath);
                        if (UtilValidate.isEmpty(fileType))
                            fileType = FilenameUtils.getExtension(fullPath.toString());
                        dispatcher.runSync("triggerFileEvent",
                                UtilMisc.toMap("fileEvent", "" + event.kind(), "fileLocation", "" + fullPath,
                                        "fileType", fileType, "eventName", eventName, "eventRoot", eventRoot,
                                        "userLogin", userLogin));
                    }
                    key.reset();
                    key = scipioWatcher.take();
                }
            } catch (Exception e) {
                Debug.logWarning("Could not fire FileListener Event" + e, module);
            }
        }
    }

    public static Thread getThreadByName(String threadName) {
        for (Thread t : Thread.getAllStackTraces().keySet()) {
            if (t.getName().equals(threadName))
                return t;
        }
        return null;
    }
}