package com.highway2urhell; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.instrument.Instrumentation; import java.lang.instrument.UnmodifiableClassException; import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import com.highway2urhell.agent.InstrumentationHolder; import com.highway2urhell.domain.EntryPathData; import com.highway2urhell.domain.FilterEntryPath; import com.highway2urhell.domain.H2hConfig; import com.highway2urhell.domain.OutputSystem; import com.highway2urhell.service.AbstractLeechService; import com.highway2urhell.service.LeechService; import com.highway2urhell.service.ListenerService; import com.highway2urhell.service.ReporterService; import com.highway2urhell.service.ThunderExporterService; import com.highway2urhell.service.TransformerService; import com.highway2urhell.transformer.EntryPointTransformer; import com.highway2urhell.transformer.LineNumberEntryPointTransformer; public class CoreEngine { private static CoreEngine instance; private Map<String, LeechService> leechPluginRegistry = new HashMap<String, LeechService>(); private Set<ReporterService> reporterPluginRegistry = new HashSet<ReporterService>(); private final static String H2H_CONFIG = "H2H_CONFIG"; private final static String JAVA = "Java"; private final static Integer DEFAULT_TIMER = 2000; private final static String NO_URL = "NO_URL"; private final static String NO_SOURCE = "NO_SOURCE"; private H2hConfig config; private CoreEngine() { // nothing } public static CoreEngine getInstance() { if (instance == null) { synchronized (CoreEngine.class) { if (instance == null) { instance = new CoreEngine(); instance.registerPlugins(); instance.runPluginsTriggeredAtStartup(); instance.configure(); instance.runListener(); } } } return instance; } private void runListener() { ScheduledExecutorService schExService = Executors.newScheduledThreadPool(1); schExService.scheduleAtFixedRate(new Runnable() { public void run() { System.out.println("Call the H2H-Web server"); ListenerService.getInstance().callServerH2H(); } }, 5, 10, TimeUnit.SECONDS); } public void enableEntryPointCoverage(FilterEntryPath filter) throws ClassNotFoundException, UnmodifiableClassException { System.out.println("enabling entry point coverage "+filter.toString()); Instrumentation instrumentation = InstrumentationHolder.getInstance().getInst(); if (instrumentation != null) { TransformerService ts = new TransformerService(); Map<String, List<EntryPathData>> mapConvert = ts .transformDataFromLeechPluginForTransformation(leechPluginRegistry.values(), filter); if (!config.getPathSend()) { // if the initPath are not called initPathsRemote(); } instrumentation.addTransformer( new EntryPointTransformer(mapConvert, CoreEngine.getInstance().getConfig().getPerformance()), true); ts.transformAllClassScanByH2h(instrumentation, mapConvert.keySet()); } else { System.err.println("Instrumentation fail because internal inst is null"); } } private void getLineNumberFromEntryPoint(FilterEntryPath filter) throws ClassNotFoundException, UnmodifiableClassException { System.out.println("enabling getLineNumberFromEntryPoint "+filter.toString()); Instrumentation instrumentation = InstrumentationHolder.getInstance().getInst(); if (instrumentation != null) { TransformerService ts = new TransformerService(); Map<String, List<EntryPathData>> mapConvert = ts .transformDataFromLeechPluginForTransformation(leechPluginRegistry.values(), filter); instrumentation.addTransformer(new LineNumberEntryPointTransformer(mapConvert)); ts.transformAllClassScanByH2h(instrumentation, mapConvert.keySet()); } else { System.err.println("Instrumentation fail because internal inst is null"); } } public void initPathsRemoteWithOutTransformerLine() { ThunderExporterService.getInstance().initPathsRemoteApp(); config.setPathSend(true); } public void initPathsRemote() { if (config.getToken() != null && !config.getPathSend()) { try { FilterEntryPath filter = new FilterEntryPath(); filter.setFilter(true); filter.setListFilter(new ArrayList<String>()); getLineNumberFromEntryPoint(filter); ThunderExporterService.getInstance().initPathsRemoteApp(); config.setPathSend(true); } catch (ClassNotFoundException e) { System.err.println("Error while launchTransformer "+ e); } catch (UnmodifiableClassException e) { System.err.println("Error while launchTransformer "+ e); } } } public void updateLineNumberEntryPoint(EntryPathData entry) { System.out.println("Try to update entry "+entry); for (LeechService leech : leechPluginRegistry.values()) { for (EntryPathData entryPath : leech.getFrameworkInformations().getListEntryPath()) { if(entryPath.getClassName().equals(entry.getClassName()) && entryPath.getMethodName().equals(entry.getMethodName()) && entryPath.getSignatureName().equals(entry.getSignatureName())){ entryPath.setLineNumber(entry.getLineNumber()); System.out.println("Update complete entry "+entry); } } } } public void leech() { for (ReporterService reporterService : reporterPluginRegistry) { for (LeechService leechService : leechPluginRegistry.values()) { reporterService.report(leechService.getFrameworkInformations()); } } } public Collection<LeechService> getLeechServiceRegistered() { return leechPluginRegistry.values(); } public LeechService getFramework(String frameworkName) { return leechPluginRegistry.get(frameworkName); } private void registerPlugins() { autoDiscoverLeechPlugins(); autoDiscoverReporterPlugins(); } private void autoDiscoverLeechPlugins() { Set<AbstractLeechService> leechServices = PluginUtils.autodiscoverPlugin(AbstractLeechService.class); for (AbstractLeechService leechService : leechServices) { leechPluginRegistry.put(leechService.getFrameworkInformations().getFrameworkName(), leechService); } } private void autoDiscoverReporterPlugins() { reporterPluginRegistry = PluginUtils.autodiscoverPlugin(ReporterService.class); } private void runPluginsTriggeredAtStartup() { for (LeechService leechService : leechPluginRegistry.values()) { if (leechService.isTriggeredAtStartup()) { leechService.receiveData(null); } } } private void configure() { // Grab Env String rootH2h = System.getProperty(H2H_CONFIG); if (rootH2h == null) { defaultConfig(); } else if ("".equals(rootH2h)) { defaultConfig(); } else { parseConfig(rootH2h); } } private void defaultConfig() { config = new H2hConfig(); config.setTypeAppz(JAVA); config.setUrlApplication(NO_URL); config.setNameApplication(String.valueOf(System.currentTimeMillis())); config.setPathSource(NO_SOURCE); config.setDescription("Default Name."); config.setPerformance(false); config.setTimer(OutputSystem.REMOTE); config.setHigherTime(DEFAULT_TIMER); // TODO // Hardcoded la valeur de la plateforme --> le jour ou la plateforme // fonctionnera ... one day ... one day .. // Actuellement on hardcode le local config.setUrlH2hWeb("http://localhost:8090/core/api/ThunderEntry"); // TODO // Recuperer le token comme parametre le jour ou la plate fonctionnera // ... one day ... one day .. config.setToken(null); } private void parseConfig(String pathFile) { config = new H2hConfig(); config.setTypeAppz(JAVA); Properties prop = new Properties(); InputStream input = null; try { input = new FileInputStream(pathFile); prop.load(input); config.setUrlApplication(prop.getProperty("urlapplication")); config.setNameApplication(prop.getProperty("nameapplication")); config.setPathH2h(prop.getProperty("pathH2h")); config.setPathSource(prop.getProperty("pathSource")); config.setDescription(prop.getProperty("description")); config.setVersionApp(prop.getProperty("versionApp")); config.setToken(prop.getProperty("token")); config.setReference(prop.getProperty("reference")); String performance = prop.getProperty("performance"); if (performance != null && performance.equals("true")) { config.setPerformance(true); } else { config.setPerformance(false); } String timer = prop.getProperty("timer"); if (timer != null) { config.setTimer(OutputSystem.valueOf(timer)); } else { throw new RuntimeException("Variable timer is not defined"); } config.setUrlH2hWeb(prop.getProperty("urlh2hweb")); String higherTimer = prop.getProperty("higherTimer"); if (higherTimer != null) { try { config.setHigherTime(Integer.valueOf(higherTimer)); } catch (NumberFormatException e) { // default value config.setHigherTime(DEFAULT_TIMER); } } else { // default value config.setHigherTime(DEFAULT_TIMER); } } catch (IOException ex) { throw new RuntimeException("Error while reading H2hConfigFile " + pathFile, ex); } finally { if (input != null) { try { input.close(); } catch (IOException e) { // Don't care } } } } public H2hConfig getConfig() { return config; } }