diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/PreferenceConstants.java b/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/PreferenceConstants.java index 4672d5a..962d99a 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/PreferenceConstants.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/PreferenceConstants.java @@ -1,5 +1,7 @@ package com.jfrog.ide.eclipse.configuration; +import java.util.HashMap; +import java.util.Map; /** * Constant definitions for plug-in preferences * @@ -12,6 +14,7 @@ public class PreferenceConstants { public static final String XRAY_URL = "URL"; public static final String XRAY_USERNAME = "Username"; public static final String XRAY_PASSWORD = "Password"; + public static final String DEBUG_LOGS = "DebugLogs"; // Connection constants public static final int CONNECTION_TIMEOUT_MILLISECONDS = 300 * 1000; @@ -20,4 +23,13 @@ public class PreferenceConstants { // Eclipse Buildship plugins public static final String GRADLE_PLUGIN_QUALIFIER = "org.eclipse.buildship.core"; public static final String GRADLE_DISTRIBUTION = "gradle.distribution"; + + + public static Map getCliDebugLogsEnvVars(){ + Map envVars = new HashMap<>(); + envVars.put("JFROG_CLI_LOG_LEVEL", "DEBUG"); + envVars.put("CI", "true"); + + return envVars; + } } diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayGlobalConfiguration.java b/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayGlobalConfiguration.java index 2b5ed72..2cbaf45 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayGlobalConfiguration.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayGlobalConfiguration.java @@ -1,7 +1,11 @@ package com.jfrog.ide.eclipse.configuration; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.core.runtime.ICoreRunnable; import org.eclipse.core.runtime.preferences.ConfigurationScope; +import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.preference.StringFieldEditor; @@ -11,10 +15,10 @@ import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.preferences.ScopedPreferenceStore; +import com.jfrog.ide.eclipse.log.Logger; import com.jfrog.ide.eclipse.scheduling.CliJob; import com.jfrog.ide.eclipse.ui.ComponentDetails; import com.jfrog.ide.eclipse.ui.issues.ComponentIssueDetails; - /** * Panel for configuring Xray URL, username and password. * @@ -40,6 +44,7 @@ public void createFieldEditors() { addField(usernameEditor); addField(passwordEditor); addField(new TestConnectionButton(urlEditor, usernameEditor, passwordEditor, getFieldEditorParent())); + addField(new BooleanFieldEditor(PreferenceConstants.DEBUG_LOGS, "Generate Debug Logs", getFieldEditorParent())); } @Override @@ -48,9 +53,20 @@ public boolean performOk() { if (!XrayServerConfigImpl.getInstance().areCredentialsSet()) { return true; } + + final Map configEnv; + + // define log level + if (XrayServerConfigImpl.getInstance().getIsDebugLogs()) { + Logger.getInstance().setLogLevel(Logger.DEBUG); + configEnv = PreferenceConstants.getCliDebugLogsEnvVars(); + } else { + Logger.getInstance().setLogLevel(Logger.INFO); + configEnv = new HashMap<>(); + } // Define the runnable to execute the CLI config command - ICoreRunnable runnable = monitor -> { + ICoreRunnable runnableServerConfig = monitor -> { try { CliDriverWrapper.getInstance().getCliDriver().addCliServerConfig( XrayServerConfigImpl.getInstance().getXrayUrl(), @@ -60,7 +76,7 @@ public boolean performOk() { XrayServerConfigImpl.getInstance().getPassword(), XrayServerConfigImpl.getInstance().getAccessToken(), CliDriverWrapper.HOME_PATH.toFile(), - System.getenv() + configEnv ); } catch (Exception e) { CliDriverWrapper.getInstance().showCliError("An error occurred while setting up the server connection:", e); @@ -68,19 +84,14 @@ public boolean performOk() { }; // Schedule the CliJob to execute the runnable - CliJob.doSchedule("Setup Server Configuration", runnable); - - boolean doQuickScan = false; + CliJob.doSchedule("Setup Server Configuration", runnableServerConfig); + ComponentDetails[] componentsDetails = { ComponentIssueDetails.getInstance()}; for (ComponentDetails componentsDetail : componentsDetails) { if (componentsDetail != null) { componentsDetail.credentialsSet(); - doQuickScan = true; } } - if (doQuickScan) { - // TODO: run a scan using the ScanManager - } return true; } diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayServerConfigImpl.java b/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayServerConfigImpl.java index d8330b2..9a098b1 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayServerConfigImpl.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/configuration/XrayServerConfigImpl.java @@ -22,8 +22,6 @@ */ @SuppressWarnings("restriction") public class XrayServerConfigImpl implements ServerConfig { - // TODO: adjust implementation for configuring server using JfrogCliDriver - private static XrayServerConfigImpl instance; private IPreferencesService service = Platform.getPreferencesService(); @@ -48,6 +46,10 @@ public String getUsername() { public String getPassword() { return getValue(PreferenceConstants.XRAY_PASSWORD); } + + public boolean getIsDebugLogs() { + return getValue(PreferenceConstants.DEBUG_LOGS) == "true"; + } private String getValue(String key) { return trim(service.getString(PreferenceConstants.XRAY_QUALIFIER, key, "", null)); @@ -110,32 +112,32 @@ public boolean isInsecureTls() { @Override public String getAccessToken() { - // TODO Auto-generated method stub + // This functionality is not yet implemented by the plug-in. return null; } @Override public String getExternalResourcesRepo() { - // TODO Auto-generated method stub + // This functionality is not yet implemented by the plug-in. return null; } @Override public PolicyType getPolicyType() { - // TODO Auto-generated method stub + // This functionality is not yet implemented by the plug-in. return null; } @Override public String getProject() { - // TODO Auto-generated method stub + // This functionality is not yet implemented by the plug-in. return null; } @Override public String getWatches() { - // TODO Auto-generated method stub + // This functionality is not yet implemented by the plug-in. return null; } -} +} \ No newline at end of file diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/log/Logger.java b/bundle/src/main/java/com/jfrog/ide/eclipse/log/Logger.java index 5c10c03..08eb7aa 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/log/Logger.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/log/Logger.java @@ -12,6 +12,14 @@ public class Logger implements Log { private static Logger instance; private static ProblemsLogger viewLogger; private final String ID = "jfrog-eclipse-plugin"; + + public static final int DEBUG = 1; + public static final int INFO = 2; + public static final int WARN = 3; + public static final int ERROR = 4; + + //set default log level as INFO + private int minLogLevel = INFO; private Logger() { ilog = ResourcesPlugin.getPlugin().getLog(); @@ -23,16 +31,23 @@ public static Logger getInstance() { } return instance; } + + public void setLogLevel(int logLevel) { + this.minLogLevel = logLevel; + } + + public int getLogLevel() { + return minLogLevel; + } @Override public void debug(String message) { - ilog.log(new Status(Status.OK, ID, "[OK] " + message)); + log(DEBUG, Status.OK, "[DEBUG] ", message); } @Override public void error(String message) { - ilog.log(new Status(Status.ERROR, ID, "[ERROR] " + message)); - logToProblemsLogger(message, Status.ERROR); + log(ERROR, Status.ERROR, "[ERROR] ", message); } @Override @@ -43,14 +58,23 @@ public void error(String message, Throwable t) { @Override public void info(String message) { - ilog.log(new Status(Status.INFO, ID, "[INFO] " + message)); + log(INFO, Status.INFO, "[INFO] ", message); } @Override public void warn(String message) { - ilog.log(new Status(Status.WARNING, ID, "[WARN] " + message)); - logToProblemsLogger(message, Status.WARNING); + log(WARN, Status.WARNING, "[WARN] ", message); } + + private void log(int level, int status, String prefix, String message) { + if (minLogLevel > level) { + return; + } + ilog.log(new Status(status, ID, prefix + message)); + if (status == Status.WARNING || status == Status.ERROR) { + logToProblemsLogger(message, status); + } + } private void logToProblemsLogger(String message, int status) { if (viewLogger == null) { diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/scan/ScanCache.java b/bundle/src/main/java/com/jfrog/ide/eclipse/scan/ScanCache.java new file mode 100644 index 0000000..83e3edc --- /dev/null +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/scan/ScanCache.java @@ -0,0 +1,41 @@ +package com.jfrog.ide.eclipse.scan; + +import java.util.ArrayList; +import java.util.List; + +import com.jfrog.ide.common.nodes.FileTreeNode; + +public class ScanCache { + private List scanResults; + + private static ScanCache instance; + + private ScanCache() { + scanResults = new ArrayList(); + } + + public static ScanCache getInstance() { + if (instance == null) { + synchronized (ScanCache.class) { + if (instance == null) { + instance = new ScanCache(); + } + } + } + return instance; + } + + public List getScanResults() { + return scanResults; + } + + public void updateScanResults(List results) { + if (results != null) { + scanResults.addAll(results); + } + } + + public void resetCache() { + scanResults = new ArrayList(); + } +} \ No newline at end of file diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/scan/ScanManager.java b/bundle/src/main/java/com/jfrog/ide/eclipse/scan/ScanManager.java index 6ce0ff4..c4cd81f 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/scan/ScanManager.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/scan/ScanManager.java @@ -1,65 +1,101 @@ package com.jfrog.ide.eclipse.scan; -import java.io.IOException; -import java.nio.file.Files; +import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CancellationException; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ICoreRunnable; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.swt.widgets.Composite; -import org.jfrog.build.extractor.scan.DependencyTree; +import org.jfrog.build.extractor.executor.CommandResults; -import com.fasterxml.jackson.core.JsonProcessingException; import com.jfrog.ide.common.configuration.JfrogCliDriver; -import com.jfrog.ide.common.filter.FilterManager; -import com.jfrog.ide.common.log.ProgressIndicator; -import com.jfrog.ide.common.scan.ComponentPrefix; -import com.jfrog.ide.eclipse.configuration.XrayServerConfigImpl; +import com.jfrog.ide.common.parse.SarifParser; +import com.jfrog.ide.eclipse.configuration.CliDriverWrapper; +import com.jfrog.ide.eclipse.configuration.PreferenceConstants; import com.jfrog.ide.eclipse.log.Logger; -import com.jfrog.ide.eclipse.log.ProgressIndicatorImpl; import com.jfrog.ide.eclipse.scheduling.CliJob; -import com.jfrog.ide.eclipse.ui.FilterManagerSingleton; +import com.jfrog.ide.eclipse.ui.issues.ComponentIssueDetails; import com.jfrog.ide.eclipse.ui.issues.IssuesTree; -import com.jfrog.ide.eclipse.utils.ProjectsMap; -import com.jfrog.xray.client.services.summary.Components; import org.jfrog.build.api.util.Log; /** * @author yahavi */ -public abstract class ScanManager { - +public class ScanManager { static final Path HOME_PATH = Paths.get(System.getProperty("user.home"), ".jfrog-eclipse-plugin"); + private static ScanManager instance; private IProgressMonitor monitor; - IProject project; - Log log; - JfrogCliDriver cliDriver; + private IWorkspace iworkspace; + private IProject[] projects; + private Log log; + private JfrogCliDriver cliDriver; + private SarifParser sarifParser; + private AtomicBoolean scanInProgress = new AtomicBoolean(false); - ScanManager(IProject project, ComponentPrefix prefix) throws IOException { - this.project = project; - Files.createDirectories(HOME_PATH); - log = Logger.getInstance(); + private ScanManager() { + this.iworkspace = ResourcesPlugin.getWorkspace(); + this.projects = iworkspace.getRoot().getProjects(); + this.log = Logger.getInstance(); + this.cliDriver = CliDriverWrapper.getInstance().getCliDriver(); + this.sarifParser = new SarifParser(log); } - - /** - * Collect and return {@link Components} to be scanned by JFrog Xray. - * Implementation should be project type specific. - * - * @return - * - * @throws CoreException - * @throws IOException - * @throws JsonProcessingException - */ - public IProject getIProject() { - return project; + public static ScanManager getInstance(){ + if (instance == null) { + synchronized (ScanManager.class) { + if (instance == null) { + instance = new ScanManager(); + } + } + } + return instance; } + public void startScan(Composite parent, boolean isDebugLogs) { + Map auditEnvVars = new HashMap<>(); + + // refresh projects list + projects = iworkspace.getRoot().getProjects(); + if (projects.length == 0) { + log.info("No projects to scan."); + return; + } + + // If scan is in progress - do not perform another scan + if (isScanInProgress()) { + log.info("Previous scan still running..."); + return; + } + + scanInProgress.set(true); + resetIssuesView(IssuesTree.getInstance()); + ScanCache.getInstance().resetCache(); + + if (isDebugLogs) { + auditEnvVars = PreferenceConstants.getCliDebugLogsEnvVars(); + } + + for (IProject project : projects) { + scanAndUpdateResults(IssuesTree.getInstance(), parent, project, auditEnvVars); + } + } + + public void checkCanceled() { + if (monitor != null && monitor.isCanceled()) { + throw new CancellationException("Xray scan was canceled"); + } + } + public void setMonitor(IProgressMonitor monitor) { this.monitor = monitor; } @@ -67,44 +103,97 @@ public void setMonitor(IProgressMonitor monitor) { public IProgressMonitor getMonitor(){ return monitor; } + + public boolean isScanInProgress() { + return scanInProgress.get(); + } + + public void scanFinished() { + scanInProgress.set(false); + } + + public AtomicBoolean getScanInProgress() { + return scanInProgress; + } + + private void resetIssuesView(IssuesTree issuesTree) { + ComponentIssueDetails.getInstance().recreateComponentDetails(); + issuesTree.reset(); + } /** - * Schedule a dependency scan. + * Schedule an audit scan. * - * @param quickScan - True iff this is a quick scan. + * @param issuesTree - The issues tree object to present the issues found by the scan. * @param parent - The parent UI composite. Cancel the scan if the parent is * disposed. + * @param project - The scanned project object. + * @param envVars = The environment variables for running the audit command. */ - public void scanAndUpdateResults(boolean quickScan, IssuesTree issuesTree, Composite parent) { - CliJob.doSchedule(project.getName(), new ScanRunnable(parent, issuesTree, quickScan)); + public void scanAndUpdateResults(IssuesTree issuesTree, Composite parent, IProject project, Map envVars) { + CliJob.doSchedule(String.format("Performing Scan: %s", project.getName()), new ScanRunnable(parent, issuesTree, project, envVars)); } /** - * Start a dependency scan. + * Start an audit scan. */ private class ScanRunnable implements ICoreRunnable { private IssuesTree issuesTree; - private boolean quickScan; private Composite parent; + private IProject project; + private Map envVars; + - private ScanRunnable(Composite parent, IssuesTree issuesTree, boolean quickScan) { + private ScanRunnable(Composite parent, IssuesTree issuesTree, IProject project, Map envVars) { this.parent = parent; this.issuesTree = issuesTree; - this.quickScan = quickScan; + this.project = project; + this.envVars = envVars; + } @Override public void run(IProgressMonitor monitor) throws CoreException { - // TODO: implement scan manager using JfrogCliDriver - } - - private void setScanResults() { - // TODO: re implement using SarifParser + ScanManager.this.monitor = monitor; + // if the parent process is disposed - do not run the scan + if (isDisposed()) { + return; + } + + log.info(String.format("Performing scan on: %s", project.getName())); + + try { + if (project.isOpen()) { + IPath projectPath = project.getLocation(); + CommandResults auditResults = cliDriver.runCliAudit(new File(projectPath.toString()), null, CliDriverWrapper.CLIENT_ID_SERVER, null, envVars); + if (!auditResults.isOk()) { + // log the issue to the problems tab + log.error("Audit scan failed with an error: " + auditResults.getErr()); + return; + } + + checkCanceled(); + + log.info("Finished audit scan successfully.\n" + auditResults.getRes()); + log.debug(auditResults.getErr()); + + log.debug("Updating scan cache."); + ScanCache.getInstance().updateScanResults(sarifParser.parse(auditResults.getRes())); + + // TODO: update issues tree + } + } catch (CancellationException ce) { + log.info(ce.getMessage()); + } catch (Exception e) { + CliDriverWrapper.getInstance().showCliError("An error occurred while performing audit scan", e); + } finally { + scanFinished(); + } } private boolean isDisposed() { return parent == null || parent.isDisposed(); } + } - -} +} \ No newline at end of file diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/scheduling/CliJobEventListener.java b/bundle/src/main/java/com/jfrog/ide/eclipse/scheduling/CliJobEventListener.java index 0726f34..da9fab5 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/scheduling/CliJobEventListener.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/scheduling/CliJobEventListener.java @@ -5,15 +5,15 @@ import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import com.jfrog.ide.eclipse.scan.ScanManager; + public class CliJobEventListener extends JobChangeAdapter { @Override public void done(IJobChangeEvent event) { Job[] jobs = Job.getJobManager().find(CliJob.FAMILY); - // TODO: implement a listener for the audit scan -// ScanManagersFactory scanManagersFactory = ScanManagersFactory.getInstance(); if (ArrayUtils.isEmpty(jobs)) { -// scanManagersFactory.scanFinished(); + ScanManager.getInstance().scanFinished(); } } } diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/ui/PartControl.java b/bundle/src/main/java/com/jfrog/ide/eclipse/ui/PartControl.java index 7a8b0b5..41fc114 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/ui/PartControl.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/ui/PartControl.java @@ -10,7 +10,6 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; -import com.jfrog.ide.eclipse.configuration.XrayServerConfigImpl; import com.jfrog.ide.eclipse.ui.actions.Filter.FilterType; import com.jfrog.ide.eclipse.ui.issues.ComponentIssueDetails; import com.jfrog.ide.eclipse.ui.issues.IssuesTab; @@ -30,7 +29,6 @@ public void createPartControl(Composite parent) { XrayScanToolbar xrayScanToolbar = new XrayScanToolbar(parent); createTabs(parent, xrayScanToolbar); - doQuickScan(parent); } private void createTabs(Composite parent, XrayScanToolbar xrayScanToolbar) { @@ -45,13 +43,6 @@ public void widgetSelected(SelectionEvent event) { }); } - private void doQuickScan(Composite parent) { - if (XrayServerConfigImpl.getInstance().areCredentialsSet()) { -// ScanManagersFactory.getInstance().startScan(parent, true); - // TODO: run a scan - } - } - @PreDestroy public void dispose() { ComponentIssueDetails.disposeComponentDetails(); diff --git a/bundle/src/main/java/com/jfrog/ide/eclipse/ui/actions/Refresh.java b/bundle/src/main/java/com/jfrog/ide/eclipse/ui/actions/Refresh.java index a3b377d..813d013 100644 --- a/bundle/src/main/java/com/jfrog/ide/eclipse/ui/actions/Refresh.java +++ b/bundle/src/main/java/com/jfrog/ide/eclipse/ui/actions/Refresh.java @@ -4,6 +4,7 @@ import org.eclipse.swt.widgets.ToolBar; import com.jfrog.ide.eclipse.configuration.XrayServerConfigImpl; import com.jfrog.ide.eclipse.log.Logger; +import com.jfrog.ide.eclipse.scan.ScanManager; /** * Start a new slow scan. @@ -22,7 +23,7 @@ public void execute(SelectionEvent event) { Logger.getInstance().error("Xray server is not configured."); return; } -// ScanManagersFactory.getInstance().startScan(getParent(), false); - // TODO: run a scan + + ScanManager.getInstance().startScan(getParent(), XrayServerConfigImpl.getInstance().getIsDebugLogs()); } }