0,0 → 1,369 |
/* |
* 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.configuration.ConfigurationException; |
import org.apache.commons.configuration.PropertiesConfiguration; |
import org.apache.jcs.JCS; |
import org.apache.jcs.access.exception.CacheException; |
import org.apache.log4j.Logger; |
|
/** |
* @author Brian Rosenberger, bru(at)brutex.de |
* |
*/ |
|
public class FindingsCacheServlet extends HttpServlet { |
|
private static final long serialVersionUID = 4041338473949999960L; |
private final static Logger logger = Logger |
.getLogger(FindingsCacheServlet.class); |
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, Logger.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"); |
} |
|
PropertiesConfiguration config = null; |
try { |
config = new PropertiesConfiguration(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(); |
} |
|
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |