From: Mathieu Baudier Date: Sun, 10 Nov 2013 19:17:35 +0000 (+0000) Subject: JDBC, SSH command (+ pseudo file retrieval) and keyring X-Git-Tag: argeo-slc-2.1.7~288 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=ee9455a85f291bd41955aae4ab406f381b5dfd9a;p=gpl%2Fargeo-slc.git JDBC, SSH command (+ pseudo file retrieval) and keyring git-svn-id: https://svn.argeo.org/slc/trunk@6610 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/modules/org.argeo.slc.akb.services/META-INF/spring/services-osgi.xml b/modules/org.argeo.slc.akb.services/META-INF/spring/services-osgi.xml index 9b792f372..cbc38157a 100644 --- a/modules/org.argeo.slc.akb.services/META-INF/spring/services-osgi.xml +++ b/modules/org.argeo.slc.akb.services/META-INF/spring/services-osgi.xml @@ -23,4 +23,7 @@ + + + diff --git a/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml b/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml index fc42e1386..0711d6555 100644 --- a/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml +++ b/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml @@ -8,6 +8,7 @@ + diff --git a/modules/org.argeo.slc.akb.services/pom.xml b/modules/org.argeo.slc.akb.services/pom.xml index 5b3c4f919..0618a7119 100644 --- a/modules/org.argeo.slc.akb.services/pom.xml +++ b/modules/org.argeo.slc.akb.services/pom.xml @@ -19,7 +19,7 @@ *, - org.argeo.slc.akb + org.argeo.slc.akb, diff --git a/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml b/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml index 52d134018..730a9c661 100644 --- a/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml +++ b/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml @@ -18,13 +18,16 @@ + + + \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/pom.xml b/plugins/org.argeo.slc.akb.ui/pom.xml index e5f2c2d17..c40bca7b1 100644 --- a/plugins/org.argeo.slc.akb.ui/pom.xml +++ b/plugins/org.argeo.slc.akb.ui/pom.xml @@ -51,6 +51,11 @@ org.argeo.eclipse.ui ${version.argeo-commons} + + org.argeo.commons.security + org.argeo.security.ui + ${version.argeo-commons} + diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/ConnectorAliasEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/ConnectorAliasEditor.java index b272a38f4..a69fdcf3a 100644 --- a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/ConnectorAliasEditor.java +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/ConnectorAliasEditor.java @@ -3,6 +3,7 @@ package org.argeo.slc.akb.ui.editors; import javax.jcr.Property; import javax.jcr.RepositoryException; +import org.argeo.eclipse.ui.ErrorFeedback; import org.argeo.slc.akb.AkbException; import org.argeo.slc.akb.AkbNames; import org.argeo.slc.akb.AkbTypes; @@ -106,7 +107,7 @@ public class ConnectorAliasEditor extends AbstractAkbNodeEditor { public void modifyText(ModifyEvent event) { try { // TODO enhance this - // retrieve old and new node type + // retrieve old and new node type int oldIndex = getCurrTypeIndex(); int selIndex = typeCmb.getSelectionIndex(); @@ -158,12 +159,16 @@ public class ConnectorAliasEditor extends AbstractAkbNodeEditor { Composite firstLine = getToolkit().createComposite(group); firstLine.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - firstLine.setLayout(new GridLayout(3, false)); + firstLine.setLayout(new GridLayout(2, false)); getToolkit().createLabel(firstLine, "URL"); final Text urlTxt = getToolkit().createText(firstLine, "", SWT.BORDER); urlTxt.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + getToolkit().createLabel(firstLine, "User"); + final Text userTxt = getToolkit().createText(firstLine, "", SWT.BORDER); + userTxt.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + final Button testBtn = getToolkit().createButton(firstLine, "Test connection", SWT.PUSH); // testBtn.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, @@ -176,17 +181,27 @@ public class ConnectorAliasEditor extends AbstractAkbNodeEditor { // update display value AkbUiUtils.refreshFormTextWidget(urlTxt, getAkbNode(), AkbNames.AKB_CONNECTOR_URL); + AkbUiUtils.refreshFormTextWidget(userTxt, getAkbNode(), + AkbNames.AKB_CONNECTOR_USER); } }; // Listeners AkbUiUtils.addTextModifyListener(urlTxt, getAkbNode(), AkbNames.AKB_CONNECTOR_URL, part); + AkbUiUtils.addTextModifyListener(userTxt, getAkbNode(), + AkbNames.AKB_CONNECTOR_USER, part); testBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - boolean testSuccesfull = getAkbService().testConnector( - getAkbNode()); + boolean testSuccesfull; + try { + testSuccesfull = getAkbService() + .testConnector(getAkbNode()); + } catch (Exception e1) { + testSuccesfull = false; + ErrorFeedback.show("Cannot test connection", e1); + } String name = AkbJcrUtils.get(getAkbNode(), Property.JCR_TITLE); String url = AkbJcrUtils.get(getAkbNode(), diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/JdbcQueryTemplateEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/JdbcQueryTemplateEditor.java index aea5f0aea..078db17ba 100644 --- a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/JdbcQueryTemplateEditor.java +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/JdbcQueryTemplateEditor.java @@ -9,6 +9,7 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PartInitException; import org.eclipse.ui.forms.AbstractFormPart; import org.eclipse.ui.forms.IManagedForm; @@ -58,4 +59,10 @@ public class JdbcQueryTemplateEditor extends AkbItemTemplateEditor { managedForm.addPart(part); } + @Override + protected void addOtherPages() throws PartInitException { + addPage(new JdbcTestPage(getAkbService(), this, "testPage", "Test", + getAkbNode())); + } + } diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/JdbcTestPage.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/JdbcTestPage.java new file mode 100644 index 000000000..7189f5f24 --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/JdbcTestPage.java @@ -0,0 +1,215 @@ +package org.argeo.slc.akb.ui.editors; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; + +import org.argeo.security.ui.PrivilegedJob; +import org.argeo.slc.SlcException; +import org.argeo.slc.akb.AkbNames; +import org.argeo.slc.akb.AkbService; +import org.argeo.slc.akb.ui.AkbUiUtils; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ILazyContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +/** Test JDBC. */ +public class JdbcTestPage extends FormPage implements AkbNames { + private Node node; + private AkbService akbService; + + private TableViewer viewer = null; + private IContentProvider contentProvider; + + private PreparedStatement statement; + + public JdbcTestPage(AkbService akbService, FormEditor editor, String id, + String title, Node node) { + super(editor, id, title); + this.akbService = akbService; + this.node = node; + } + + protected void createFormContent(IManagedForm managedForm) { + super.createFormContent(managedForm); + ScrolledForm form = managedForm.getForm(); + form.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + Composite parent = form.getBody(); + + parent.setLayout(AkbUiUtils.gridLayoutNoBorder()); + FormToolkit toolkit = getEditor().getToolkit(); + Table table = toolkit.createTable(parent, SWT.VIRTUAL); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + table.setHeaderVisible(true); + table.setLinesVisible(true); + viewer = new TableViewer(table); + contentProvider = new JdbcTestContentProvider(viewer); + viewer.setContentProvider(contentProvider); + // viewer.setLabelProvider(new ColumnLabelProvider(){}); + + statement = akbService.prepareJdbcQuery(node); + PrivilegedJob job = new PrivilegedJob("Execute query on " + node) { + + @Override + protected IStatus doRun(IProgressMonitor progressMonitor) { + try { + final ResultSet resultSet = statement.executeQuery(); + getEditorSite().getWorkbenchWindow().getShell() + .getDisplay().syncExec(new Runnable() { + + @Override + public void run() { + viewer.setInput(resultSet); + } + }); + return Status.OK_STATUS; + } catch (SQLException e) { + throw new SlcException("Cannot execute " + node, e); + } + } + }; + job.schedule(); + } + + @Override + public void dispose() { + try { + statement.close(); + statement.getConnection().close(); + } catch (SQLException e) { + // silent + } + } + + private class JdbcTestContentProvider implements ILazyContentProvider { + private TableViewer viewer; + private ResultSet resultSet; + private boolean isScrollable; + + private List buffer = new ArrayList(); + + private List columns = new ArrayList(); + private Integer columnCount = 0; + + private int rowCount = 0; + + public JdbcTestContentProvider(TableViewer viewer) { + this.viewer = viewer; + } + + public void dispose() { + try { + resultSet.close(); + } catch (SQLException e) { + // silent + } + } + + public void inputChanged(Viewer v, Object oldInput, Object newInput) { + if (newInput == null) + return; + + TableViewer viewer = (TableViewer) v; + + resultSet = (ResultSet) newInput; + try { + isScrollable = resultSet.getType() != ResultSet.TYPE_FORWARD_ONLY; + columnCount = resultSet.getMetaData().getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + columns.add(new JdbcColumn(i, resultSet.getMetaData())); + if (oldInput == null)// first time + addColumn(viewer, i - 1); + } + + if (isScrollable) { + if (resultSet.next()) + rowCount = 1; + viewer.setItemCount(rowCount); + } else { + while (resultSet.next()) { + Object[] lst = new Object[columnCount]; + for (int i = 1; i <= columnCount; i++) { + lst[i - 1] = resultSet.getObject(i); + buffer.add(lst); + } + } + viewer.setItemCount(buffer.size()); + } + + } catch (SQLException e) { + throw new SlcException("Cannot configure JDBC column", e); + } + } + + protected void addColumn(TableViewer viewer, final int index) { + TableViewerColumn col = new TableViewerColumn(viewer, SWT.NONE); + col.getColumn().setWidth(100); + col.getColumn().setText(columns.get(index).name); + col.setLabelProvider(new ColumnLabelProvider() { + @Override + public String getText(Object element) { + return ((Object[]) element)[index].toString(); + } + }); + } + + public void updateElement(int index) { + if (resultSet == null) + return; + + try { + if (isScrollable) { + resultSet.absolute(index + 1); + Object[] lst = new Object[columnCount]; + for (int i = 1; i <= columnCount; i++) { + lst[i - 1] = resultSet.getObject(i); + } + viewer.replace(lst, index); + int itemCount = viewer.getTable().getItemCount(); + if (index == (itemCount - 1) && resultSet.next()) + viewer.setItemCount(itemCount + 1); + } else { + viewer.replace(buffer.get(index), index); + } + } catch (Exception e) { + throw new SlcException("Cannot update element", e); + } + } + } + + private class JdbcColumn { + // public final Integer index; + public final String name; + + // public final Integer type; + + public JdbcColumn(int index, ResultSetMetaData metaData) + throws SQLException { + // this.index = index; + this.name = metaData.getColumnName(index); + // this.type = metaData.getColumnType(index); + + } + } + +} diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshCommandTemplateEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshCommandTemplateEditor.java index 7c730502c..a91420c43 100644 --- a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshCommandTemplateEditor.java +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshCommandTemplateEditor.java @@ -4,6 +4,7 @@ import org.argeo.slc.akb.AkbNames; import org.argeo.slc.akb.ui.AkbUiPlugin; import org.argeo.slc.akb.ui.AkbUiUtils; import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; @@ -25,13 +26,28 @@ public class SshCommandTemplateEditor extends AkbItemTemplateEditor { return ID; } + @Override + protected void populateTestPage(Composite parent) { + parent.setLayout(AkbUiUtils.gridLayoutNoBorder()); + + Text outputDisplay = getToolkit().createText(parent, "", SWT.MULTI); + outputDisplay.setFont(new Font(parent.getDisplay(), "Monospaced", 10, + SWT.NONE)); + outputDisplay.setEditable(false); + outputDisplay + .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + String output = getAkbService().executeCommand(getAkbNode()); + outputDisplay.setText(output); + } + @Override protected void populateBottomPart(Composite parent, IManagedForm managedForm) { parent.setLayout(AkbUiUtils.gridLayoutNoBorder()); Group group = new Group(parent, SWT.NO_FOCUS); getToolkit().adapt(group, false, false); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - + group.setLayout(new GridLayout(1, false)); // first line: Description diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshFileTemplateEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshFileTemplateEditor.java index d4712bcc8..309bedeba 100644 --- a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshFileTemplateEditor.java +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/SshFileTemplateEditor.java @@ -4,6 +4,7 @@ import org.argeo.slc.akb.AkbNames; import org.argeo.slc.akb.ui.AkbUiPlugin; import org.argeo.slc.akb.ui.AkbUiUtils; import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; @@ -25,6 +26,21 @@ public class SshFileTemplateEditor extends AkbItemTemplateEditor { return ID; } + @Override + protected void populateTestPage(Composite parent) { + parent.setLayout(AkbUiUtils.gridLayoutNoBorder()); + + Text outputDisplay = getToolkit().createText(parent, "", SWT.MULTI); + outputDisplay.setFont(new Font(parent.getDisplay(), "Monospaced", 10, + SWT.NONE)); + outputDisplay.setEditable(false); + outputDisplay + .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + String output = getAkbService().retrieveFile(getAkbNode()); + outputDisplay.setText(output); + } + @Override protected void populateBottomPart(Composite parent, IManagedForm managedForm) { parent.setLayout(AkbUiUtils.gridLayoutNoBorder()); diff --git a/runtime/org.argeo.slc.akb/pom.xml b/runtime/org.argeo.slc.akb/pom.xml index 66f502715..f6e27e7e5 100644 --- a/runtime/org.argeo.slc.akb/pom.xml +++ b/runtime/org.argeo.slc.akb/pom.xml @@ -20,6 +20,14 @@ *, javax.jcr.nodetype, + com.microsoft.sqlserver.jdbc;resolution:=optional, + com.mysql.jdbc;resolution:=optional, + net.sourceforge.jtds.jdbc;resolution:=optional, + oracle.jdbc;resolution:=optional, + org.apache.derby.jdbc;resolution:=optional, + org.h2;resolution:=optional, + org.hsqldb;resolution:=optional, + org.postgresql;resolution:=optional @@ -37,5 +45,12 @@ org.argeo.security.core ${version.argeo-commons} + + + + org.argeo.slc + org.argeo.slc.support.simple + 1.1.15-SNAPSHOT + diff --git a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java index 018f094a3..76248a842 100644 --- a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java +++ b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java @@ -17,6 +17,7 @@ public interface AkbNames { /* CONNECTOR PROPERTIES */ public final static String AKB_CONNECTOR_URL = "akb:connectorUrl"; + public final static String AKB_CONNECTOR_USER = "akb:connectorUser"; /* ITEMS PROPERTIES */ public final static String AKB_USED_CONNECTOR = "akb:usedConnector"; diff --git a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbService.java b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbService.java index 1f39ff832..8a16c63d3 100644 --- a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbService.java +++ b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbService.java @@ -1,5 +1,7 @@ package org.argeo.slc.akb; +import java.sql.PreparedStatement; + import javax.jcr.Node; import javax.jcr.RepositoryException; @@ -16,4 +18,10 @@ public interface AkbService { * current user has the sufficient credentials to connect */ public boolean testConnector(Node connector); + + public PreparedStatement prepareJdbcQuery(Node node); + + public String executeCommand(Node node); + + public String retrieveFile(Node node); } diff --git a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/core/AkbServiceImpl.java b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/core/AkbServiceImpl.java index e819bbfa8..ba7b6cc04 100644 --- a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/core/AkbServiceImpl.java +++ b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/core/AkbServiceImpl.java @@ -1,5 +1,11 @@ package org.argeo.slc.akb.core; +import java.net.URI; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLFeatureNotSupportedException; import java.util.Map; import javax.annotation.Resource; @@ -9,13 +15,22 @@ import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; +import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.slc.SlcException; import org.argeo.slc.akb.AkbException; import org.argeo.slc.akb.AkbNames; import org.argeo.slc.akb.AkbService; import org.argeo.slc.akb.AkbTypes; +import org.argeo.slc.jsch.SimpleUserInfo; +import org.argeo.util.security.Keyring; + +import com.jcraft.jsch.ChannelExec; +import com.jcraft.jsch.JSch; /** * Concrete access to akb services. It provides among other an initialized @@ -27,6 +42,8 @@ public class AkbServiceImpl implements AkbService, AkbNames { /* DEPENDENCY INJECTION */ private Repository repository; + private Keyring keyring; + // Populate the repository in a demo context. private Map demoData = null; @@ -36,6 +53,10 @@ public class AkbServiceImpl implements AkbService, AkbNames { * receive/provide data. */ public void init() { + // JDBC drivers + // TODO make it configurable + initJdbcDriver("org.postgresql.Driver"); + Session adminSession = null; try { adminSession = repository.login(); @@ -62,6 +83,18 @@ public class AkbServiceImpl implements AkbService, AkbNames { } } + protected Boolean initJdbcDriver(String driver) { + try { + Class.forName(driver); + return true; + } catch (ClassNotFoundException e) { + if (log.isDebugEnabled()) + log.debug("Cannot load JDBC driver : " + driver + ", " + + e.getMessage()); + return false; + } + } + /** Clean shutdown of the backend. */ public void destroy() { } @@ -89,9 +122,215 @@ public class AkbServiceImpl implements AkbService, AkbNames { // /////////////////////////////////////// // / CONNECTORS - public boolean testConnector(Node connector) { - // TODO Implement this. - return false; + public boolean testConnector(Node connectorNode) { + try { + if (connectorNode.isNodeType(AkbTypes.AKB_JDBC_CONNECTOR)) { + String connectorUrl = connectorNode.getProperty( + AKB_CONNECTOR_URL).getString(); + String connectorUser = connectorNode.getProperty( + AKB_CONNECTOR_USER).getString(); + + String pwdPath = getPasswordPath(connectorNode); + char[] pwd = keyring.getAsChars(pwdPath); + DriverManager.getConnection(connectorUrl, connectorUser, + new String(pwd)); + savePassword(connectorNode.getSession(), pwdPath, pwd); + return true; + } else if (connectorNode.isNodeType(AkbTypes.AKB_SSH_CONNECTOR)) { + String connectorUrl = connectorNode.getProperty( + AKB_CONNECTOR_URL).getString(); + String connectorUser = connectorNode.getProperty( + AKB_CONNECTOR_USER).getString(); + String pwdPath = getPasswordPath(connectorNode); + char[] pwd = keyring.getAsChars(pwdPath); + + URI url = new URI(connectorUrl); + String host = url.getHost(); + int port = url.getPort(); + if (port == -1) + port = 22; + JSch jsch = new JSch(); + com.jcraft.jsch.Session sess = jsch.getSession(connectorUser, + host, port); + SimpleUserInfo userInfo = new SimpleUserInfo(); + userInfo.setPassword(new String(pwd)); + sess.setUserInfo(userInfo); + sess.connect(); + sess.disconnect(); + + savePassword(connectorNode.getSession(), pwdPath, pwd); + return true; + } else { + throw new SlcException("Unsupported connector " + connectorNode); + } + } catch (Exception e) { + throw new SlcException("Cannot test connection", e); + } + } + + /** + * Opens a new connection each time. All resources must be cleaned by + * caller. + */ + public PreparedStatement prepareJdbcQuery(Node node) { + PreparedStatement statement = null; + try { + if (node.isNodeType(AkbTypes.AKB_JDBC_QUERY)) { + String sqlQuery = node.getProperty(AKB_QUERY_TEXT).getString(); + + String connectorPath = node.getProperty(AKB_USED_CONNECTOR) + .getString(); + Node connectorNode = node.getSession().getNode(connectorPath); + String connectorUrl = connectorNode.getProperty( + AKB_CONNECTOR_URL).getString(); + String connectorUser = connectorNode.getProperty( + AKB_CONNECTOR_USER).getString(); + + String pwdPath = getPasswordPath(connectorNode); + // String pwdPath = connectorNode.getPath() + '/' + // + ArgeoNames.ARGEO_PASSWORD; + char[] pwd = keyring.getAsChars(pwdPath); + Connection connection = DriverManager.getConnection( + connectorUrl, connectorUser, new String(pwd)); + try { + statement = connection.prepareStatement(sqlQuery, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + } catch (SQLFeatureNotSupportedException e) { + log.warn("Scroll not supported for " + connectorUrl); + statement = connection.prepareStatement(sqlQuery); + } + } else { + throw new SlcException("Unsupported node " + node); + } + return statement; + } catch (Exception e) { + throw new SlcException("Cannot execute test JDBC query on " + node, + e); + } + } + + public String executeCommand(Node node) { + try { + String command = node.getProperty(AkbNames.AKB_COMMAND_TEXT) + .getString(); + + String connectorPath = node.getProperty(AKB_USED_CONNECTOR) + .getString(); + Node connectorNode = node.getSession().getNode(connectorPath); + String connectorUrl = connectorNode.getProperty(AKB_CONNECTOR_URL) + .getString(); + String connectorUser = connectorNode + .getProperty(AKB_CONNECTOR_USER).getString(); + String pwdPath = getPasswordPath(connectorNode); + char[] pwd = keyring.getAsChars(pwdPath); + + URI url = new URI(connectorUrl); + String host = url.getHost(); + int port = url.getPort(); + if (port == -1) + port = 22; + JSch jsch = new JSch(); + com.jcraft.jsch.Session sess = jsch.getSession(connectorUser, host, + port); + SimpleUserInfo userInfo = new SimpleUserInfo(); + userInfo.setPassword(new String(pwd)); + sess.setUserInfo(userInfo); + sess.connect(); + + sess.openChannel("exec"); + final ChannelExec channel = (ChannelExec) sess.openChannel("exec"); + channel.setCommand(command); + + channel.setInputStream(null); + channel.setXForwarding(false); + channel.setAgentForwarding(false); + channel.setErrStream(null); + + channel.connect(); + + String output = IOUtils.toString(channel.getInputStream()); + channel.disconnect(); + + sess.disconnect(); + + return output; + } catch (Exception e) { + throw new SlcException("Cannot execute command", e); + } + + } + + public String retrieveFile(Node node) { + try { + String filePath = node.getProperty(AkbNames.AKB_FILE_PATH) + .getString(); + String command = "cat " + filePath; + + // TODO do a proper scp + String connectorPath = node.getProperty(AKB_USED_CONNECTOR) + .getString(); + Node connectorNode = node.getSession().getNode(connectorPath); + String connectorUrl = connectorNode.getProperty(AKB_CONNECTOR_URL) + .getString(); + String connectorUser = connectorNode + .getProperty(AKB_CONNECTOR_USER).getString(); + String pwdPath = getPasswordPath(connectorNode); + char[] pwd = keyring.getAsChars(pwdPath); + + URI url = new URI(connectorUrl); + String host = url.getHost(); + int port = url.getPort(); + if (port == -1) + port = 22; + JSch jsch = new JSch(); + com.jcraft.jsch.Session sess = jsch.getSession(connectorUser, host, + port); + SimpleUserInfo userInfo = new SimpleUserInfo(); + userInfo.setPassword(new String(pwd)); + sess.setUserInfo(userInfo); + sess.connect(); + + sess.openChannel("exec"); + final ChannelExec channel = (ChannelExec) sess.openChannel("exec"); + channel.setCommand(command); + + channel.setInputStream(null); + channel.setXForwarding(false); + channel.setAgentForwarding(false); + channel.setErrStream(null); + + channel.connect(); + + String output = IOUtils.toString(channel.getInputStream()); + channel.disconnect(); + + sess.disconnect(); + + return output; + } catch (Exception e) { + throw new SlcException("Cannot execute command", e); + } + + } + + protected String getPasswordPath(Node node) throws RepositoryException { + Node home = UserJcrUtils.getUserHome(node.getSession()); + if (node.getPath().startsWith(home.getPath())) + return node.getPath() + '/' + ArgeoNames.ARGEO_PASSWORD; + else + return home.getPath() + node.getPath() + '/' + + ArgeoNames.ARGEO_PASSWORD; + } + + private void savePassword(Session session, String pwdPath, char[] pwd) + throws RepositoryException { + if (!session.itemExists(pwdPath)) { + JcrUtils.mkdirs(session, JcrUtils.parentPath(pwdPath)); + session.save(); + keyring.set(pwdPath, pwd); + } + } // /** Expose injected repository */ @@ -107,4 +346,9 @@ public class AkbServiceImpl implements AkbService, AkbNames { public void setDemoData(Map demoData) { this.demoData = demoData; } + + public void setKeyring(Keyring keyring) { + this.keyring = keyring; + } + } \ No newline at end of file