/******************************************************************************* * Copyright (c) 2011 Subgraph. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subgraph - initial API and implementation ******************************************************************************/ package com.subgraph.vega.impl.scanner.modules; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import com.subgraph.vega.api.events.IEvent; import com.subgraph.vega.api.events.IEventHandler; import com.subgraph.vega.api.html.IHTMLParser; import com.subgraph.vega.api.model.IModel; import com.subgraph.vega.api.model.IWorkspace; import com.subgraph.vega.api.model.WorkspaceCloseEvent; import com.subgraph.vega.api.model.WorkspaceOpenEvent; import com.subgraph.vega.api.paths.IPathFinder; import com.subgraph.vega.api.scanner.modules.IBasicModuleScript; import com.subgraph.vega.api.scanner.modules.IResponseProcessingModule; import com.subgraph.vega.api.scanner.modules.IScannerModuleRegistry; import com.subgraph.vega.api.scanner.modules.ModuleScriptType; import com.subgraph.vega.impl.scanner.modules.scripting.BasicModuleScript; import com.subgraph.vega.impl.scanner.modules.scripting.ResponseProcessorScript; import com.subgraph.vega.impl.scanner.modules.scripting.ScriptLoader; import com.subgraph.vega.impl.scanner.modules.scripting.ScriptedModule; import com.subgraph.vega.impl.scanner.modules.scripting.tests.DomTestModule; import com.subgraph.vega.impl.scanner.modules.scripting.tests.TestScriptLoader; public class ScannerModuleRepository implements IScannerModuleRegistry { private final Logger logger = Logger.getLogger("modules"); private IPathFinder pathFinder; private IHTMLParser htmlParser; private IModel model; private ScriptLoader scriptLoader; private TestScriptLoader testScriptLoader; private Bundle bundle; private IWorkspace currentWorkspace; void activate(BundleContext context) { this.bundle = context.getBundle(); scriptLoader = new ScriptLoader(getScriptDirectory()); scriptLoader.reloadModules(); currentWorkspace = model.addWorkspaceListener(new IEventHandler() { @Override public void handleEvent(IEvent event) { if(event instanceof WorkspaceOpenEvent) handleWorkspaceOpen((WorkspaceOpenEvent) event); else if(event instanceof WorkspaceCloseEvent) handleWorkspaceClose((WorkspaceCloseEvent) event); } }); } private void handleWorkspaceOpen(WorkspaceOpenEvent event) { this.currentWorkspace = event.getWorkspace(); } private void handleWorkspaceClose(WorkspaceCloseEvent event) { this.currentWorkspace = null; } private File getScriptDirectory() { final File configScriptPath = getScriptDirectoryFromConfig(pathFinder.getConfigFilePath()); if(configScriptPath != null && configScriptPath.exists() && configScriptPath.isDirectory()) return configScriptPath; return new File(pathFinder.getDataDirectory(), "scripts" + File.separator + "scanner"); } private File getScriptDirectoryFromConfig(File configFile) { Reader configReader = null; try { if(!(configFile.exists() && configFile.canRead())) { return null; } configReader = new FileReader(configFile); Properties configProperties = new Properties(); configProperties.load(configReader); String pathProp = configProperties.getProperty("vega.scanner.datapath"); if(pathProp != null) { return new File(pathProp, "scripts" + File.separator + "scanner"); } } catch (IOException e) { logger.log(Level.WARNING, "I/O error opening config file "+ configFile.getAbsolutePath(), e); } finally { try { if(configReader != null) { configReader.close(); } } catch (IOException e) { logger.log(Level.WARNING, "I/O error closing config file "+ configFile.getAbsolutePath(), e); } } return null; } @Override public List<IResponseProcessingModule> getResponseProcessingModules() { final List<IResponseProcessingModule> modules = new ArrayList<IResponseProcessingModule>(); for(ScriptedModule m: scriptLoader.getAllModules()) { if(m.getModuleType() == ModuleScriptType.RESPONSE_PROCESSOR) modules.add(new ResponseProcessorScript(m)); } return modules; } @Override public List<IBasicModuleScript> getBasicModules() { final List<IBasicModuleScript> modules = new ArrayList<IBasicModuleScript>(); for(ScriptedModule m: scriptLoader.getAllModules()) { if(m.getModuleType() == ModuleScriptType.BASIC_MODULE) modules.add(new BasicModuleScript(m)); } return modules; } protected void setPathFinder(IPathFinder pathFinder) { this.pathFinder = pathFinder; } protected void unsetPathFinder(IPathFinder pathFinder) { this.pathFinder = null; } protected void setHTMLParser(IHTMLParser htmlParser) { this.htmlParser = htmlParser; } protected void unsetHTMLParser(IHTMLParser htmlParser) { this.htmlParser = null; } protected void setModel(IModel model) { this.model = model; } protected void unsetModel(IModel model) { this.model = null; } @Override public void runDomTests() { if(testScriptLoader == null) { testScriptLoader = new TestScriptLoader(scriptLoader.getPreludeScope(),bundle); testScriptLoader.load(); } Thread testThread = new Thread(createDomTestRunnable()); testThread.start(); } private Runnable createDomTestRunnable() { return new Runnable() { @Override public void run() { for(ScriptedModule m: testScriptLoader.getAllModules()) { runDomTestModule(m); } } }; } private void runDomTestModule(ScriptedModule module) { if(module.getModuleType() != ModuleScriptType.DOM_TEST) return; final DomTestModule test = new DomTestModule(module, bundle, htmlParser); try { test.run(currentWorkspace); } catch (Exception e) { e.printStackTrace(); } } @Override public List<IResponseProcessingModule> updateResponseProcessingModules(List<IResponseProcessingModule> currentModules) { if(!scriptLoader.reloadModules()) { return currentModules; } final Map<String, ResponseProcessorScript> pathMap = new LinkedHashMap<String, ResponseProcessorScript>(); final List<IResponseProcessingModule> newModules = new ArrayList<IResponseProcessingModule>(); for(IResponseProcessingModule m: currentModules) { if(m instanceof ResponseProcessorScript) { ResponseProcessorScript rps = (ResponseProcessorScript) m; pathMap.put(rps.getModule().getScriptFile().getPath(), rps); } } for(ScriptedModule sm: scriptLoader.getAllModulesByType(ModuleScriptType.RESPONSE_PROCESSOR)) { String path = sm.getScriptFile().getPath(); if(pathMap.containsKey(path)) { ResponseProcessorScript old = pathMap.get(path); newModules.add(new ResponseProcessorScript(sm, old.isEnabled(), old.getRunningTimeProfile())); } else { newModules.add(new ResponseProcessorScript(sm)); } } return newModules; } @Override public List<IBasicModuleScript> updateBasicModules(List<IBasicModuleScript> currentModules) { if(!scriptLoader.reloadModules()) { return currentModules; } final Map<String, BasicModuleScript> pathMap = new LinkedHashMap<String, BasicModuleScript>(); final List<IBasicModuleScript> newModules = new ArrayList<IBasicModuleScript>(); for(IBasicModuleScript m: currentModules) { if(m instanceof BasicModuleScript) { BasicModuleScript bms = (BasicModuleScript) m; pathMap.put(bms.getModule().getScriptFile().getPath(), bms); } } for(ScriptedModule sm: scriptLoader.getAllModulesByType(ModuleScriptType.BASIC_MODULE)) { String path = sm.getScriptFile().getPath(); if(pathMap.containsKey(path)) { BasicModuleScript old = pathMap.get(path); newModules.add(new BasicModuleScript(sm, old.isEnabled(), old.getRunningTimeProfile())); } else { newModules.add(new BasicModuleScript(sm)); } } return newModules; } }