public class AssessmentRun extends SwampThing{
    public AssessmentRun(Session session) {
        super(session);
    }
    public AssessmentRun(Session session, Map map) {
        super(session, map);
    }

    @Override
    protected SwampThing getNewInstance() {
        return new AssessmentRun(getSession());
    }

    @Override
    public String getIDKey() {
        return AssessmentRunHandler.ASSESSMENT_RUN_UUID;
    }


    public Project getProject() {
        return project;
    }

    public void setProject(Project project) {
        this.project = project;
    }

    public PackageThing getPkg() {
        return pkg;
    }

    public void setPkg(PackageThing pkg) {
        this.pkg = pkg;
    }

    public Platform getPlatform() {
        return platform;
    }

    public void setPlatform(Platform platform) {
        this.platform = platform;
    }

    public void setPlatformVersion(PlatformVersion platform_version) {
        this.platform_version = platform_version;
    }
    
    public Tool getTool() {
        return tool;
    }

    public void setTool(Tool tool) {
        this.tool = tool;
    }

    public String getPackageName() {
        return getConversionMap().getString("package_name");
    }
    
    public String getPackageVersion() {
        return getConversionMap().getString("package_version_string");
    }
    
    public String getToolName() {
        return getConversionMap().getString("tool_name");
    }
    
    public String getToolVersion() {
        return getConversionMap().getString("tool_version_string");
    }

    public String getPlatformName() {
        return getConversionMap().getString("platform_name");
    }
    
    public String getPlatformVersion() {
        return getConversionMap().getString("platform_version_string");
    }
    
    Project project;
    PackageThing pkg;
    Platform platform;
    PlatformVersion platform_version;
    Tool tool;

    @Override
    public String toString() {
        return "AssessmentRun[" +
                "uuid=" + getIdentifier() +
                ", project=" + (project==null?"none":getProject().getFullName())+
                ", pkg=" + (pkg==null?"none":getPkg().getName()) +
                ", platform=" + (platform==null?"none":getPlatform().getName()) +
                ", tool=" + (tool==null?"none":getTool().getName()) +
                "]";
    }
} public class Platform extends SwampThing {
    public Platform(Session session) {
        super(session);
    }
    public Platform(Session session, Map map) {
        super(session, map);
    }

    @Override
    protected SwampThing getNewInstance() {
        return new Platform(getSession());
    }

    @Override
    public String getIDKey() {return PLATFORM_UUID_KEY;}
    public String getName(){return getString(NAME_KEY);}
    public void setName(String name){put(NAME_KEY,name);}
    public String getPlatformSharingStatus(){return getString(PLATFORM_SHARING_STATUS_KEY);}
    public void setPlatformSharingStatus(String sharingStatus){put(PLATFORM_SHARING_STATUS_KEY, sharingStatus);}
    public Date getCreateDate(){return getDate(CREATE_DATE_KEY);}
    public void setCreateDate(Date createDate){put(CREATE_DATE_KEY, createDate);}
    public String getDescription(){return getString(DESCRIPTION_KEY);}
    public List<String> getVersions(){return getAsArray(VERSION_STRINGS_KEY);}
/*
    public Date getUpdateDate(){return getDate(UPDATE_DATE_KEY);}
    public void setUpdateDate(Date updateDate){put(UPDATE_DATE_KEY,updateDate);}
*/

    @Override
    public String toString() {
        return "Platform[uuid=" + getIdentifier() + ", name=" + getName() + ", create date=" + getCreateDate() + "]";
    }
} public class Project extends SwampThing {


    @Override
    protected SwampThing getNewInstance() {
        return new Project(getSession());
    }

    @Override
    public String getIDKey() {
        return PROJECT_UID_KEY;
    }


    public Project(Session session) {
        super(session);
    }
    public Project(Session session, Map map) {
        super(session, map);
    }


    public String getDescription() {
        return getString(DESCRIPTION_KEY);
    }

    public void setDescription(String description) {
        put(DESCRIPTION_KEY, description);
    }

    public String getFullName() {
        return getString(FULL_NAME_KEY);
    }

    public void setFullName(String fullName) {
        put(FULL_NAME_KEY, fullName);
    }


    public String getShortName() {
        return getString(SHORT_NAME_KEY);
    }

    public void setShortName(String shortName) {
        put(SHORT_NAME_KEY, shortName);
    }

    public String getAffiliation() {
        return getString(AFFILIATION_KEY);
    }

    public void setAffiliation(String affiliation) {
        put(AFFILIATION_KEY, affiliation);
    }

    public Date getCreateDate() {
        return getDate(CREATE_DATE_KEY);
    }

    public void setCreateDate(Date createDate) {
        put(CREATE_DATE_KEY, createDate);
    }

    public Date getDenialDate() {
        return getDate(DENIAL_DATE_KEY);
    }

    public void setDenialDate(Date denialDate) {
        put(DENIAL_DATE_KEY, denialDate);
    }

    public Date getDeactivationDate() {
        return getDate((DEACTIVATION_DATE_KEY));
    }

    public void setDeactivationDate(Date deactivationDate) {
        put(DEACTIVATION_DATE_KEY, deactivationDate);
    }

    public String getOwnerUUID() {
        return getString(USER_UID_KEY);
    }

    public void setOwnerUUID(String ownerUUID) {
        put(USER_UID_KEY, ownerUUID);
    }

    public boolean isTrialProjectFlag() {
        return getBoolean(TRIAL_PROJECT_FLAG_KEY);
    }

    public void setTrialProjectFlag(boolean trialProjectFlag) {
        put(TRIAL_PROJECT_FLAG_KEY, trialProjectFlag);
    }

    @Override
    public String toString() {
        return "Project[name=" + getFullName() + ",description=" + getDescription() + ", owner id=" + getOwnerUUID() +
                ", create date=" + getCreateDate() + ", uuid=" + getIdentifier() + "]";
    }
} public class IncompatibleAssessmentTupleException extends SwampApiWrapperException {
	public IncompatibleAssessmentTupleException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.INCOMPATIBLE_TUPLE);
	}

	public IncompatibleAssessmentTupleException(String msg){
	    super(msg);
	    setExitCode(SwampApiWrapperExitCodes.INCOMPATIBLE_TUPLE);
	}

} public class InvalidIdentifierException extends SwampApiWrapperException {
	public InvalidIdentifierException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.INVALID_UUID);
	}

	public InvalidIdentifierException(String msg){
	    super(msg);
	    setExitCode(SwampApiWrapperExitCodes.INVALID_UUID);
	}

} public class InvalidNameException extends SwampApiWrapperException {
	public InvalidNameException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.INVALID_NAME);
	}

	public InvalidNameException(String msg){
	    super(msg);
	    setExitCode(SwampApiWrapperExitCodes.INVALID_NAME);
	}

} public class NoDefaultPlatformException extends SwampApiWrapperException {
	public NoDefaultPlatformException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.NO_DEFAULT_PLATFORM);
	}
	
	public NoDefaultPlatformException(String msg){
        super(msg);
        setExitCode(SwampApiWrapperExitCodes.NO_DEFAULT_PLATFORM);
    }
} public class SessionExpiredException extends SwampApiWrapperException {
	public SessionExpiredException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.SESSION_EXPIRED);
	}
	
    public SessionExpiredException(String msg){
        super(msg);
        setExitCode(SwampApiWrapperExitCodes.SESSION_EXPIRED);
    }

} public class SessionRestoreException extends SwampApiWrapperException {
	public SessionRestoreException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.SESSION_RESTORE_ERROR);
	}
	
	   public SessionRestoreException(String msg){
	        super(msg);
	        setExitCode(SwampApiWrapperExitCodes.SESSION_RESTORE_ERROR);
	    }

} public class SessionSaveException extends SwampApiWrapperException {
	public SessionSaveException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.SESSION_SAVE_ERROR);
	}
	
	public SessionSaveException(String msg){
        super(msg);
        setExitCode(SwampApiWrapperExitCodes.SESSION_SAVE_ERROR);
    }
} public class ToolPermissionException extends SwampApiWrapperException {
	public ToolPermissionException(Exception exception){
		super(exception);
		setExitCode(SwampApiWrapperExitCodes.TOOL_NO_PERMISSION);
	}

	public ToolPermissionException(String msg){
	    super(msg);
	    setExitCode(SwampApiWrapperExitCodes.TOOL_NO_PERMISSION);
	}

} public class HandlerFactory {
    AdministrationHandler administrationHandler;
    AssessmentRunHandler<? extends AssessmentRun> assessmentHandler;
    AssessmentRecordHandler<? extends AssessmentRecord> assessmentRecordHandler;
    AssessmentResultHandler<? extends AssessmentResults> assessmentResultHandler;

    Session CSASession;
    
    PackageHandler<? extends PackageThing> packageHandler;
    
    PackageVersionHandler<? extends PackageVersion> packageVersionHandler;

    PlatformHandler<? extends Platform> platformHandler;

    PlatformVersionHandler<? extends PlatformVersion> platformVersionHandler;

    ProjectHandler<? extends Project> projectHandler;

    RunRequestHandler<? extends RunRequest> runRequestHandler;

    RunRequestScheduleHandler<? extends RunRequestSchedule> runRequestScheduleHandler;

    ToolHandler<? extends Tool> toolHandler;

    protected ToolVersionHandler<? extends ToolVersion> toolVersionHandler;

    UserHandler<? extends User> userHandler;

    /**
     * Convenience constructor to take a list of (at least) 2 sessions. The 0th element is assumed
     * to be the RWS session and the 1st element is assumed to the CSA session.
     * @param sessions
     */
    public HandlerFactory(List<Session> sessions){
        if(sessions.size()< 1){
            throw new IllegalArgumentException("Error: You must supply at least 2 sessions");
        }
        this.CSASession = sessions.get(1);
    }

    public HandlerFactory(Session CSASession) {
        this.CSASession = CSASession;
    }

    public AdministrationHandler getAdminHandler(){
        if(administrationHandler == null){
            administrationHandler = new AdministrationHandler(getCSASession());
        }
        return administrationHandler;
    }

    public AssessmentRunHandler<? extends AssessmentRun> getAssessmentHandler() {
        if(assessmentHandler == null){
            assessmentHandler = new AssessmentRunHandler<>(getCSASession());
            assessmentHandler.setProjectHandler(getProjectHandler());
        }
        return assessmentHandler;
    }

    public AssessmentRecordHandler<? extends AssessmentRecord> getassessmentRecordHandler() {
        if(assessmentRecordHandler == null){
            assessmentRecordHandler = new AssessmentRecordHandler<>(getCSASession());
        }
        return assessmentRecordHandler;
    }

    public AssessmentResultHandler<? extends AssessmentResults> getAssessmentResultHandler() {
        if(assessmentResultHandler == null){
            assessmentResultHandler = new AssessmentResultHandler<>(getCSASession());
        }
        return assessmentResultHandler;
    }
    public Session getCSASession() {
        return CSASession;
    }

    public PackageHandler<? extends PackageThing> getPackageHandler() {
        if(packageHandler == null){
            packageHandler = new PackageHandler<>(getCSASession());
        }
        return packageHandler;
    }
    public PackageVersionHandler<? extends PackageVersion> getPackageVersionHandler() {
        if(packageVersionHandler == null){
            packageVersionHandler = new PackageVersionHandler<>(getCSASession());
        }
        return packageVersionHandler;
    }
    public PlatformHandler<? extends Platform> getPlatformHandler() {
        if(platformHandler == null){
            platformHandler = new PlatformHandler<>(getCSASession());
        }
        return platformHandler;
    }

    public PlatformVersionHandler<? extends PlatformVersion> getPlatformVersionHandler() {
        if(platformVersionHandler == null){
            platformVersionHandler = new PlatformVersionHandler<>(getCSASession());
        }
        return platformVersionHandler;
    }

    public ProjectHandler<? extends Project> getProjectHandler() {
        if(projectHandler == null){
            projectHandler = new ProjectHandler<>(getCSASession());
        }
        return projectHandler;
    }


    public RunRequestHandler<? extends RunRequest> getRunRequestHandler() {
        if(runRequestHandler == null){
            runRequestHandler = new RunRequestHandler<>(getCSASession());
        }
        return runRequestHandler;
    }

    public RunRequestScheduleHandler<? extends RunRequestSchedule> getRunRequestScheduleHandler() {
        if(runRequestScheduleHandler == null){
            runRequestScheduleHandler = new RunRequestScheduleHandler<>(getCSASession());
        }
        return runRequestScheduleHandler;
    }

    public ToolHandler<? extends Tool> getToolHandler() {
        if(toolHandler == null){
            toolHandler = new ToolHandler<>(getCSASession());
        }
        return toolHandler;
    }
    public ToolVersionHandler<? extends ToolVersion> getToolVersionHandler() {
        if(toolVersionHandler== null){
            toolVersionHandler = new ToolVersionHandler<>(getCSASession());
        }
        return toolVersionHandler;
    }
    public UserHandler<? extends User> getUserHandler() {
        if(userHandler == null){
            userHandler = new UserHandler<>(getCSASession());
        }
        return userHandler;
    }
    public void setAssessmentHandler(AssessmentRunHandler<? extends AssessmentRun> assessmentHandler) {
        this.assessmentHandler = assessmentHandler;
    }
    public void setCSASession(Session CSASession) {
        this.CSASession = CSASession;
    }
    public void setPackageHandler(PackageHandler<? extends PackageThing> packageHandler) {
        this.packageHandler = packageHandler;
    }
    public void setPackageVersionHandler(PackageVersionHandler<? extends PackageVersion> packageVersionHandler) {
        this.packageVersionHandler = packageVersionHandler;
    }
    public void setPlatformHandler(PlatformHandler<? extends Platform> platformHandler) {
        this.platformHandler = platformHandler;
    }

    public void setPlatformVersionHandler(PlatformVersionHandler<? extends PlatformVersion> platformVersionHandler) {
        this.platformVersionHandler = platformVersionHandler;
    }


    public void setProjectHandler(ProjectHandler<? extends Project> projectHandler) {
        this.projectHandler = projectHandler;
    }

    public void setRunRequestHandler(RunRequestHandler<? extends RunRequest> runRequestHandler) {
        this.runRequestHandler = runRequestHandler;
    }

    public void setRunRequestScheduleHandler(RunRequestScheduleHandler<? extends RunRequestSchedule> runRequestScheduleHandler) {
        this.runRequestScheduleHandler = runRequestScheduleHandler;
    }


    public void setToolHandler(ToolHandler<? extends Tool> toolHandler) {
        this.toolHandler = toolHandler;
    }

    public void setUserHandler(UserHandler<? extends User> userHandler) {
        this.userHandler = userHandler;
    }
} public class PackageHandler<T extends PackageThing> extends AbstractHandler<T> {


    public static final String PACKAGE_UUID_KEY = "package_uuid";
    public static final String PACKAGE_OWNER_UUID_KEY = "package_owner_uuid";
    public static final String PACKAGE_NAME_KEY = "name";
    public static final String PACKAGE_DESCRIPTION_KEY = "description";
    public static final String PACKAGE_TYPE_KEY = "package_type";
    public static final String PACKAGE_LANGUAGE_KEY = "package_language";
    public static final String PACKAGE_TYPE_ID_KEY = "package_type_id";
    public static final String PACKAGE_SHARING_STATUS_KEY = "package_sharing_status";
    public static final String EXTERNAL_URI_KEY = "external_uri";
    public static final String CREATE_DATE_KEY = "create_date";
    public static final String UPDATE_DATE_KEY = "update_date";
    public static final String IS_OWNED_KEY = "is_owned";
    public static final String VERSION_STRINGS = "version_strings";

    public static final int PACKAGE_TYPE_C_SOURCE = 1;
    public static final int PACKAGE_TYPE_JAVA_SOURCE = 2;
    public static final int PACKAGE_TYPE_JAVA_BYTECODE = 3;
    public static final int PACKAGE_TYPE_PYTHON2 = 4;
    public static final int PACKAGE_TYPE_PYTHON3 = 5;
    public static final String PACKAGE_SHARING_STATUS_PRIVATE = "private";
    public static final String PACKAGE_SHARING_STATUS_PUBLIC = "public";
    public static final String PACKAGE_SHARING_STATUS_SHARED = "shared";


    public PackageHandler(Session session) {
        super(session);
    }

    public static final String ENDPOINT_LIST = "packages/users/";
    // public static final String ENDPOINT_LIST = "packages/";


    public PackageThing create(String name,
                               String description,
                               int type) {
        return create(name, description, null, type, null);
    }

    public PackageThing create(String name,
                               String description,
                               String externalUri,
                               int type,
                               String pkg_lang) {
        ConversionMapImpl map = new ConversionMapImpl();
        map.put(PACKAGE_OWNER_UUID_KEY, getSession().getUserUID());
        // map.put(PACKAGE_OWNER_UUID_KEY, SWAMPIdentifiers.IDENTIFIER_CAPUT + "deadbeef-cafe-cafe-cafe-deadbeefdeadbeef");
        map.put(PACKAGE_SHARING_STATUS_KEY, PACKAGE_SHARING_STATUS_PRIVATE);
        map.put(PACKAGE_NAME_KEY, name);
        if (externalUri != null) {
            map.put(EXTERNAL_URI_KEY, externalUri);
        }
        map.put(PACKAGE_DESCRIPTION_KEY, description);
        map.put(PACKAGE_TYPE_ID_KEY, Integer.toString(type));
        if (pkg_lang != null) {
        	map.put(PACKAGE_LANGUAGE_KEY, pkg_lang.toLowerCase());
        }
        
        return (PackageThing) super.create(map);
    }

    public PackageThing create(String name,
    		String description,
    		String externalUri,
    		int type) {
    	ConversionMapImpl map = new ConversionMapImpl();
    	map.put(PACKAGE_OWNER_UUID_KEY, getSession().getUserUID());
    	// map.put(PACKAGE_OWNER_UUID_KEY, SWAMPIdentifiers.IDENTIFIER_CAPUT + "deadbeef-cafe-cafe-cafe-deadbeefdeadbeef");
    	map.put(PACKAGE_SHARING_STATUS_KEY, PACKAGE_SHARING_STATUS_PRIVATE);
    	map.put(PACKAGE_NAME_KEY, name);
    	if (externalUri != null) {
    		map.put(EXTERNAL_URI_KEY, externalUri);
    	}
    	map.put(PACKAGE_DESCRIPTION_KEY, description);
    	map.put(PACKAGE_TYPE_ID_KEY, Integer.toString(type));


    	return (PackageThing) super.create(map);
    }


    protected T fromJSON(JSONObject json) {
        T packageThing = (T) new PackageThing(getSession());
        ConversionMapImpl map = new ConversionMapImpl();
        String[] sAttrib = {PACKAGE_NAME_KEY, PACKAGE_DESCRIPTION_KEY, PACKAGE_TYPE_KEY, PACKAGE_TYPE_ID_KEY, PACKAGE_SHARING_STATUS_KEY, EXTERNAL_URI_KEY};
        String[] uAttrib = {PACKAGE_UUID_KEY};
        String[] bAttrib = {IS_OWNED_KEY};
        String[] dAttrib = {CREATE_DATE_KEY, UPDATE_DATE_KEY};
        String[] aAttrib = {VERSION_STRINGS};
        setAttributes(map, sAttrib, json, DATA_TYPE_STRING);
        setAttributes(map, uAttrib, json, DATA_TYPE_IDENTIFIER);
        setAttributes(map, bAttrib, json, DATA_TYPE_BOOLEAN);
        setAttributes(map, dAttrib, json, DATA_TYPE_DATE);
        setAttributes(map, aAttrib, json, DATA_TYPE_ARRAY);
        packageThing.setConversionMap(map);
        return packageThing;
    }

    public List<T> getAll() {
        MyResponse mr = null;
        mr = getClient().rawGet(createURL(ENDPOINT_LIST + getSession().getUserUID()), null);
        ArrayList<T> pkgs = new ArrayList<>();
        // For packages, the first call gets all the packages and individual calls to a specific url get
        // the rest of the information.
        for (int i = 0; i < mr.jsonArray.size(); i++) {
            JSONObject json = mr.jsonArray.getJSONObject(i);
            //String uuid = json.getString(PACKAGE_UUID_KEY);
            //String url = createURL("packages/" + uuid);
            //MyResponse mr2 = getClient().rawGet(url, null);
            //pkgs.add(fromJSON(mr2.json));
            pkgs.add(fromJSON(json));
        }
        return pkgs;
    }

    @Override
    public T get(Identifier identifier) {
        T t = super.get(identifier);
        List<PackageVersion> versions = (List<PackageVersion>) HandlerFactoryUtil.getPackageVersionH().getAll(t);
        t.setVersions(versions);
        return t;
    }

    /**
     * Return all the packages associated with a project.
     * @param project
     * @return
     */
    public List<T> getAll(Project project) {
        MyResponse mr = null;
        mr = getClient().rawGet(createURL("packages/protected/"+ project.getUUIDString()), null);
        ArrayList<T> pkgs = new ArrayList<>();
        // For packages, the first call gets all the packages and individual calls to a specific url get
        // the rest of the information.
        for (int i = 0; i < mr.jsonArray.size(); i++) {
            JSONObject json = mr.jsonArray.getJSONObject(i);
            //String uuid = json.getString(PACKAGE_UUID_KEY);
            //String url = createURL("packages/" + uuid);
            //MyResponse mr2 = getClient().rawGet(url, null);
            //pkgs.add(fromJSON(mr2.json));
            pkgs.add(fromJSON(json));
        }
        return pkgs;
    }

    
    @Override
    public String getURL() {
        return createURL("packages");
    }

    /*
    public List<String> getTypes() {
        String url = createURL("packages/types");
        MyResponse mr = getClient().rawGet(url, null);

        List<String> pkg_types = new ArrayList<String>();
        for (int i = 0; i < mr.jsonArray.size(); ++i){
        	pkg_types.add(mr.jsonArray.getJSONObject(i).getString("name"));
        }
        return pkg_types;
    }*/

    public Map<String, Integer> getTypes() {
    	String url = createURL("packages/types");
    	MyResponse mr = getClient().rawGet(url, null);

    	Map<String, Integer> pkg_types = new HashMap<String, Integer>();
    	for (int i = 0; i < mr.jsonArray.size(); ++i){
    		pkg_types.put(mr.jsonArray.getJSONObject(i).getString("name"),
    				Integer.valueOf(mr.jsonArray.getJSONObject(i).getInt("package_type_id")));
    	}
    	return pkg_types;
    }

    /*
     * Input: Package Type name
     * Output: Returns a platform UUID
     * 
     * */
    public String getDefaultPlatform(String pkg_type) {
        String url = createURL("packages/types");
        MyResponse mr = getClient().rawGet(url, null);
        String default_platform_uuid = null;
        
        
        for (int i = 0; i < mr.jsonArray.size(); ++i){
        	if (pkg_type.equals(mr.jsonArray.getJSONObject(i).getString("name"))){
        		default_platform_uuid = mr.jsonArray.getJSONObject(i).getString("default_platform_uuid");
        		break;
        	}
        }
        return default_platform_uuid;
    }

    public boolean deletePackage(PackageThing pkg) {
    	MyResponse mr = null;
    	mr = getClient().delete(getURL() + "/" + pkg.getUUIDString());
    	//if (mr.getHttpResponseCode() == HttpStatus.SC_OK) {
    	// This is incorrect, the setHttpResponseCode is not called to set the actual error 
    	if (mr.getHttpResponseCode() == 0) {
    		return true;
    	}else {
    		return false;
    	}
    }
} public class ConversionMapImpl extends HashMap<String, Object> implements ConversionMap<String, Object> {
    public static final boolean BOOLEAN_DEFAULT = false;
    public static final long LONG_DEFAULT = 0L;


    @Override
    public Date getDate(java.lang.String key) {
        return (Date) get(key);
    }

    @Override
    public boolean getBoolean(java.lang.String key) {
        Object x = get(key);
        if(x == null) return BOOLEAN_DEFAULT;
        return (boolean) x;
    }

    @Override
    public long getLong(java.lang.String key) {
        if(get(key) == null) return LONG_DEFAULT;
        return (long) get(key);
    }

    @Override
    public java.lang.String getString(String key) {
        Object x = get(key);
        if (x == null) return null;
        return x.toString();
    }


    @Override
    public Identifier getIdentifier(String key) {
        return (Identifier) get(key);
    }


    @Override
    public URI getURI(java.lang.String key) {
        Object x = get(key);
        if (x == null) return null;
        return URI.create(x.toString());
    }

    @Override
    public byte[] getBytes(java.lang.String key) {
        Object x = get(key);
        if (x.getClass().isArray()) {
            // try to return it...
            return (byte[]) x;
        }
        return null;
    }
}
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.http.HttpException;
import org.apache.http.client.CookieStore;
import org.apache.log4j.Logger;
import org.continuousassurance.swamp.api.AssessmentRecord;
import org.continuousassurance.swamp.api.AssessmentResults;
import org.continuousassurance.swamp.api.AssessmentRun;
import org.continuousassurance.swamp.api.PackageThing;
import org.continuousassurance.swamp.api.PackageVersion;
import org.continuousassurance.swamp.api.Platform;
import org.continuousassurance.swamp.api.PlatformVersion;
import org.continuousassurance.swamp.api.Project;
import org.continuousassurance.swamp.api.Tool;
import org.continuousassurance.swamp.api.ToolVersion;
import org.continuousassurance.swamp.api.User;
import org.continuousassurance.swamp.cli.exceptions.IncompatibleAssessmentTupleException;
import org.continuousassurance.swamp.cli.exceptions.InvalidIdentifierException;
import org.continuousassurance.swamp.cli.exceptions.InvalidNameException;
import org.continuousassurance.swamp.cli.exceptions.NoDefaultPlatformException;
import org.continuousassurance.swamp.cli.exceptions.SessionExpiredException;
import org.continuousassurance.swamp.cli.exceptions.SessionRestoreException;
import org.continuousassurance.swamp.cli.exceptions.SessionSaveException;
import org.continuousassurance.swamp.cli.exceptions.ToolPermissionException;
import org.continuousassurance.swamp.session.HTTPException;
import org.continuousassurance.swamp.session.Session;
import org.continuousassurance.swamp.session.handlers.HandlerFactory;
import org.continuousassurance.swamp.session.handlers.PackageHandler;
import org.continuousassurance.swamp.session.util.ConversionMapImpl;
import org.continuousassurance.swamp.session.util.Proxy;
import org.continuousassurance.swamp.session.util.SWAMPConfigurationLoader;
import org.continuousassurance.swamp.util.HandlerFactoryUtil;
import edu.uiuc.ncsa.security.util.ssl.SSLConfiguration;
import net.sf.json.JSONException;
						Files.move(csa_session, Paths.get(csaSessionObject), StandardCopyOption.ATOMIC_MOVE);
						Files.move(csa_cookies, Paths.get(csaCookies), StandardCopyOption.ATOMIC_MOVE);
					} catch (IOException e) {
					    LOGGER.error(null, e);
					}
				}
				
				try {
					Files.delete(old_dir);
				} catch (IOException e) {
				    LOGGER.error(null, e);
				}
			}
		}
	}

	//Code copied from https://stackoverflow.com/questions/41198379/sorting-version-numbers
	public int mycompare(String o1, String o2) {

	    if (o1 == null && o2 == null) {
	        return 0;
	    } else if (o1 == null && o2 != null) {
	        return -1;
	    } else if (o1 != null && o2 == null) {
	        return 1;
	    } else {
	        if (o1.length() == 0 && o2.length() == 0) {
	            return 0;
	        } else if (o1.length() == 0 && o2.length() > 0) {
	            return -1;
	        } else if (o1.length() > 0 && o2.length() == 0) {
	            return 1;
	        } else {
	            return compareVersion(o1, o2);
	        }
	    }
	}

	/**
	 * Reads and starts SWAMP session object/cookies in ~/.SWAMP_SESSION/
	 *
	 * @return true if valid, non-expired sessions instantiated 
	 */
	public boolean restoreSession() throws SessionExpiredException, SessionRestoreException {

		moveCookies();
		
		if (!SwampApiWrapper.fileExists(csaSessionObject) ||
				!SwampApiWrapper.fileExists(csaCookies)) {
			throw new SessionRestoreException("Could not locate session objects and cookies to recover the session");
		}

		try {
			Session csa_session = (Session)deserialize(csaSessionObject);
			handlerFactory = new HandlerFactory(csa_session);

			CookieStore csa_cookie_store = (CookieStore)deserialize(csaCookies);

			Date current_date = new Date();
			if (csa_cookie_store.clearExpired(current_date)){
				throw new SessionExpiredException("Session cookies expired");
			}

			handlerFactory.getCSASession().getClient().getContext().setCookieStore(csa_cookie_store);
			HandlerFactoryUtil.setHandlerFactory(handlerFactory);
		}catch (IOException e){
			throw new SessionRestoreException(e);
		}catch (ClassNotFoundException e){
			throw new SessionRestoreException(e);
		}

		return (handlerFactory.getUserHandler().getCurrentUser() != null);
	}

	public boolean hasToolPermission(String tool_uuid, String project_uuid, String package_uuid) {
        try {
            handlerFactory.getToolHandler().hasPermission(tool_uuid, project_uuid, package_uuid);
        }catch(HTTPException exp) {
            /*
             if (exp.getMessage().equalsIgnoreCase("no_permission") && exp.getStatusCode() == 401) {
                return false;
            }*/
            return false;
        }
        return true;
    }    

	
	public boolean hasToolPermission(Tool tool, PackageThing pkg, Project project) {
	    try {
	        handlerFactory.getToolHandler().hasPermission(tool, project, pkg);
	    }catch(HTTPException exp) {
	        /*if (exp.getMessage().equalsIgnoreCase("no_permission") && exp.getStatusCode() == 401) {
	            return false;
	        }*/
	        return false;
	    }
	    return true;
	}    

	/**
	 * Run multiple assessments, on a package with a set of tools on a set of platforms
	 *  
	 *  
	 *  @param pkg: package version object
	 *  @param tools: list of tool object
	 *  @param project: project object
	 *  @param platformVersions: list of platform object
	 *  
	 *  @return list of assessment run objects
	 *  
	 */
	protected List<AssessmentRun> runAssessment(PackageVersion pkg, List<Tool> tools, 
			Project project, List<PlatformVersion> platformVersions) {
		List<AssessmentRun> arun_list = new ArrayList<AssessmentRun>();
		for (PlatformVersion platform_version : platformVersions) {
			for (Tool tool : tools) {
			    try {
		            handlerFactory.getToolHandler().hasPermission(tool, project, pkg.getPackageThing());
		        }catch(HTTPException exp) {
		            throw new ToolPermissionException("No permission for the tool: '" + exp.getMessage() + "', " + tool);