+ }
+
+ @Override
+ public Node createAkbTemplate(Node parentNode, String name)
+ throws RepositoryException {
+ Node newTemplate = parentNode.addNode(name, AkbTypes.AKB_ENV_TEMPLATE);
+ newTemplate.setProperty(Property.JCR_TITLE, name);
+ newTemplate.addNode(AkbTypes.AKB_CONNECTOR_FOLDER,
+ AkbTypes.AKB_CONNECTOR_FOLDER);
+ return newTemplate;
+ }
+
+ // //////////////////////////
+ // ENVIRONMENTS
+ @Override
+ public Node createActiveEnv(Node template, String name,
+ boolean copyDefaultConnectors) throws RepositoryException {
+
+ Session session = template.getSession();
+ Node parentEnvNode = session.getNode(AKB_ENVIRONMENTS_BASE_PATH);
+ Node createdEnv = parentEnvNode.addNode(name, AkbTypes.AKB_ENV);
+ createdEnv.setProperty(AKB_ENV_TEMPLATE_PATH, template.getPath());
+ createdEnv.setProperty(Property.JCR_TITLE, name);
+
+ Node connectorParent = createdEnv.addNode(
+ AkbTypes.AKB_CONNECTOR_FOLDER, AkbTypes.AKB_CONNECTOR_FOLDER);
+
+ NodeIterator ni = template.getNode(AkbTypes.AKB_CONNECTOR_FOLDER)
+ .getNodes();
+ activeConns: while (ni.hasNext()) {
+ Node currNode = ni.nextNode();
+ if (currNode.isNodeType(AkbTypes.AKB_CONNECTOR_ALIAS)) {
+ String connType = currNode.getProperty(AKB_CONNECTOR_TYPE)
+ .getString();
+
+ if (AkbJcrUtils.isEmptyString(connType))
+ // Cannot create an instance if the type is undefined
+ continue activeConns;
+
+ Node newConnector = connectorParent.addNode(currNode.getName(),
+ connType);
+ newConnector.setProperty(AKB_CONNECTOR_ALIAS_PATH,
+ currNode.getPath());
+ if (copyDefaultConnectors
+ && currNode
+ .hasNode(AkbNames.AKB_DEFAULT_TEST_CONNECTOR)) {
+ Node defaultConn = currNode
+ .getNode(AkbNames.AKB_DEFAULT_TEST_CONNECTOR);
+ if (defaultConn.hasProperty(AkbNames.AKB_CONNECTOR_URL))
+ newConnector
+ .setProperty(
+ AkbNames.AKB_CONNECTOR_URL,
+ defaultConn.getProperty(
+ AkbNames.AKB_CONNECTOR_URL)
+ .getString());
+ if (defaultConn.hasProperty(AkbNames.AKB_CONNECTOR_USER))
+ newConnector.setProperty(
+ AkbNames.AKB_CONNECTOR_USER,
+ defaultConn.getProperty(
+ AkbNames.AKB_CONNECTOR_USER)
+ .getString());
+ }
+ }
+ }
+ return createdEnv;
+ }
+
+ // ///////////////////////////////////////
+ // CONNECTORS
+
+ @Override
+ public Node createConnectorAlias(Node templateNode, String name,
+ String connectorType) throws RepositoryException {
+ Node parent = JcrUtils.mkdirs(templateNode,
+ AkbTypes.AKB_CONNECTOR_FOLDER, AkbTypes.AKB_CONNECTOR_FOLDER);
+ Node newConnector = parent.addNode(name, AkbTypes.AKB_CONNECTOR_ALIAS);
+ newConnector.setProperty(Property.JCR_TITLE, name);
+ newConnector.setProperty(AkbNames.AKB_CONNECTOR_TYPE, connectorType);
+
+ // Node defaultConnector =
+ Node defaultConn = newConnector.addNode(
+ AkbNames.AKB_DEFAULT_TEST_CONNECTOR, connectorType);
+ defaultConn.setProperty(AkbNames.AKB_CONNECTOR_ALIAS_PATH,
+ newConnector.getPath());
+ return newConnector;
+ }
+
+ @Override
+ public NodeIterator getDefinedAliases(Node itemTemplate,
+ String connectorType) throws RepositoryException {
+ try {
+ Session session = itemTemplate.getSession();
+ QueryManager queryManager = session.getWorkspace()
+ .getQueryManager();
+ QueryObjectModelFactory factory = queryManager.getQOMFactory();
+
+ Selector source = factory.selector(AkbTypes.AKB_CONNECTOR_ALIAS,
+ AkbTypes.AKB_CONNECTOR_ALIAS);
+ Constraint defaultC = factory.descendantNode(
+ source.getSelectorName(), itemTemplate.getPath());
+
+ if (connectorType != null) {
+ Constraint connType = factory.comparison(factory.propertyValue(
+ source.getSelectorName(), AkbNames.AKB_CONNECTOR_TYPE),
+ QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO,
+ factory.literal(session.getValueFactory().createValue(
+ connectorType)));
+ defaultC = factory.and(defaultC, connType);
+ }
+
+ // Order by default by JCR TITLE
+ // TODO check if node definition has MIX_TITLE mixin
+ // TODO Apparently case insensitive ordering is not implemented in
+ // current used JCR implementation
+ Ordering order = factory
+ .ascending(factory.upperCase(factory.propertyValue(
+ source.getSelectorName(), Property.JCR_TITLE)));
+ QueryObjectModel query;
+ query = factory.createQuery(source, defaultC,
+ new Ordering[] { order }, null);
+ QueryResult result = query.execute();
+ return result.getNodes();
+ } catch (RepositoryException e) {
+ throw new AkbException("Unable to list connector", e);
+ }
+ }
+
+ @Override
+ public Node getActiveConnectorByAlias(Node envNode, String aliasPath)
+ throws RepositoryException {
+ try {
+ Session session = envNode.getSession();
+ QueryManager queryManager = session.getWorkspace()
+ .getQueryManager();
+ QueryObjectModelFactory factory = queryManager.getQOMFactory();
+
+ Selector source = factory.selector(AkbTypes.AKB_CONNECTOR,
+ AkbTypes.AKB_CONNECTOR);
+ Constraint defaultC = factory.descendantNode(
+ source.getSelectorName(), envNode.getPath());
+
+ Constraint connType = factory.comparison(
+ factory.propertyValue(source.getSelectorName(),
+ AkbNames.AKB_CONNECTOR_ALIAS_PATH),
+ QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, factory
+ .literal(session.getValueFactory().createValue(
+ aliasPath)));
+ defaultC = factory.and(defaultC, connType);
+
+ QueryObjectModel query;
+ query = factory.createQuery(source, defaultC, null, null);
+ QueryResult result = query.execute();
+ NodeIterator ni = result.getNodes();
+
+ if (!ni.hasNext())
+ return null;
+ else {
+ Node connector = ni.nextNode();
+ if (ni.hasNext())
+ throw new AkbException("More than one alias with name "
+ + aliasPath + " has been defined for environment "
+ + envNode);
+ else
+ return connector;
+ }
+ } catch (RepositoryException e) {
+ throw new AkbException("Unable to get connector " + aliasPath
+ + " in " + envNode, e);
+ }
+ }
+
+ @Override
+ 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 activeEnv, Node node) {
+ PreparedStatement statement = null;
+ try {
+
+ if (node.isNodeType(AkbTypes.AKB_JDBC_QUERY)) {
+ String connectorAliasStr = node.getProperty(AKB_USED_CONNECTOR)
+ .getString();
+ // in case of a template passed env can be null
+ if (activeEnv == null) {
+ activeEnv = AkbJcrUtils.getCurrentTemplate(node);
+ }
+ Node connectorNode = getActiveConnectorByAlias(activeEnv,
+ connectorAliasStr);
+
+ String sqlQuery = node.getProperty(AKB_QUERY_TEXT).getString();
+
+ String connectorUrl = AkbJcrUtils.get(connectorNode,
+ AKB_CONNECTOR_URL);
+ String connectorUser = AkbJcrUtils.get(connectorNode,
+ AKB_CONNECTOR_USER);
+
+ // Sanity check
+ if (AkbJcrUtils.isEmptyString(connectorUrl)
+ || AkbJcrUtils.isEmptyString(connectorUser))
+ return null;
+
+ 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 activeEnv, Node node) {
+ try {
+
+ String connectorAliasStr = node.getProperty(AKB_USED_CONNECTOR)
+ .getString();
+ // in case of a template passed env can be null
+ if (activeEnv == null) {
+ activeEnv = AkbJcrUtils.getCurrentTemplate(node);
+ }
+ Node connectorNode = getActiveConnectorByAlias(activeEnv,
+ connectorAliasStr);
+ String command = node.getProperty(AkbNames.AKB_COMMAND_TEXT)
+ .getString();
+
+ String connectorUrl = AkbJcrUtils.get(connectorNode,
+ AKB_CONNECTOR_URL);
+ String connectorUser = AkbJcrUtils.get(connectorNode,
+ AKB_CONNECTOR_USER);
+
+ // Sanity check
+ if (AkbJcrUtils.isEmptyString(connectorUrl)
+ || AkbJcrUtils.isEmptyString(connectorUser))
+ return null;
+
+ 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 activeEnv, Node node) {
+ try {
+ String filePath = node.getProperty(AkbNames.AKB_FILE_PATH)
+ .getString();
+ String command = "cat " + filePath;
+
+ String connectorAliasStr = node.getProperty(AKB_USED_CONNECTOR)
+ .getString();
+ // in case of a template passed env can be null
+ if (activeEnv == null) {
+ activeEnv = AkbJcrUtils.getCurrentTemplate(node);
+ }
+ Node connectorNode = getActiveConnectorByAlias(activeEnv,
+ connectorAliasStr);
+
+ // TODO do a proper scp
+ String connectorUrl = AkbJcrUtils.get(connectorNode,
+ AKB_CONNECTOR_URL);
+ String connectorUser = AkbJcrUtils.get(connectorNode,
+ AKB_CONNECTOR_USER);
+
+ // Sanity check
+ if (AkbJcrUtils.isEmptyString(connectorUrl)
+ || AkbJcrUtils.isEmptyString(connectorUser))
+ return null;
+
+ 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);
+ }
+