| /** |
| * Copyright (c) 2020 RBEI and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v. 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Adhith Gopal - Initial API and Implementation |
| * |
| */ |
| package org.eclipse.blockchain.model.core; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| |
| import org.eclipse.blockchain.model.ethproject.DeploymentModel; |
| import org.eclipse.blockchain.model.ethproject.EthereumProject; |
| import org.eclipse.blockchain.model.ethproject.EthprojectFactory; |
| import org.eclipse.blockchain.model.ethproject.EthprojectPackage; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceVisitor; |
| import org.eclipse.core.runtime.CoreException; |
| |
| /** |
| * |
| * EMF Notification mechanism is not used here, if required then Adapter's have |
| * to be created and registered in the list of adapters |
| */ |
| public class EthereumProjectHandler { |
| private static EthereumProjectHandler instance = null; |
| private final Map<String, EthereumProject> projectMap = new HashMap<>(); |
| |
| private EthereumProjectHandler() { |
| } |
| |
| /** |
| * @return This provides an Ethereum Project Handle which can be used to |
| * manipulate the Ethereum Project |
| */ |
| public static EthereumProjectHandler getInstance() { |
| if (null == instance) { |
| instance = new EthereumProjectHandler(); |
| /** |
| * This is just to initialize the EMF model and listeners |
| */ |
| EthprojectPackage.eINSTANCE.eClass(); |
| } |
| return instance; |
| } |
| |
| /** |
| * This returns the Ethereum Project instance that matches the project name. If |
| * none match then a new Ethereum Project instance is created |
| * |
| * @param projectName - The name of the project |
| * @return - EthereumProject |
| */ |
| public EthereumProject getEthProject(final String projectName) { |
| return this.projectMap.computeIfAbsent(projectName, (v) -> { |
| EthereumProject ethProj = EthprojectFactory.eINSTANCE.createEthereumProject(); |
| /** |
| * Initialize all collections so that no NPE gets thrown |
| */ |
| ethProj.setProjectBuilders(new ArrayList<>()); |
| ethProj.setProjectNatures(new ArrayList<>()); |
| ethProj.setCompiledSolidityFiles(new HashSet<>()); |
| ethProj.setEnvironmentBasedDeployedModel(new HashMap<>()); |
| return ethProj; |
| }); |
| } |
| |
| /** |
| * Remove the project from the map |
| * |
| * @param projectName - The name of project which should be removed. |
| */ |
| public void removeEthProject(final String projectName) { |
| this.projectMap.remove(projectName); |
| } |
| |
| /** |
| * Adds the given nature to the list of project natures of ethereum project |
| * |
| * @param ethProject - The Ethereum Project for which nature should be added |
| * @param natureId - The nature id string |
| */ |
| public void addProjectNature(final EthereumProject ethProject, final String natureId) { |
| ethProject.getProjectNatures().add(natureId); |
| } |
| |
| /** |
| * Adds the given builder to the list of project builders of ethereum project |
| * |
| * @param ethProject - The Ethereum Project for which nature should be added |
| * @param builderId - The builder id string |
| */ |
| public void addProjectBuilder(final EthereumProject ethProject, final String builderId) { |
| ethProject.getProjectBuilders().add(builderId); |
| } |
| |
| /** |
| * @param projectName - The ethereum Project name for which first matching sol |
| * file should be returned |
| * @return - The first matching sol file, if none then null |
| * @throws CoreException - |
| */ |
| public IFile getSolFile(final String projectName) throws CoreException { |
| EthereumProject ethProject = this.projectMap.get(projectName); |
| IProject project = ethProject.getProject(); |
| if (project != null) { |
| project.accept(new IResourceVisitor() { |
| |
| @Override |
| public boolean visit(final IResource resource) throws CoreException { |
| if ((resource instanceof IFile) && (resource.getFileExtension() != null) |
| && resource.getFileExtension().equals("sol")) { |
| ethProject.setFirstMatchingSolFile(resource.getProjectRelativePath().toOSString()); |
| return false; |
| } |
| return true; |
| } |
| }); |
| return (IFile) project.findMember(ethProject.getFirstMatchingSolFile()); |
| } |
| return null; |
| } |
| |
| /** |
| * This method is used to add the compiled solidity files to the set that is |
| * maintained in this project |
| * |
| * @param solidityFile - The compiled solidity file that belongs to this project |
| */ |
| public void addCompiledSolidityFiles(final IResource solidityFile) { |
| EthereumProject ethProject = this.projectMap.get(solidityFile.getProject().getName()); |
| ethProject.getCompiledSolidityFiles().add(solidityFile.getProjectRelativePath().toOSString()); |
| } |
| |
| /** |
| * |
| * @param scFile - The SC resource |
| * @param environment - This denotes the environment into which this SC is |
| * deployed(Embedded/Geth) |
| * @return - Whether the SC is deployed into the passed in environment |
| */ |
| public boolean isSCDeployed(final IResource scFile, final String environment) { |
| Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName()) |
| .getEnvironmentBasedDeployedModel().get(environment); |
| return (map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString()); |
| } |
| |
| /** |
| * This creates a deployment model for a smart contract that is deployed into a |
| * blockchain |
| * |
| * @param contractAddress - The contract address of the deployed SC |
| * @param scFile - The SC resource |
| * @param lastUsedAccount - The account that was last used for performing a |
| * transaction |
| * @param environment - This denotes the environment into which this SC is |
| * deployed(Embedded/Geth) |
| */ |
| public void createDeploymentModel(final String contractAddress, final IResource scFile, |
| final String lastUsedAccount, final String environment) { |
| DeploymentModel deploymentModel = EthprojectFactory.eINSTANCE.createDeploymentModel(); |
| deploymentModel.setContractAddress(contractAddress); |
| deploymentModel.setScFile(scFile.getProjectRelativePath().toOSString()); |
| deploymentModel.setLastUsedAccount(lastUsedAccount); |
| deploymentModel.setEnvironment(environment); |
| |
| EthereumProject ethProject = this.projectMap.get(scFile.getProject().getName()); |
| /** |
| * The below addition will add all the DM's that get created to the ETHProj |
| * model and will be serialized during modal save. |
| */ |
| ethProject.getDeploymentmodel().add(deploymentModel); |
| Map<String, DeploymentModel> depModelMap = ethProject.getEnvironmentBasedDeployedModel() |
| .computeIfAbsent(environment, m -> new HashMap<>()); |
| depModelMap.put(scFile.getProjectRelativePath().toOSString(), deploymentModel); |
| } |
| |
| /** |
| * |
| * @param scFile - The SC resource |
| * @param environment - This denotes the environment into which this SC is |
| * deployed(Embedded/Geth) |
| * @return - The account that was last used for performing a transaction |
| */ |
| public String getLastUsedAccount(final IResource scFile, final String environment) { |
| Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName()) |
| .getEnvironmentBasedDeployedModel().get(environment); |
| if ((map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString())) { |
| return map.get(scFile.getProjectRelativePath().toOSString()).getLastUsedAccount(); |
| } |
| return ""; |
| } |
| |
| /** |
| * This is used to update the last used account(for transacting with blockchain) |
| * |
| * @param scFile - The SC resource |
| * @param accountDetails - The new account that was used for transaction |
| * @param environment - This denotes the environment into which this SC is |
| * deployed(Embedded/Geth) |
| */ |
| public void updateLastUsedAccount(final IResource scFile, final String accountDetails, final String environment) { |
| Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName()) |
| .getEnvironmentBasedDeployedModel().get(environment); |
| if ((map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString())) { |
| map.get(scFile.getProjectRelativePath().toOSString()).setLastUsedAccount(accountDetails); |
| } |
| } |
| |
| /** |
| * |
| * @param scFile - The SC resource |
| * @param environment - This denotes the environment into which this SC is |
| * deployed(Embedded/Geth) |
| * @return - The contract address of the deployed SC |
| */ |
| public String getContractAddress(final IResource scFile, final String environment) { |
| Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName()) |
| .getEnvironmentBasedDeployedModel().get(environment); |
| if ((map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString())) { |
| return map.get(scFile.getProjectRelativePath().toOSString()).getContractAddress(); |
| } |
| return ""; |
| } |
| |
| /** |
| * This method is used to remove the SC resource from the map which holds |
| * deployed resources |
| * |
| * @param projectName - The ethereum project name from which SC should be |
| * removed |
| * @param resource - The SC resource |
| * @param environment - This denotes the environment into which this SC is |
| * deployed(Embedded/Geth) |
| */ |
| public void removeDeploymentModelForResource(final IResource resource, final String environment) { |
| EthereumProject ethProject = this.projectMap.get(resource.getProject().getName()); |
| if (null == ethProject) { |
| return; |
| } |
| Map<String, Map<String, DeploymentModel>> envMap = ethProject.getEnvironmentBasedDeployedModel(); |
| if (null == envMap) { |
| return; |
| } |
| Map<String, DeploymentModel> map = envMap.get(environment); |
| if ((map != null) && map.containsKey(resource.getProjectRelativePath().toOSString())) { |
| DeploymentModel dm = map.remove(resource.getProjectRelativePath().toOSString()); |
| /** |
| * Also remove from ethProject |
| */ |
| ethProject.getDeploymentmodel().remove(dm); |
| } |
| } |
| } |