All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.classpath.ClassPathHandler Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
 * contributors
 *
 * This file is part of EvoSuite.
 *
 * EvoSuite is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3.0 of the License, or
 * (at your option) any later version.
 *
 * EvoSuite is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EvoSuite. If not, see .
 */
package org.evosuite.classpath;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.jar.*;

import org.evosuite.Properties;
import org.evosuite.runtime.util.Inputs;
import org.evosuite.utils.LoggingUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * When running EvoSuite there are at least three different classpaths
 * to handle: (1) the one of the target project, (2) the one of EvoSuite
 * itself, and (3) the one of the starter of EvoSuite.
 * Note that (2) and (3) can indeed be different: eg if EvoSuite is
 * not run from command line, and rather run from Maven/Eclipse that
 * use their own classloaders.
 * 
 * @author arcuri
 *
 */
public class ClassPathHandler {

	private static Logger logger = LoggerFactory.getLogger(ClassPathHandler.class);

	private static final ClassPathHandler singleton = new ClassPathHandler();


	/**
	 * The classpath of the project to test, including all
	 * its dependencies
	 */
	private String targetClassPath;
	
	/**
	 * When we start the client, we need to know what is the classpath of EvoSuite.
	 * Problem is, if EvoSuite was called from Eclipse/Maven, when the classpath will
	 * not be part of the system classpath. And might not be feasible to query the
	 * current classloader to get such info, as we cannot make any assumption on its implementation.
	 * So, in those cases, we need to manually specify it
	 */
	private String evosuiteClassPath;


	private ClassPathHandler(){		
	}
	
	public static ClassPathHandler getInstance(){
		return singleton;
	}
	
	public static void resetSingleton(){
		getInstance().targetClassPath = null;
		getInstance().evosuiteClassPath = null;
	}

	public String getEvoSuiteClassPath(){
		if(evosuiteClassPath==null){
			evosuiteClassPath = System.getProperty("java.class.path");
		}
		
		return evosuiteClassPath;
	}
	
	/**
	 * Replace current CP of EvoSuite with the given elements 
	 * @param elements
	 * @throws IllegalArgumentException if values in elements are not valid classpath entries
	 */
	public void setEvoSuiteClassPath(String[] elements) throws IllegalArgumentException{
		String cp = getClassPath(elements);
		evosuiteClassPath = cp;
	}
	
	
	/**
	 * Replace current CP for target project with the given elements 
	 * @param elements
	 * @throws IllegalArgumentException if values in elements are not valid classpath entries
	 */
	public void changeTargetClassPath(String[] elements) throws IllegalArgumentException{
		String cp = getClassPath(elements);
		Properties.CP = cp;
		targetClassPath = cp;
	}

	private String getClassPath(String[] elements) {
		if(elements==null || elements.length==0){
			throw new IllegalArgumentException("No classpath elements");
		}

		String cp = "";
		boolean first = true;
		for (String entry : elements) {
			checkIfValidClasspathEntry(entry);
			if (first) {
				first = false;
			} else {
				cp += File.pathSeparator;
			}
			cp += entry;
		}
		return cp;
	}
	
	/**
	 * Return the classpath of the target project.
	 * This should include also all the third-party jars
	 * it depends on
	 * 
	 *  

* If no classpath has been set so far, the one from the property file * will be used, if it exists. * * @return */ public String getTargetProjectClasspath() { if (targetClassPath == null) { String line = null; if (Properties.CP_FILE_PATH != null) { File file = new File(Properties.CP_FILE_PATH); try (InputStream in = new BufferedInputStream(new FileInputStream(file))) { Scanner scanner = new Scanner(in); line = scanner.nextLine(); } catch (Exception e) { LoggingUtils.getEvoLogger().error("Error while processing " + file.getAbsolutePath() + " : " + e.getMessage()); } } targetClassPath = line!=null ? line : Properties.CP; } return targetClassPath; } public static String writeClasspathToFile(String classpath) { try { File file = File.createTempFile("EvoSuite_classpathFile",".txt"); file.deleteOnExit(); BufferedWriter out = new BufferedWriter(new FileWriter(file)); String line = classpath; out.write(line); out.newLine(); out.close(); return file.getAbsolutePath(); } catch (Exception e) { throw new IllegalStateException("Failed to create tmp file for classpath specification: "+e.getMessage()); } } /** * Add classpath entry to the classpath of the target project * * @param element * @throws IllegalArgumentException */ public void addElementToTargetProjectClassPath(String element) throws IllegalArgumentException{ checkIfValidClasspathEntry(element); getTargetProjectClasspath(); //need to be sure it is initialized if(targetClassPath==null || targetClassPath.isEmpty()){ targetClassPath = element; } else { if(targetClassPath.contains(element)){ return; //already there, nothing to add } targetClassPath += File.pathSeparator + element; Properties.CP = targetClassPath; } } private void checkIfValidClasspathEntry(String element) throws IllegalArgumentException{ if(element==null || element.isEmpty()){ throw new IllegalArgumentException("Empty input element"); } File file = new File(element); if(!file.exists()){ throw new IllegalArgumentException("Classpath element does not exist on disk at: "+element); } if(!element.endsWith(".jar") && !file.isDirectory()){ throw new IllegalArgumentException("A classpath element should either be a jar or a folder: "+element); } } /** * Get the project classpath as an array of elements * * @return a non-null array */ public String[] getClassPathElementsForTargetProject(){ String cp = getTargetProjectClasspath(); if(cp==null){ return new String[0]; } return cp.split(File.pathSeparator); } /** * This is meant only for running the EvoSuite test cases, whose CUTs will be in the * classpath of EvoSuite itself */ public void changeTargetCPtoTheSameAsEvoSuite(){ File outDir = new File("target"+File.separator+"classes"); if(outDir.exists()){ changeTargetClassPath(new String[]{outDir.getAbsolutePath()}); File testDir = new File("target"+File.separator+"test-classes"); if(testDir.exists()){ addElementToTargetProjectClassPath(testDir.getAbsolutePath()); } } else { //TODO: just in case... not sure it would work properly changeTargetClassPath(getEvoSuiteClassPath().split(File.pathSeparator)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy