Java tutorial
/* * Copyright 2015 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.robotframework.ide.eclipse.main.plugin.project; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Consumer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.e4.core.services.events.IEventBroker; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.rf.ide.core.dryrun.RobotDryRunLibraryEventListener; import org.rf.ide.core.dryrun.RobotDryRunLibraryImport; import org.rf.ide.core.dryrun.RobotDryRunLibraryImport.DryRunLibraryImportStatus; import org.rf.ide.core.dryrun.RobotDryRunLibraryImport.DryRunLibraryType; import org.rf.ide.core.dryrun.RobotDryRunLibraryImportCollector; import org.rf.ide.core.dryrun.RobotDryRunTemporarySuites; import org.rf.ide.core.executor.EnvironmentSearchPaths; import org.rf.ide.core.executor.RobotRuntimeEnvironment.RobotEnvironmentException; import org.rf.ide.core.project.RobotProjectConfig.LibraryType; import org.rf.ide.core.project.RobotProjectConfig.ReferencedLibrary; import org.robotframework.ide.eclipse.main.plugin.RedPlugin; import org.robotframework.ide.eclipse.main.plugin.RedWorkspace; import org.robotframework.ide.eclipse.main.plugin.launch.RobotPathsNaming; import org.robotframework.ide.eclipse.main.plugin.model.RobotProject; import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile; import org.robotframework.ide.eclipse.main.plugin.project.editor.libraries.ILibraryClass; import org.robotframework.ide.eclipse.main.plugin.project.editor.libraries.JarStructureBuilder; import org.robotframework.ide.eclipse.main.plugin.project.editor.libraries.PythonLibStructureBuilder; import org.robotframework.red.swt.SwtThread; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.io.Files; /** * @author mmarzec */ public class LibrariesAutoDiscoverer extends AbstractAutoDiscoverer { private final boolean showSummary; private final Optional<String> libraryNameToDiscover; private final RobotDryRunLibraryImportCollector dryRunLibraryImportCollector; public LibrariesAutoDiscoverer(final RobotProject robotProject, final List<? extends IResource> resources) { this(robotProject, resources, true, null); } public LibrariesAutoDiscoverer(final RobotProject robotProject, final List<? extends IResource> resources, final String libraryNameToDiscover) { this(robotProject, resources, true, libraryNameToDiscover); } public LibrariesAutoDiscoverer(final RobotProject robotProject, final List<? extends IResource> resources, final boolean showSummary) { this(robotProject, resources, showSummary, null); } @VisibleForTesting LibrariesAutoDiscoverer(final RobotProject robotProject, final List<? extends IResource> resources, final boolean showSummary, final String libraryNameToDiscover) { super(robotProject, resources, new LibrariesSourcesCollector(robotProject), new DryRunTargetsCollector()); this.showSummary = showSummary; this.libraryNameToDiscover = Optional.ofNullable(Strings.emptyToNull(libraryNameToDiscover)); this.dryRunLibraryImportCollector = new RobotDryRunLibraryImportCollector( robotProject.getStandardLibraries().keySet()); } @Override RobotDryRunLibraryEventListener createDryRunEventListener(final Consumer<String> startSuiteHandler) { return new RobotDryRunLibraryEventListener(dryRunLibraryImportCollector, startSuiteHandler); } @Override Job start(final Shell parent) { if (lockDryRun()) { final WorkspaceJob wsJob = new WorkspaceJob("Discovering libraries") { @Override public IStatus runInWorkspace(final IProgressMonitor monitor) throws CoreException { try { startDiscovering(monitor); if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } final List<RobotDryRunLibraryImport> libraryImports = getLibraryImportsToProcess(); startAddingLibrariesToProjectConfiguration(monitor, libraryImports); if (showSummary) { showSummary(parent, libraryImports); } } catch (final CoreException e) { throw new AutoDiscovererException("Problems occurred during discovering libraries.", e); } catch (final InterruptedException e) { // fine, will simply stop dry run } finally { monitor.done(); unlockDryRun(); } return Status.OK_STATUS; } @Override protected void canceling() { stopDiscovering(); } }; wsJob.setUser(true); wsJob.schedule(); return wsJob; } return null; } private List<RobotDryRunLibraryImport> getLibraryImportsToProcess() { final List<RobotDryRunLibraryImport> libraryImports = dryRunLibraryImportCollector.getImportedLibraries(); if (libraryNameToDiscover.isPresent()) { for (final RobotDryRunLibraryImport libraryImport : libraryImports) { if (libraryImport.getName().equalsIgnoreCase(libraryNameToDiscover.get())) { return Collections.singletonList(libraryImport); } } return Collections.emptyList(); } return libraryImports; } private void startAddingLibrariesToProjectConfiguration(final IProgressMonitor monitor, final List<RobotDryRunLibraryImport> libraryImports) { if (!libraryImports.isEmpty()) { final ImportedLibrariesConfigUpdater updater = new ImportedLibrariesConfigUpdater(robotProject); final List<RobotDryRunLibraryImport> libraryImportsToAdd = updater .getLibraryImportsToAdd(libraryImports); final SubMonitor subMonitor = SubMonitor.convert(monitor); subMonitor.subTask("Adding libraries to project configuration..."); subMonitor.setWorkRemaining(libraryImportsToAdd.size() + 1); for (final RobotDryRunLibraryImport libraryImport : libraryImportsToAdd) { updater.addLibrary(libraryImport); subMonitor.worked(1); } subMonitor.subTask("Updating project configuration..."); final IEventBroker eventBroker = PlatformUI.getWorkbench().getService(IEventBroker.class); updater.finalizeLibrariesAdding(eventBroker); subMonitor.worked(1); } } private void showSummary(final Shell parent, final List<RobotDryRunLibraryImport> libraryImports) { SwtThread.syncExec(() -> new LibrariesAutoDiscovererWindow(parent, libraryImports).open()); } private static class DryRunTargetsCollector implements IDryRunTargetsCollector { private final List<String> suiteNames = new ArrayList<>(); private final List<File> additionalProjectsLocations = new ArrayList<>(); @Override public void collectSuiteNamesAndAdditionalProjectsLocations(final RobotProject robotProject, final List<? extends IResource> resources) { final List<String> resourcesPaths = new ArrayList<>(); for (final IResource resource : resources) { if (isResourceFile(resource)) { final IPath resourceFilePath = RedWorkspace.Paths .toWorkspaceRelativeIfPossible(resource.getProjectRelativePath()); resourcesPaths.add(resourceFilePath.toString()); } else if (resource.isLinked()) { collectLinkedSuiteNamesAndProjectsLocations(resource); } else { suiteNames.add(RobotPathsNaming.createSuiteName(resource)); } } if (!resourcesPaths.isEmpty()) { final File tempSuiteFile = RobotDryRunTemporarySuites.createResourceFile(resourcesPaths); if (tempSuiteFile != null) { suiteNames.add(Files.getNameWithoutExtension(tempSuiteFile.getPath())); additionalProjectsLocations.add(tempSuiteFile.getParentFile()); } } } private boolean isResourceFile(final IResource resource) { RobotSuiteFile suiteFile = null; if (resource.getType() == IResource.FILE) { suiteFile = RedPlugin.getModelManager().createSuiteFile((IFile) resource); } return suiteFile != null && suiteFile.isResourceFile(); } private void collectLinkedSuiteNamesAndProjectsLocations(final IResource resource) { final IPath linkedFileLocation = resource.getLocation(); if (linkedFileLocation != null) { final File linkedFile = linkedFileLocation.toFile(); if (linkedFile.exists()) { suiteNames.add(Files.getNameWithoutExtension(linkedFile.getName())); final File linkedFileParentPath = linkedFile.getParentFile(); if (!additionalProjectsLocations.contains(linkedFileParentPath)) { additionalProjectsLocations.add(linkedFileParentPath); } } } } @Override public List<String> getSuiteNames() { return suiteNames; } @Override public List<File> getAdditionalProjectsLocations() { return additionalProjectsLocations; } } private static class ImportedLibrariesConfigUpdater extends LibrariesConfigUpdater { ImportedLibrariesConfigUpdater(final RobotProject robotProject) { super(robotProject); } List<RobotDryRunLibraryImport> getLibraryImportsToAdd(final List<RobotDryRunLibraryImport> libraryImports) { final List<String> existingLibraryNames = new ArrayList<>(); for (final ReferencedLibrary existingLibrary : config.getLibraries()) { existingLibraryNames.add(existingLibrary.getName()); } final List<RobotDryRunLibraryImport> result = new ArrayList<>(); for (final RobotDryRunLibraryImport libraryImport : libraryImports) { if (libraryImport.getType() != DryRunLibraryType.UNKNOWN) { if (existingLibraryNames.contains(libraryImport.getName())) { libraryImport.setStatus(DryRunLibraryImportStatus.ALREADY_EXISTING); } else { result.add(libraryImport); } } } return result; } void addLibrary(final RobotDryRunLibraryImport libraryImport) { if (libraryImport.getType() == DryRunLibraryType.JAVA) { addJavaLibrary(libraryImport); } else if (libraryImport.getType() == DryRunLibraryType.PYTHON) { addPythonLibrary(libraryImport); } } private void addPythonLibrary(final RobotDryRunLibraryImport libraryImport) { final PythonLibStructureBuilder pythonLibStructureBuilder = new PythonLibStructureBuilder( robotProject.getRuntimeEnvironment(), robotProject.getRobotProjectConfig(), robotProject.getProject()); try { final Collection<ILibraryClass> libraryClasses = pythonLibStructureBuilder .provideEntriesFromFile(libraryImport.getSourcePath(), libraryImport.getName()); addReferencedLibrariesFromClasses(libraryImport, libraryClasses); } catch (final RobotEnvironmentException e) { final Optional<File> modulePath = findPythonLibraryModulePath(libraryImport); if (modulePath.isPresent()) { final Path path = new Path(modulePath.get().getPath()); final ReferencedLibrary newLibrary = ReferencedLibrary.create(LibraryType.PYTHON, libraryImport.getName(), path.toPortableString()); addLibraries(Collections.singletonList(newLibrary)); } else { libraryImport.setStatus(DryRunLibraryImportStatus.NOT_ADDED); libraryImport.setAdditionalInfo(e.getMessage()); } } } private Optional<File> findPythonLibraryModulePath(final RobotDryRunLibraryImport libraryImport) { try { final EnvironmentSearchPaths envSearchPaths = new RedEclipseProjectConfig(config) .createEnvironmentSearchPaths(robotProject.getProject()); return robotProject.getRuntimeEnvironment().getModulePath(libraryImport.getName(), envSearchPaths); } catch (final RobotEnvironmentException e1) { return Optional.empty(); } } private void addJavaLibrary(final RobotDryRunLibraryImport libraryImport) { final JarStructureBuilder jarStructureBuilder = new JarStructureBuilder( robotProject.getRuntimeEnvironment(), robotProject.getRobotProjectConfig(), robotProject.getProject()); try { final Collection<ILibraryClass> libraryClasses = jarStructureBuilder .provideEntriesFromFile(libraryImport.getSourcePath()); addReferencedLibrariesFromClasses(libraryImport, libraryClasses); } catch (final RobotEnvironmentException e) { libraryImport.setStatus(DryRunLibraryImportStatus.NOT_ADDED); libraryImport.setAdditionalInfo(e.getMessage()); } } private void addReferencedLibrariesFromClasses(final RobotDryRunLibraryImport libraryImport, final Collection<ILibraryClass> libraryClasses) { final Collection<ReferencedLibrary> librariesToAdd = new ArrayList<>(); for (final ILibraryClass libraryClass : libraryClasses) { if (libraryClass.getQualifiedName().equalsIgnoreCase(libraryImport.getName())) { librariesToAdd.add(libraryClass.toReferencedLibrary(libraryImport.getSourcePath().getPath())); } } if (!librariesToAdd.isEmpty()) { addLibraries(librariesToAdd); } else { libraryImport.setStatus(DryRunLibraryImportStatus.NOT_ADDED); libraryImport.setAdditionalInfo("RED was unable to find class '" + libraryImport.getName() + "' inside '" + libraryImport.getSourcePath() + "' module."); } } } }