/** | |
* 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); | |
} | |
} | |
} |