Subversion Repositories XServices

Rev

Rev 184 | Blame | Last modification | View Log | Download | RSS feed

/*
 *   Copyright 2013 Brian Rosenberger (Brutex Network)
 *
 *   Licensed 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 net.brutex.xservices.util.cache;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.ws.rs.core.Response;
import net.brutex.xservices.types.scm.ItemListType;
import net.brutex.xservices.types.scm.ItemType;
import net.brutex.xservices.types.scmfindings.FindingDetailsType;
import net.brutex.xservices.types.scmfindings.FindingType;
import net.brutex.xservices.types.scmfindings.FindingsListType;
import net.brutex.xservices.types.scmfindings.GroupMatchListType;
import net.brutex.xservices.types.scmfindings.ObjectFactory;
import net.brutex.xservices.ws.rs.CVSInfoImpl;

import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.jcs.access.exception.CacheException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * @author Brian Rosenberger, bru(at)brutex.de
 * 
 */

public class FindingsCacheServlet extends HttpServlet {

        private static final long serialVersionUID = 4041338473949999960L;
        private static final Logger logger = LogManager.getLogger();
        private final List<File> configfiles = new ArrayList<File>();
        private final ObjectFactory FACTORY = new ObjectFactory();
        private ExecutorService executor;

        @Override
        public void init() throws ServletException {
                super.init();
                executor = (ExecutorService) getServletContext()
                                .getAttribute("CACHE_EXECUTOR");
                
                if(! this.initConfigList()) return;
                if(! this.initConfigFindings()) return;

                int i = 1;
                for(File f: configfiles) {
                        //Initialise configuration bean using default values
                        FindingsConfigBean cbean = new FindingsConfigBean(i, LogManager.getLogger("worker-"+i+ "." + this.getClass().getName()));
                        i++;
                        
                        
                        
                        //Read cvs-cache-interval parameter
                        try {
                                int cacheinterval = Integer.parseInt(getServletContext()
                                                .getInitParameter("cvs-cache-interval"));
                                cbean.setCacheinterval(cacheinterval);
                                logger.info("FindingsCacheServlet set to "+ cacheinterval + " minutes interval.");
                        } catch (NumberFormatException e) {
                                 logger.warn("Could not read parameter 'cvs-cache-interval' from web.xml. Using default value '"
                                                + cbean.getCacheinterval()+ "' minutes");
                        }
                        
                        Configurations configs = new Configurations();
                        PropertiesConfiguration config = null;
                        try {
                                config = configs.properties(f);
                        } catch (ConfigurationException e) {
                                logger.error("Could not read parameter file at '"+f.getAbsolutePath()+"'");
                                return;
                        }
                        
                                        
                        File cvsconfig = new File(config.getString("CVSROOTCONFIGFILE"));
                        cbean.setCvsconfig(cvsconfig);
                        FindingsCacheServlet.logger.debug("Fetching list of files using '"
                                        + cvsconfig.getAbsolutePath() + "' config file");
                        
                        
                        List<Object> filepatterns = config.getList("FILESEARCH");
                        cbean.setFilepatterns(filepatterns);
                        FindingsCacheServlet.logger.debug("Checking '"
                                        + filepatterns.size()
                                        + "' patterns for file name and path matching.");
                        
                        
                        List<Object> contentpatterns = config.getList("CONTENTSEARCH");
                        cbean.setContentpatterns(contentpatterns);
                        FindingsCacheServlet.logger.debug("Checking '"
                                        + contentpatterns.size()
                                        + "' patterns for content matching");
                        

                        
                        
                        executor.submit(new ThisRunnable(cbean));
                        
                }
                logger.info("FindingsCacheServlet has been initialized.");

        }
        
        /*
         * Initialise CVS findings configuration
         */
        private boolean initConfigFindings() {
                String filename = getServletContext().getInitParameter(
                                "cvs-findings-configuration");
                if (filename == null) {
                        logger.warn("'cvs-findings-configuration' init parameter is not specified.");
                        return false;
                }
                final File findingsconfig = new File(filename);
                logger.info("CVS findings configuration file found at '"
                                + findingsconfig.getAbsolutePath() + "'");
                if ((!findingsconfig.canRead()) || (findingsconfig.isDirectory())) {
                        logger.info("CVS findings configuration file '"
                                        + findingsconfig.getAbsolutePath() + "' does not exist.");
                        return false;
                }
                return true;
        }

        /*
         * Add all specified CVS configuration files to the list. Parameter pattern
         * is "cvs-config-XX".
         */
        private boolean initConfigList() {
                Enumeration<String> attributes = getServletContext()
                                .getInitParameterNames();
                while (attributes.hasMoreElements()) {
                        String name = (String) attributes.nextElement();
                        if (name.startsWith("cvs-config-")) {
                                String configfile = getServletContext().getInitParameter(name);
                                logger.info("Adding CVS configuration file: " + configfile);
                                this.configfiles.add(new File(configfile));
                        }
                }
                /*
                 * Verify, that all configuration files do exists and are readable.
                 */
                List<File> removelist = new ArrayList<File>();
                for (File f : configfiles) {
                        if (!f.exists()) {
                                logger.warn("CVS configuration file '"
                                                + f.getAbsolutePath()
                                                + "' is specified, but does not exist. Removing from list.");
                                removelist.add(f);
                        } else if (!f.canRead()) {
                                logger.warn("CVS configuration file '"
                                                + f.getAbsolutePath()
                                                + "' does exist, but is not readable. Removing from list.");
                                removelist.add(f);
                        }
                }
                configfiles.removeAll(removelist);
                return true;
        }

        
        
        
        class ThisRunnable implements Runnable {
                boolean isInterrupted = false;
                FindingsConfigBean configuration;

                public ThisRunnable(FindingsConfigBean configuration) {
                        this.configuration = configuration;
                }

                public void run() {
                        CVSInfoImpl instance = new CVSInfoImpl();

                        ItemListType fileslist = (ItemListType) instance
                                        .getRepositoryFiles(null, configuration.getCvsconfig(), "", true, true, true)
                                        .getEntity();
                        ObjectFactory FACTORY = new ObjectFactory();
                        FindingsListType findingsList = FACTORY.createFindingsListType();

                        FindingsCacheServlet.logger.info("Processing '"
                                        + fileslist.getItems().size() + "' files and directories.");

                        while (!this.isInterrupted) {
                                Pattern p;
                                for (ItemType i : fileslist.getItems()) {
                                        if (this.isInterrupted)
                                                break;
                                        Iterator<Object> iterF = configuration.getFilepatterns().iterator();
                                        while(iterF.hasNext()) {
                                                Object o = iterF.next();
                                                if (this.isInterrupted)
                                                        break;
                                                FindingsCacheServlet.logger.debug("Scanning filename '"
                                                                + i.getFullname() + "' for pattern '"
                                                                + (String) o + "'");
                                                p = Pattern.compile((String) o);
                                                Matcher m = p.matcher(i.getFullname());
                                                if (m.find()) {
                                                        FindingType finding = FACTORY.createFindingType();
                                                        finding.setFilesearch(p.toString());
                                                        ItemType it = (ItemType) instance.getFileContent(
                                                                        null, configuration.getCvsconfig(), i.getFullname(), true)
                                                                        .getEntity();
                                                        finding.setContent(it.getContent());
                                                        finding.setData(it.getData());
                                                        finding = copyDetails(finding, i);
                                                        findingsList.getFindings().add(finding);
                                                        FindingsCacheServlet.logger
                                                                        .debug("Match found for '"
                                                                                        + i.getFullname() + "'");
                                                        break;
                                                }
                                                FindingsCacheServlet.logger
                                                                .debug("No match found for '" + i.getFullname()
                                                                                + "'");
                                        }
                                }
                                FindingsCacheServlet.logger
                                                .debug("Processing file content for '"
                                                                + findingsList.getFindings().size()
                                                                + "' entries in the list.");

                                for (FindingType t : findingsList.getFindings()) {
                                        if (this.isInterrupted)
                                                break;
                                        boolean isFound = false;
                                        Matcher m;
                                        Iterator<Object> iter = configuration.getContentpatterns().iterator();
                                        while (iter.hasNext()) {

                                                Object o = iter.next();
                                                if (this.isInterrupted)
                                                        break;
                                                FindingsCacheServlet.logger
                                                                .debug("Scanning file content for file '"
                                                                                + t.getFullname() + "' for pattern '"
                                                                                + (String) o + "'");

                                                Pattern p1 = Pattern.compile((String) o);
                                                m = p1.matcher(t.getContent());
                                                t.setContentsearch(p1.toString());

                                                isFound = true;
                                                int s = m.start();
                                                int e = m.end();
                                                String c = m.group();

                                                FindingDetailsType fd = FACTORY
                                                                .createFindingDetailsType();
                                                GroupMatchListType gm = FACTORY
                                                                .createGroupMatchListType();
                                                gm.setMatchAtIndex(s);
                                                gm.setMatchToIndex(e);
                                                gm.setMatchString(c);
                                                gm.setMatchGroup(0);
                                                fd.setFullmatch(gm);
                                                for (int i = 1; i <= m.groupCount(); i++) {
                                                        GroupMatchListType gmg = FACTORY
                                                                        .createGroupMatchListType();
                                                        s = m.start(i);
                                                        e = m.end(i);
                                                        c = m.group(i);
                                                        gmg.setMatchAtIndex(s);
                                                        gmg.setMatchToIndex(e);
                                                        gmg.setMatchString(c);
                                                        gmg.setMatchGroup(i);
                                                        fd.getMatchLists().add(gmg);
                                                }
                                                t.getFindingLists().add(fd);
                                                FindingsCacheServlet.logger
                                                                .debug("Found matching content at index '" + s
                                                                                + "' in file '" + t.getFullname()
                                                                                + "' with pattern '" + p1.toString()
                                                                                + "'");
                                        }

                                        if (!isFound) {
                                                findingsList.getFindings().remove(t);
                                                FindingsCacheServlet.logger
                                                                .debug("Found matching filename for '"
                                                                                + t.getFullname()
                                                                                + "' but content didn't match. Removing.");
                                        }

                                        try {
                                                instance.getCacheInstance().put(
                                                                "FINDINGS-" + t.getROOT(), findingsList);
                                                FindingsCacheServlet.logger
                                                                .info("FINDINGS for CVSROOT '" + t.getROOT()
                                                                                + "' have been updated in cache.");
                                        } catch (CacheException e) {
                                                FindingsCacheServlet.logger.error(e.getMessage(), e);
                                        }
                                }
                                try {
                                        int cacheinterval = configuration.getCacheinterval();
                                        FindingsCacheServlet.logger.debug("Now sleeping for '"
                                                        + cacheinterval + "' minutes");
                                        Thread.currentThread();
                                        Thread.sleep(cacheinterval * 60000);
                                        FindingsCacheServlet.logger.debug("Waking up after '"
                                                        + cacheinterval + "' minutes of sleep");
                                } catch (InterruptedException e) {
                                        this.isInterrupted = true;
                                        FindingsCacheServlet.logger
                                                        .warn("FindingsCacheServlet cache was interrupted. Shutting down.");
                                }
                        }

                }

                private FindingType copyDetails(FindingType finding, ItemType item) {
                        finding.setDescription(item.getDescription());
                        finding.setFullname(item.getFullname());
                        finding.setName(item.getName());
                        finding.setPath(item.getPath());
                        finding.setRemotefullname(item.getRemotefullname());
                        finding.setRemotename(item.getRemotename());
                        finding.setRemotepath(item.getRemotepath());
                        finding.setROOT(item.getROOT());
                        return finding;
                }

        }




        /* (non-Javadoc)
         * @see javax.servlet.GenericServlet#destroy()
         */
        @Override
        public void destroy() {
                // TODO Auto-generated method stub
                executor.shutdown();
                try {
                        executor.awaitTermination(3, TimeUnit.SECONDS);
                        logger.info("Cache Worker Threads have shut down.");
                } catch (InterruptedException e) {
                        logger.error("Cache Worker Threads did not terminate within timeout.", e);
                }
                super.destroy();
        }
        
}

Generated by GNU Enscript 1.6.5.90.