SecoBlocks first commit.
diff --git a/org.eclipse.blockchain.server.ui/.classpath b/org.eclipse.blockchain.server.ui/.classpath
new file mode 100644
index 0000000..b862a29
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.blockchain.server.ui/.project b/org.eclipse.blockchain.server.ui/.project
new file mode 100644
index 0000000..92333ee
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.blockchain.server.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.blockchain.server.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.blockchain.server.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..295926d
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/org.eclipse.blockchain.server.ui/META-INF/MANIFEST.MF b/org.eclipse.blockchain.server.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..73826be
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Ui
+Bundle-SymbolicName: org.eclipse.blockchain.server.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: org.eclipse.blockchain.server.ui
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.eclipse.wst.server.ui,
+ org.eclipse.blockchain.server.core,
+ org.eclipse.swt,
+ org.eclipse.blockchain.core,
+ org.eclipse.core.runtime,
+ org.eclipse.wst.server.core,
+ org.eclipse.blockchain.ui,
+ org.eclipse.ui,
+ org.eclipse.ui.console,
+ org.eclipse.equinox.registry
+Export-Package: org.eclipse.blockchain.server.ui.wizard.fragment
diff --git a/org.eclipse.blockchain.server.ui/bin/.gitignore b/org.eclipse.blockchain.server.ui/bin/.gitignore
new file mode 100644
index 0000000..cf1db2e
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/bin/.gitignore
@@ -0,0 +1 @@
+/org/
diff --git a/org.eclipse.blockchain.server.ui/build.properties b/org.eclipse.blockchain.server.ui/build.properties
new file mode 100644
index 0000000..7001e8b
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ icon/
diff --git a/org.eclipse.blockchain.server.ui/icon/eth.png b/org.eclipse.blockchain.server.ui/icon/eth.png
new file mode 100644
index 0000000..da216e1
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/icon/eth.png
Binary files differ
diff --git a/org.eclipse.blockchain.server.ui/icon/sol.png b/org.eclipse.blockchain.server.ui/icon/sol.png
new file mode 100644
index 0000000..0c9abc3
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/icon/sol.png
Binary files differ
diff --git a/org.eclipse.blockchain.server.ui/plugin.xml b/org.eclipse.blockchain.server.ui/plugin.xml
new file mode 100644
index 0000000..8500d6b
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/plugin.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.wst.server.ui.serverImages">
+ <image
+ icon="icon/eth.png"
+ id="org.eclipse.blockchain.server.ui.test.image"
+ typeIds="org.eclipse.blockchain.server.core.TestServer,org.eclipse.blockchain.server.core.TestRuntime">
+ </image>
+ </extension>
+ <extension
+ point="org.eclipse.wst.server.ui.wizardFragments">
+ <fragment
+ class="org.eclipse.blockchain.server.ui.wizard.fragment.GethWizardFragment"
+ id="org.eclipse.blockchain.server.ui.test.wizard.fragment"
+ typeIds="org.eclipse.blockchain.server.core.TestServer">
+ </fragment>
+ </extension>
+
+</plugin>
diff --git a/org.eclipse.blockchain.server.ui/src/org/eclipse/blockchain/server/ui/wizard/fragment/GethWizardComposite.java b/org.eclipse.blockchain.server.ui/src/org/eclipse/blockchain/server/ui/wizard/fragment/GethWizardComposite.java
new file mode 100644
index 0000000..c4fd68a
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/src/org/eclipse/blockchain/server/ui/wizard/fragment/GethWizardComposite.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) Robert Bosch GmbH. All rights reserved.
+ */
+package org.eclipse.blockchain.server.ui.wizard.fragment;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.blockchain.core.BlockchainCore;
+import org.eclipse.blockchain.core.CoreCommandExecutor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+
+/**
+ * This is just a proto-type class and not constructed fully.
+ *
+ * @author ADG5COB
+ */
+public class GethWizardComposite extends Composite {
+
+ private IWizardHandle wizard = null;
+ private Text dataDirText;
+ private Text initFileText;
+ private final String userDir = System.getProperty("user.dir");
+ private String networkId = "";
+ private Label networkIdLabel;
+ private final Map<String, String> gethOptions = new HashMap<>();
+ private String dataDirectory = "";
+ private String genesisFile = "";
+
+ /**
+ * @return -
+ */
+ protected String getDataDirectory() {
+ return this.dataDirectory;
+ }
+
+ /**
+ * @return -
+ */
+ protected String getGenesisFile() {
+ return this.genesisFile;
+ }
+
+ /**
+ * @return -
+ */
+ protected Map<String, String> getGethOptions() {
+ return this.gethOptions;
+ }
+
+ /**
+ *
+ */
+ GethWizardComposite(final Composite parent, final IWizardHandle wizard) {
+ super(parent, SWT.NONE);
+ this.wizard = wizard;
+ this.wizard.setTitle("Geth Server");
+ this.wizard.setDescription("This is used to start a geth server instance");
+
+ populateGethOptions();
+
+ createDialogArea();
+ }
+
+ private void createDialogArea() {
+ GridLayout layout = new GridLayout();
+ setLayout(layout);
+ setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Composite containerComp = new Composite(this, SWT.None);
+ containerComp.setLayout(new GridLayout(3, false));
+ containerComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ createContent(containerComp);
+ }
+
+ private void createContent(final Composite containerComp) {
+ // First Layer
+ Label dataDirLabel = new Label(containerComp, SWT.None);
+ dataDirLabel.setText("Data Directory");
+ dataDirLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+
+ this.dataDirText = new Text(containerComp, SWT.BORDER);
+ this.dataDirText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ this.dataDirText.setText("");
+ this.dataDirText.setToolTipText(this.dataDirText.getText());
+
+ this.dataDirText.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(final ModifyEvent e) {
+ GethWizardComposite.this.dataDirectory = GethWizardComposite.this.dataDirText.getText();
+ GethWizardComposite.this.wizard.update();
+ }
+ });
+
+ Button dataDirBrowse = new Button(containerComp, SWT.PUSH);
+ dataDirBrowse.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+ dataDirBrowse.setText("Browse");
+ dataDirBrowse.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ getAndSetSelectedDirectoryNode(containerComp, GethWizardComposite.this.dataDirText);
+ GethWizardComposite.this.dataDirectory = GethWizardComposite.this.dataDirText.getText();
+ GethWizardComposite.this.wizard.update();
+ }
+ });
+
+ // Second Layer
+ Label initFileLabel = new Label(containerComp, SWT.None);
+ initFileLabel.setText("Init File");
+ initFileLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+
+ this.initFileText = new Text(containerComp, SWT.BORDER);
+ this.initFileText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ this.initFileText.setText("");
+ this.initFileText.setToolTipText("Under development!!!");
+ this.initFileText.setEnabled(false);
+
+ Button initFileBrowse = new Button(containerComp, SWT.PUSH);
+ initFileBrowse.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+ initFileBrowse.setText("Browse");
+ initFileBrowse.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ getandSetSelectedGenesisFile(containerComp, GethWizardComposite.this.initFileText);
+ }
+ });
+
+ // Scrolled Composite - contains network values
+ ScrolledComposite networkComposite = new ScrolledComposite(containerComp, SWT.V_SCROLL | SWT.BORDER);
+ networkComposite.setLayout(new GridLayout(1, false));
+ networkComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 3, 0));
+ Composite networkChild = createdScrolledContent(networkComposite);
+
+ networkComposite.setContent(networkChild);
+ networkComposite.setMinSize(networkComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ networkComposite.setExpandHorizontal(true);
+ networkComposite.setExpandVertical(true);
+ networkComposite.layout();
+ }
+
+ private Composite createdScrolledContent(final ScrolledComposite scrolledComposite) {
+ /**
+ * This contains the geth arguments which should be made configurable, as of now its static but networkId will be
+ * read from the genesis file
+ */
+ Composite childComp = new Composite(scrolledComposite, SWT.None);
+ childComp.setLayout(new GridLayout(1, false));
+ childComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ Group networkGroup = new Group(childComp, SWT.BORDER);
+ networkGroup.setLayout(new GridLayout(1, false));
+ networkGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ networkGroup.setText("Network");
+
+ this.networkIdLabel = new Label(networkGroup, SWT.None | SWT.READ_ONLY);
+ this.networkIdLabel.setText("Network ID : " +
+ (this.networkId.isEmpty() ? CoreCommandExecutor.getInstance().getDefaultNetworkIdForGeth() : this.networkId));
+
+ Group rpcGroup = new Group(childComp, SWT.BORDER);
+ rpcGroup.setLayout(new GridLayout(1, false));
+ rpcGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ rpcGroup.setText("RPC");
+
+ for (Map.Entry<String, String> entry : this.gethOptions.entrySet()) {
+ Label lab = new Label(rpcGroup, SWT.None);
+ String val = entry.getValue();
+ lab.setText(entry.getKey() + (val.isEmpty() ? "" : " : " + val));
+ }
+ return childComp;
+ }
+
+ private void getandSetSelectedGenesisFile(final Composite parent, final Text textWidget) {
+ FileDialog dataDir = new FileDialog(parent.getShell());
+ dataDir.setFilterPath(this.userDir);
+ String selectedDir = dataDir.open();
+ if (selectedDir != null) {
+ textWidget.setText(selectedDir);
+ try (BufferedReader br = new BufferedReader(new FileReader(new File(selectedDir)))) {
+ String contents = "";
+ while ((contents = br.readLine()) != null) {
+ if (contents.contains("chainId")) {
+ this.networkId = contents.substring(contents.indexOf(':') + 1).replace(",", "").trim();
+ this.networkIdLabel.setText("Network ID : " + this.networkId);
+ this.networkIdLabel.getParent().layout();
+ }
+ }
+ }
+ catch (IOException e) {
+ BlockchainCore.getInstance().logException("org.eclipse.blockchain.server.ui", e.getMessage(), e);
+ }
+ }
+ }
+
+ /**
+ * @return - true if wizard is complete with out any errors, false otherwise
+ */
+ public boolean isWizardComplete() {
+ boolean dataDirectoryPresent = false;
+ // The validation should be done here
+ if ((this.dataDirectory != null) && !this.dataDirectory.equals("")) {
+ File folder = new File(this.dataDirectory);
+ if (folder.exists()) {
+ dataDirectoryPresent = true;
+ }
+ else {
+ this.wizard.setDescription("Data directory path is not valid");
+ }
+ }
+
+ return dataDirectoryPresent;
+ }
+
+ private void getAndSetSelectedDirectoryNode(final Composite parent, final Text textWidget) {
+ DirectoryDialog dirDialog = new DirectoryDialog(parent.getShell());
+ dirDialog.setFilterPath(this.userDir);
+ String selectedDir = dirDialog.open();
+ if (selectedDir != null) {
+ textWidget.setText(selectedDir);
+ }
+ }
+
+ private void populateGethOptions() {
+ this.gethOptions.put("rpc", "");
+ this.gethOptions.put("rpccorsdomain", "*");
+ this.gethOptions.put("rpcapi", "db,eth,net,web3,personal");
+ this.gethOptions.put("gcmode", "archive");
+ }
+
+ /**
+ *
+ */
+ protected void prePerformFinish() {
+ this.dataDirectory = getTextValue(this.dataDirText);
+ this.genesisFile = getTextValue(this.initFileText);
+ }
+
+ private String getTextValue(final Text inputText) {
+ StringBuffer textValueBuffer = new StringBuffer();
+ Display.getDefault().syncExec(() -> {
+ textValueBuffer.append(inputText.getText());
+ });
+ return textValueBuffer.toString();
+ }
+
+}
diff --git a/org.eclipse.blockchain.server.ui/src/org/eclipse/blockchain/server/ui/wizard/fragment/GethWizardFragment.java b/org.eclipse.blockchain.server.ui/src/org/eclipse/blockchain/server/ui/wizard/fragment/GethWizardFragment.java
new file mode 100644
index 0000000..de8978b
--- /dev/null
+++ b/org.eclipse.blockchain.server.ui/src/org/eclipse/blockchain/server/ui/wizard/fragment/GethWizardFragment.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) Robert Bosch GmbH. All rights reserved.
+ */
+package org.eclipse.blockchain.server.ui.wizard.fragment;
+
+import java.util.Set;
+
+import org.eclipse.blockchain.core.BlockchainCore;
+import org.eclipse.blockchain.core.CoreCommandExecutor;
+import org.eclipse.blockchain.core.Web3jHandler;
+import org.eclipse.blockchain.ui.views.AccountsView;
+import org.eclipse.blockchain.ui.views.EtherAccountViewPart;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchListener;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+
+/**
+ * This is just a proto-type class and not constructed fully.
+ *
+ * @author ADG5COB
+ */
+public class GethWizardFragment extends WizardFragment {
+
+ private GethWizardComposite gethComposite;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean hasComposite() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Composite createComposite(final Composite parent, final IWizardHandle handle) {
+ this.gethComposite = new GethWizardComposite(parent, handle);
+ return this.gethComposite;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isComplete() {
+ if (this.gethComposite != null) {
+ return this.gethComposite.isWizardComplete();
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void performFinish(final IProgressMonitor monitor) throws CoreException {
+ this.gethComposite.prePerformFinish();
+ String anyErrors = startServer();
+ if (anyErrors.isEmpty()) {
+ Display.getDefault().syncExec(() -> {
+ EtherAccountViewPart.updateView();
+ });
+ // Below activation should happen from UI-Thread
+ // PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
+ // .activate(PlatformUI.getWorkbench().getViewRegistry().find("").createView().getSite().getPart());
+ super.performFinish(monitor);
+ }
+ else {
+ getTaskModel().putObject("server", null);
+ super.performCancel(monitor);
+ }
+ }
+
+ /**
+ * This will restrict other default child fragments from getting displayed. {@inheritDoc}
+ */
+ @Override
+ public boolean isForceLastFragment() {
+ return true;
+ }
+
+ private String startServer() {
+ try {
+ String anyErrors = CoreCommandExecutor.getInstance().startGethServer(this.gethComposite.getDataDirectory(),
+ this.gethComposite.getGenesisFile(), this.gethComposite.getGethOptions());
+ Web3jHandler web3j = Web3jHandler.getInstance();
+ if (!anyErrors.isEmpty()) {
+ showError(anyErrors);
+ return anyErrors;
+ }
+ anyErrors = web3j.createInitialAccounts();
+ if (!anyErrors.isEmpty()) {
+ showError(anyErrors);
+ return anyErrors;
+ }
+ Set<String> accounts = web3j.getAccount().getAccounts().keySet();
+ AccountsView.setAccountsCombo(accounts.toArray(new String[accounts.size()]));
+ PlatformUI.getWorkbench().getDisplay();
+ Display.getDefault().syncExec(() -> {
+ EtherAccountViewPart.updateView();
+ });
+ }
+ catch (Exception e) {
+ BlockchainCore.getInstance().logException("org.eclipse.blockchain.server.ui", e.getMessage(), e);
+ }
+ PlatformUI.getWorkbench().addWorkbenchListener(new IWorkbenchListener() {
+
+ @Override
+ public boolean preShutdown(final IWorkbench workbench, final boolean forced) {
+ CoreCommandExecutor.getInstance().terminateGethServer();
+ return true;
+ }
+
+ @Override
+ public void postShutdown(final IWorkbench workbench) {
+ /**
+ * Not required
+ */
+ }
+ });
+ return "";
+ }
+
+ private void showError(final String anyErrors) {
+ Display.getDefault().syncExec(() -> {
+ MessageDialog errorDialog = new MessageDialog(Display.getDefault().getActiveShell(), "Geth Server Start Error",
+ null, anyErrors, MessageDialog.ERROR, new String[] { "OK" }, 0);
+ errorDialog.open();
+ });
+ }
+}