manifoldcf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kwri...@apache.org
Subject svn commit: r1771259 [1/2] - in /manifoldcf/branches/CONNECTORS-1344: ./ connectors/slack/ connectors/slack/connector/ connectors/slack/connector/src/ connectors/slack/connector/src/main/ connectors/slack/connector/src/main/java/ connectors/slack/conne...
Date Fri, 25 Nov 2016 09:21:14 GMT
Author: kwright
Date: Fri Nov 25 09:21:13 2016
New Revision: 1771259

URL: http://svn.apache.org/viewvc?rev=1771259&view=rev
Log:
Add Slack connector, from github pull request #11.  Patch generated with: curl -k -L -o CONNECTORS-1344.patch https://github.com/apache/manifoldcf/pull/11.diff

Added:
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/.gitignore
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/build.xml
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/Messages.java
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConfig.java
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConnector.java
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackMessage.java
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackSession.java
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_en_US.properties
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_es_ES.properties
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_ja_JP.properties
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_zh_CN.properties
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationHeader.js
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationView.html
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Configuration_Server.html
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationHeader.js
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationView.html
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Specification_Message.html
    manifoldcf/branches/CONNECTORS-1344/connectors/slack/pom.xml
Modified:
    manifoldcf/branches/CONNECTORS-1344/CHANGES.txt

Modified: manifoldcf/branches/CONNECTORS-1344/CHANGES.txt
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/CHANGES.txt?rev=1771259&r1=1771258&r2=1771259&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/CHANGES.txt (original)
+++ manifoldcf/branches/CONNECTORS-1344/CHANGES.txt Fri Nov 25 09:21:13 2016
@@ -2,6 +2,8 @@ ManifoldCF Change Log
 $Id$
 
 ======================= 2.6-dev =====================
+CONNECTORS-1344: Adds Slack Notification Connector
+(Odilo Oehmichen, Markus Schuch, Rüdiger Kurz)
 
 CONNECTORS-1338: Upgrade to SolrJ 6.3.0.
 (Shinichiro Abe)

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/.gitignore
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/.gitignore?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/.gitignore (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/.gitignore Fri Nov 25 09:21:13 2016
@@ -0,0 +1,3 @@
+/.classpath
+/.project
+/.settings/

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/build.xml
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/build.xml?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/build.xml (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/build.xml Fri Nov 25 09:21:13 2016
@@ -0,0 +1,40 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<project name="slack" default="all">
+
+    <property environment="env"/>
+    <condition property="mcf-dist" value="${env.MCFDISTPATH}">
+        <isset property="env.MCFDISTPATH"/>
+    </condition>
+    <property name="abs-dist" location="../../dist"/>
+    <condition property="mcf-dist" value="${abs-dist}">
+        <not>
+            <isset property="env.MCFDISTPATH"/>
+        </not>
+    </condition>
+
+    <import file="${mcf-dist}/connector-build.xml"/>
+
+    <target name="deliver-connector" depends="mcf-connector-build.deliver-connector">
+        <antcall target="general-add-notification-connector">
+            <param name="connector-label" value="Slack"/>
+            <param name="connector-class" value="org.apache.manifoldcf.crawler.notifications.slack.SlackConnector"/>
+        </antcall>
+    </target>
+
+</project>
\ No newline at end of file

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/Messages.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/Messages.java?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/Messages.java (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/Messages.java Fri Nov 25 09:21:13 2016
@@ -0,0 +1,141 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.crawler.notifications.slack;
+
+import java.util.Locale;
+import java.util.Map;
+import org.apache.manifoldcf.core.interfaces.ManifoldCFException;
+import org.apache.manifoldcf.core.interfaces.IHTTPOutput;
+
+public class Messages extends org.apache.manifoldcf.ui.i18n.Messages
+{
+  public static final String DEFAULT_BUNDLE_NAME="org.apache.manifoldcf.crawler.notifications.slack.common";
+  public static final String DEFAULT_PATH_NAME="org.apache.manifoldcf.crawler.notifications.slack";
+
+  /** Constructor - do no instantiate
+  */
+  protected Messages()
+  {
+  }
+
+  public static String getString(Locale locale, String messageKey)
+  {
+    return getString(DEFAULT_BUNDLE_NAME, locale, messageKey, null);
+  }
+
+  public static String getAttributeString(Locale locale, String messageKey)
+  {
+    return getAttributeString(DEFAULT_BUNDLE_NAME, locale, messageKey, null);
+  }
+
+  public static String getBodyString(Locale locale, String messageKey)
+  {
+    return getBodyString(DEFAULT_BUNDLE_NAME, locale, messageKey, null);
+  }
+
+  public static String getAttributeJavascriptString(Locale locale, String messageKey)
+  {
+    return getAttributeJavascriptString(DEFAULT_BUNDLE_NAME, locale, messageKey, null);
+  }
+
+  public static String getBodyJavascriptString(Locale locale, String messageKey)
+  {
+    return getBodyJavascriptString(DEFAULT_BUNDLE_NAME, locale, messageKey, null);
+  }
+
+  public static String getString(Locale locale, String messageKey, Object[] args)
+  {
+    return getString(DEFAULT_BUNDLE_NAME, locale, messageKey, args);
+  }
+
+  public static String getAttributeString(Locale locale, String messageKey, Object[] args)
+  {
+    return getAttributeString(DEFAULT_BUNDLE_NAME, locale, messageKey, args);
+  }
+
+  public static String getBodyString(Locale locale, String messageKey, Object[] args)
+  {
+    return getBodyString(DEFAULT_BUNDLE_NAME, locale, messageKey, args);
+  }
+
+  public static String getAttributeJavascriptString(Locale locale, String messageKey, Object[] args)
+  {
+    return getAttributeJavascriptString(DEFAULT_BUNDLE_NAME, locale, messageKey, args);
+  }
+
+  public static String getBodyJavascriptString(Locale locale, String messageKey, Object[] args)
+  {
+    return getBodyJavascriptString(DEFAULT_BUNDLE_NAME, locale, messageKey, args);
+  }
+
+  // More general methods which allow bundlenames and class loaders to be specified.
+
+  public static String getString(String bundleName, Locale locale, String messageKey, Object[] args)
+  {
+    return getString(Messages.class, bundleName, locale, messageKey, args);
+  }
+
+  public static String getAttributeString(String bundleName, Locale locale, String messageKey, Object[] args)
+  {
+    return getAttributeString(Messages.class, bundleName, locale, messageKey, args);
+  }
+
+  public static String getBodyString(String bundleName, Locale locale, String messageKey, Object[] args)
+  {
+    return getBodyString(Messages.class, bundleName, locale, messageKey, args);
+  }
+
+  public static String getAttributeJavascriptString(String bundleName, Locale locale, String messageKey, Object[] args)
+  {
+    return getAttributeJavascriptString(Messages.class, bundleName, locale, messageKey, args);
+  }
+
+  public static String getBodyJavascriptString(String bundleName, Locale locale, String messageKey, Object[] args)
+  {
+    return getBodyJavascriptString(Messages.class, bundleName, locale, messageKey, args);
+  }
+
+  // Resource output
+
+  public static void outputResource(IHTTPOutput output, Locale locale, String resourceKey,
+    Map<String,String> substitutionParameters, boolean mapToUpperCase)
+    throws ManifoldCFException
+  {
+    outputResource(output,Messages.class,DEFAULT_PATH_NAME,locale,resourceKey,
+      substitutionParameters,mapToUpperCase);
+  }
+
+  public static void outputResourceWithVelocity(IHTTPOutput output, Locale locale, String resourceKey,
+    Map<String,String> substitutionParameters, boolean mapToUpperCase)
+    throws ManifoldCFException
+  {
+    outputResourceWithVelocity(output,Messages.class,DEFAULT_BUNDLE_NAME,DEFAULT_PATH_NAME,locale,resourceKey,
+      substitutionParameters,mapToUpperCase);
+  }
+
+  public static void outputResourceWithVelocity(IHTTPOutput output, Locale locale, String resourceKey,
+    Map<String,Object> contextObjects)
+    throws ManifoldCFException
+  {
+    outputResourceWithVelocity(output,Messages.class,DEFAULT_BUNDLE_NAME,DEFAULT_PATH_NAME,locale,resourceKey,
+      contextObjects);
+  }
+
+}
+

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConfig.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConfig.java?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConfig.java (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConfig.java Fri Nov 25 09:21:13 2016
@@ -0,0 +1,52 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.crawler.notifications.slack;
+
+
+/**
+* Parameters data for the Slack notification connector.
+*/
+public class SlackConfig {
+
+  /**
+  * Slack WebHook URL
+  */
+  public static final String WEBHOOK_URL_PARAM = "webHookUrl";
+
+  /**
+  * URL template
+  */
+  public static final String URL_PARAM = "url";
+
+  // Specification nodes
+  public static final String NODE_FINISHED = "finished";
+  public static final String NODE_ERRORABORTED = "erroraborted";
+  public static final String NODE_MANUALABORTED = "manualaborted";
+  public static final String NODE_MANUALPAUSED = "manualpaused";
+  public static final String NODE_SCHEDULEPAUSED = "schedulepaused";
+  public static final String NODE_RESTARTED = "restarted";
+
+  public static final String NODE_CHANNEL = "channel";
+  public static final String NODE_MESSAGE = "message";
+
+  public static final String ATTRIBUTE_NAME = "name";
+  public static final String ATTRIBUTE_VALUE = "value";
+
+
+}
\ No newline at end of file

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConnector.java?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConnector.java (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackConnector.java Fri Nov 25 09:21:13 2016
@@ -0,0 +1,818 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.crawler.notifications.slack;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.manifoldcf.agents.interfaces.ServiceInterruption;
+import org.apache.manifoldcf.core.interfaces.ConfigParams;
+import org.apache.manifoldcf.core.interfaces.IHTTPOutput;
+import org.apache.manifoldcf.core.interfaces.IPasswordMapperActivity;
+import org.apache.manifoldcf.core.interfaces.IPostParameters;
+import org.apache.manifoldcf.core.interfaces.IThreadContext;
+import org.apache.manifoldcf.core.interfaces.ManifoldCFException;
+import org.apache.manifoldcf.core.interfaces.Specification;
+import org.apache.manifoldcf.core.interfaces.SpecificationNode;
+import org.apache.manifoldcf.crawler.system.Logging;
+
+/**
+*/
+public class SlackConnector extends org.apache.manifoldcf.crawler.notifications.BaseNotificationConnector {
+
+  protected final static long SESSION_EXPIRATION_MILLISECONDS = 300000L;
+
+  // Local variables.
+  protected long sessionExpiration = -1L;
+
+  // Parameters for establishing a session
+
+  protected String webHookUrl = null;
+
+  // Local session handle
+  protected SlackSession session = null;
+
+  //////////////////////////////////Start of Basic Connector Methods/////////////////////////
+
+  /**
+  * Connect.
+  *
+  * @param configParameters is the set of configuration parameters, which
+  * in this case describe the root directory.
+  */
+  @Override
+  public void connect(ConfigParams configParameters) {
+    super.connect(configParameters);
+    this.webHookUrl = configParameters.getParameter(SlackConfig.WEBHOOK_URL_PARAM);
+  }
+
+  /**
+  * Close the connection. Call this before discarding this instance of the
+  * repository connector.
+  */
+  @Override
+  public void disconnect()
+    throws ManifoldCFException {
+    this.webHookUrl = null;
+    finalizeConnection();
+    super.disconnect();
+  }
+
+  /**
+  * This method is periodically called for all connectors that are connected but not
+  * in active use.
+  */
+  @Override
+  public void poll() throws ManifoldCFException {
+    if (session != null)
+    {
+      if (System.currentTimeMillis() >= sessionExpiration)
+        finalizeConnection();
+    }
+  }
+
+  /**
+  * Test the connection. Returns a string describing the connection integrity.
+  *
+  * @return the connection's status as a displayable string.
+  */
+  @Override
+  public String check()
+      throws ManifoldCFException {
+    try {
+      checkConnection();
+      return super.check();
+    } catch (ServiceInterruption e) {
+      return "Connection temporarily failed: " + e.getMessage();
+    } catch (ManifoldCFException e) {
+      return "Connection failed: " + e.getMessage();
+    }
+  }
+
+  protected void checkConnection() throws ManifoldCFException, ServiceInterruption {
+    // Force a re-connection
+    finalizeConnection();
+    getSession();
+    try {
+      CheckConnectionThread cct = new CheckConnectionThread(session);
+      cct.start();
+      cct.finishUp();
+    } catch (InterruptedException e) {
+      throw new ManifoldCFException(e.getMessage(),ManifoldCFException.INTERRUPTED);
+    } catch (IOException e) {
+      handleIOException(e,"checking the connection");
+    }
+  }
+
+  protected void getSession()
+    throws ManifoldCFException, ServiceInterruption {
+    if (session == null) {
+
+      // Check that all the required parameters are there.
+      if (webHookUrl == null)
+        throw new ManifoldCFException("Missing webHookUrl parameter");
+
+      // Create a session.
+      try {
+        ConnectThread connectThread = new ConnectThread(webHookUrl);
+        connectThread.start();
+        session = connectThread.finishUp();
+      } catch (InterruptedException e) {
+        throw new ManifoldCFException(e.getMessage(),ManifoldCFException.INTERRUPTED);
+      } catch (IOException e) {
+        handleIOException(e, "connecting");
+      }
+    }
+    sessionExpiration = System.currentTimeMillis() + SESSION_EXPIRATION_MILLISECONDS;
+  }
+
+  protected void finalizeConnection() {
+    if (session != null) {
+      try {
+        CloseSessionThread closeSessionThread = new CloseSessionThread(session);
+        closeSessionThread.start();
+        closeSessionThread.finishUp();
+      } catch (InterruptedException e) {
+      } catch (IOException e) {
+        Logging.connectors.warn("Error while closing connection to server: " + e.getMessage(),e);
+      } finally {
+        session = null;
+      }
+    }
+  }
+
+  ///////////////////////////////End of Basic Connector Methods////////////////////////////////////////
+
+  //////////////////////////////Start of Notification Connector Method///////////////////////////////////
+
+  /** Notify of job stop due to error abort.
+  *@param spec is the notification specification.
+  */
+  @Override
+  public void notifyOfJobStopErrorAbort(final Specification spec)
+    throws ManifoldCFException, ServiceInterruption {
+    sendSlackMessage(spec, SlackConfig.NODE_ERRORABORTED);
+  }
+
+  /** Notify of job stop due to manual abort.
+  *@param spec is the notification specification.
+  */
+  @Override
+  public void notifyOfJobStopManualAbort(final Specification spec)
+    throws ManifoldCFException, ServiceInterruption {
+    sendSlackMessage(spec, SlackConfig.NODE_MANUALABORTED);
+  }
+
+  /** Notify of job stop due to manual pause.
+  *@param spec is the notification specification.
+  */
+  @Override
+  public void notifyOfJobStopManualPause(final Specification spec)
+    throws ManifoldCFException, ServiceInterruption {
+    sendSlackMessage(spec, SlackConfig.NODE_MANUALPAUSED);
+  }
+
+  /** Notify of job stop due to schedule pause.
+  *@param spec is the notification specification.
+  */
+  @Override
+  public void notifyOfJobStopSchedulePause(final Specification spec)
+    throws ManifoldCFException, ServiceInterruption {
+    sendSlackMessage(spec, SlackConfig.NODE_SCHEDULEPAUSED);
+  }
+
+  /** Notify of job stop due to restart.
+  *@param spec is the notification specification.
+  */
+  @Override
+  public void notifyOfJobStopRestart(final Specification spec)
+    throws ManifoldCFException, ServiceInterruption {
+    sendSlackMessage(spec, SlackConfig.NODE_RESTARTED);
+  }
+
+  /** Notify of job end.
+  *@param spec is the notification specification.
+  */
+  @Override
+  public void notifyOfJobEnd(final Specification spec)
+    throws ManifoldCFException, ServiceInterruption {
+    sendSlackMessage(spec, SlackConfig.NODE_FINISHED);
+  }
+
+  protected void sendSlackMessage(final Specification spec, final String nodeType)
+    throws ManifoldCFException, ServiceInterruption
+  {
+    String channel = "";
+    String message = "";
+    for (int i = 0; i < spec.getChildCount(); i++) {
+      SpecificationNode sn = spec.getChild(i);
+      if (sn.getType().equals(SlackConfig.NODE_CHANNEL))
+        channel = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+      else if (sn.getType().equals(SlackConfig.NODE_MESSAGE))
+        message = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+    }
+    // Look for node of the specified type
+    if (nodeType != null)
+    {
+      for (int i = 0; i < spec.getChildCount(); i++) {
+        SpecificationNode childNode = spec.getChild(i);
+        if (childNode.getType().equals(nodeType))
+        {
+          for (int j = 0; j < childNode.getChildCount(); j++) {
+            SpecificationNode sn = childNode.getChild(j);
+            if (sn.getType().equals(SlackConfig.NODE_CHANNEL))
+              channel = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+            else if (sn.getType().equals(SlackConfig.NODE_MESSAGE))
+              message = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+          }
+        }
+      }
+    }
+
+    if (StringUtils.isBlank(message)) {
+      return;
+    }
+
+    // Construct and send a slack message
+    getSession();
+
+    SendThread st = new SendThread(session, channel, message);
+    st.start();
+    try {
+      st.finishUp();
+    } catch (InterruptedException e) {
+      throw new ManifoldCFException(e.getMessage(),ManifoldCFException.INTERRUPTED);
+    } catch (IOException e) {
+      handleIOException(e,"sending slack message");
+    }
+  }
+
+
+  //////////////////////////////End of Notification Connector Methods///////////////////////////////////
+
+
+  ///////////////////////////////////////Start of Configuration UI/////////////////////////////////////
+
+  /**
+  * Output the configuration header section.
+  * This method is called in the head section of the connector's configuration page. Its purpose is to
+  * add the required tabs to the list, and to output any javascript methods that might be needed by
+  * the configuration editing HTML.
+  * The connector does not need to be connected for this method to be called.
+  *
+  * @param threadContext is the local thread context.
+  * @param out is the output to which any HTML should be sent.
+  * @param locale is the desired locale.
+  * @param parameters are the configuration parameters, as they currently exist, for this connection being configured.
+  * @param tabsArray is an array of tab names. Add to this array any tab names that are specific to the connector.
+  */
+  @Override
+  public void outputConfigurationHeader(IThreadContext threadContext, IHTTPOutput out,
+    Locale locale, ConfigParams parameters, List<String> tabsArray)
+    throws ManifoldCFException, IOException {
+    tabsArray.add(Messages.getString(locale, "SlackConnector.WebHook"));
+    // Map the parameters
+    Map<String, Object> paramMap = new HashMap<String, Object>();
+
+    // Fill in the parameters from each tab
+    fillInServerConfigurationMap(paramMap, out, parameters);
+
+    // Output the Javascript - only one Velocity template for all tabs
+    Messages.outputResourceWithVelocity(out, locale, "ConfigurationHeader.js", paramMap);
+  }
+
+  @Override
+  public void outputConfigurationBody(IThreadContext threadContext, IHTTPOutput out,
+    Locale locale, ConfigParams parameters, String tabName)
+    throws ManifoldCFException, IOException {
+    // Output the Server tab
+    Map<String, Object> paramMap = new HashMap<String, Object>();
+    // Set the tab name
+    paramMap.put("TabName", tabName);
+    // Fill in the parameters
+    fillInServerConfigurationMap(paramMap, out, parameters);
+    Messages.outputResourceWithVelocity(out, locale, "Configuration_Server.html", paramMap);
+  }
+
+  private static void fillInServerConfigurationMap(Map<String, Object> paramMap, IPasswordMapperActivity mapper, ConfigParams parameters) {
+    String webHookUrl = parameters.getParameter(SlackConfig.WEBHOOK_URL_PARAM);
+    if (webHookUrl == null)
+      webHookUrl = StringUtils.EMPTY;
+
+    paramMap.put("WEBHOOK_URL", webHookUrl);
+  }
+
+  /**
+  * Process a configuration post.
+  * This method is called at the start of the connector's configuration page, whenever there is a possibility
+  * that form data for a connection has been posted. Its purpose is to gather form information and modify
+  * the configuration parameters accordingly.
+  * The name of the posted form is always "editconnection".
+  * The connector does not need to be connected for this method to be called.
+  *
+  * @param threadContext is the local thread context.
+  * @param variableContext is the set of variables available from the post, including binary file post information.
+  * @param parameters are the configuration parameters, as they currently exist, for this connection being configured.
+  * @return null if all is well, or a string error message if there is an error that should prevent saving of the
+  * connection (and cause a redirection to an error page).
+  */
+  @Override
+  public String processConfigurationPost(IThreadContext threadContext, IPostParameters variableContext,
+    ConfigParams parameters) throws ManifoldCFException {
+
+    String webHookUrl = variableContext.getParameter("webHookUrl");
+    if (webHookUrl != null)
+      parameters.setParameter(SlackConfig.WEBHOOK_URL_PARAM, webHookUrl);
+
+    return null;
+  }
+
+  /**
+  * View configuration. This method is called in the body section of the
+  * connector's view configuration page. Its purpose is to present the
+  * connection information to the user. The coder can presume that the HTML that
+  * is output from this configuration will be within appropriate <html> and
+  * <body> tags.
+  *
+  * @param threadContext is the local thread context.
+  * @param out is the output to which any HTML should be sent.
+  * @param parameters are the configuration parameters, as they currently exist, for
+  * this connection being configured.
+  */
+  @Override
+  public void viewConfiguration(IThreadContext threadContext, IHTTPOutput out,
+    Locale locale, ConfigParams parameters) throws ManifoldCFException, IOException {
+    Map<String, Object> paramMap = new HashMap<String, Object>();
+
+    // Fill in map from each tab
+    fillInServerConfigurationMap(paramMap, out, parameters);
+
+    Messages.outputResourceWithVelocity(out, locale, "ConfigurationView.html", paramMap);
+  }
+
+
+  /////////////////////////////////End of configuration UI////////////////////////////////////////////////////
+
+
+  /////////////////////////////////Start of Specification UI//////////////////////////////////////////////////
+
+  /** Output the specification header section.
+  * This method is called in the head section of a job page which has selected a repository connection of the
+  * current type.  Its purpose is to add the required tabs to the list, and to output any javascript methods
+  * that might be needed by the job editing HTML.
+  * The connector will be connected before this method can be called.
+  *@param out is the output to which any HTML should be sent.
+  *@param locale is the locale the output is preferred to be in.
+  *@param ds is the current document specification for this job.
+  *@param connectionSequenceNumber is the unique number of this connection within the job.
+  *@param tabsArray is an array of tab names.  Add to this array any tab names that are specific to the connector.
+  */
+  @Override
+  public void outputSpecificationHeader(IHTTPOutput out, Locale locale, Specification ds,
+    int connectionSequenceNumber, List<String> tabsArray)
+    throws ManifoldCFException, IOException {
+    Map<String, Object> paramMap = new HashMap<String, Object>();
+    paramMap.put("SeqNum", Integer.toString(connectionSequenceNumber));
+    // Add the tabs
+    tabsArray.add(Messages.getString(locale, "SlackConnector.Message"));
+    Messages.outputResourceWithVelocity(out, locale, "SpecificationHeader.js", paramMap);
+  }
+
+  /** Output the specification body section.
+  * This method is called in the body section of a job page which has selected a repository connection of the
+  * current type.  Its purpose is to present the required form elements for editing.
+  * The coder can presume that the HTML that is output from this configuration will be within appropriate
+  *  <html>, <body>, and <form> tags.  The name of the form is always "editjob".
+  * The connector will be connected before this method can be called.
+  *@param out is the output to which any HTML should be sent.
+  *@param locale is the locale the output is preferred to be in.
+  *@param ds is the current document specification for this job.
+  *@param connectionSequenceNumber is the unique number of this connection within the job.
+  *@param actualSequenceNumber is the connection within the job that has currently been selected.
+  *@param tabName is the current tab name.  (actualSequenceNumber, tabName) form a unique tuple within
+  *  the job.
+  */
+  @Override
+  public void outputSpecificationBody(IHTTPOutput out, Locale locale, Specification ds,
+    int connectionSequenceNumber, int actualSequenceNumber, String tabName)
+    throws ManifoldCFException, IOException {
+    outputMessageTab(out, locale, ds, tabName, connectionSequenceNumber, actualSequenceNumber);
+  }
+
+  /**
+* Take care of "Message" tab.
+*/
+  protected void outputMessageTab(IHTTPOutput out, Locale locale,
+    Specification ds, String tabName, int connectionSequenceNumber, int actualSequenceNumber)
+    throws ManifoldCFException, IOException {
+    Map<String, Object> paramMap = new HashMap<String, Object>();
+    paramMap.put("TabName", tabName);
+    paramMap.put("SeqNum", Integer.toString(connectionSequenceNumber));
+    paramMap.put("SelectedNum", Integer.toString(actualSequenceNumber));
+    fillInMessageTab(paramMap, ds);
+    Messages.outputResourceWithVelocity(out, locale, "Specification_Message.html", paramMap);
+  }
+
+  /**
+  * Fill in Velocity context for Metadata tab.
+  */
+  protected static void fillInMessageTab(Map<String, Object> paramMap,
+    Specification ds) {
+
+    // Preload default values, for backwards compatibility
+    String channel = "";
+    String message = "";
+    for (int i = 0; i < ds.getChildCount(); i++) {
+      SpecificationNode sn = ds.getChild(i);
+      if (sn.getType().equals(SlackConfig.NODE_CHANNEL)) {
+        channel = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+      } else if (sn.getType().equals(SlackConfig.NODE_MESSAGE)) {
+        message = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+      }
+    }
+    // If ANY of the above are non-empty, we create a new dummy record
+    // TODO check if channel check is right
+    if (channel.length() > 0) {
+      // Add the dummy records
+      addRecord(paramMap, SlackConfig.NODE_FINISHED, channel, message);
+      addRecord(paramMap, SlackConfig.NODE_ERRORABORTED, channel, message);
+      addRecord(paramMap, SlackConfig.NODE_MANUALABORTED, channel, message);
+      addRecord(paramMap, SlackConfig.NODE_MANUALPAUSED, channel, message);
+      addRecord(paramMap, SlackConfig.NODE_SCHEDULEPAUSED, channel, message);
+      addRecord(paramMap, SlackConfig.NODE_RESTARTED, channel, message);
+
+    }
+    else
+    {
+      // Initialize all records with blanks
+      addRecord(paramMap, SlackConfig.NODE_FINISHED, "", "");
+      addRecord(paramMap, SlackConfig.NODE_ERRORABORTED, "", "");
+      addRecord(paramMap, SlackConfig.NODE_MANUALABORTED, "", "");
+      addRecord(paramMap, SlackConfig.NODE_MANUALPAUSED, "", "");
+      addRecord(paramMap, SlackConfig.NODE_SCHEDULEPAUSED, "", "");
+      addRecord(paramMap, SlackConfig.NODE_RESTARTED, "" ,"");
+
+      // Loop through nodes and pick them out that way
+      for (int i = 0; i < ds.getChildCount(); i++) {
+        SpecificationNode childNode = ds.getChild(i);
+        if (childNode.getType().equals(SlackConfig.NODE_FINISHED) ||
+          childNode.getType().equals(SlackConfig.NODE_ERRORABORTED) ||
+          childNode.getType().equals(SlackConfig.NODE_MANUALABORTED) ||
+          childNode.getType().equals(SlackConfig.NODE_MANUALPAUSED) ||
+          childNode.getType().equals(SlackConfig.NODE_SCHEDULEPAUSED) ||
+          childNode.getType().equals(SlackConfig.NODE_RESTARTED)) {
+          channel = "";
+          message = "";
+          for (int j = 0; j < childNode.getChildCount(); j++) {
+            SpecificationNode sn = childNode.getChild(j);
+            if (sn.getType().equals(SlackConfig.NODE_CHANNEL)) {
+              channel = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+            } else if (sn.getType().equals(SlackConfig.NODE_MESSAGE)) {
+              message = sn.getAttributeValue(SlackConfig.ATTRIBUTE_VALUE);
+            }
+          }
+          addRecord(paramMap, childNode.getType(), channel, message);
+        }
+      }
+    }
+  }
+
+  protected static void addRecord(Map<String,Object> paramMap, String nodeType, String channel, String message) {
+    paramMap.put(nodeType+"_CHANNEL", channel);
+    paramMap.put(nodeType+"_MESSAGE", message);
+  }
+
+  /** Process a specification post.
+  * This method is called at the start of job's edit or view page, whenever there is a possibility that form
+  * data for a connection has been posted.  Its purpose is to gather form information and modify the
+  * document specification accordingly.  The name of the posted form is always "editjob".
+  * The connector will be connected before this method can be called.
+  *@param variableContext contains the post data, including binary file-upload information.
+  *@param locale is the locale the output is preferred to be in.
+  *@param ds is the current document specification for this job.
+  *@param connectionSequenceNumber is the unique number of this connection within the job.
+  *@return null if all is well, or a string error message if there is an error that should prevent saving of
+  * the job (and cause a redirection to an error page).
+  */
+  @Override
+  public String processSpecificationPost(IPostParameters variableContext, Locale locale, Specification ds,
+    int connectionSequenceNumber)
+    throws ManifoldCFException {
+
+    return processMessageTab(variableContext, ds, connectionSequenceNumber);
+  }
+
+  protected String processMessageTab(IPostParameters variableContext, Specification ds,
+    int connectionSequenceNumber)
+    throws ManifoldCFException {
+
+    String seqPrefix = "s"+connectionSequenceNumber+"_";
+
+    // Remove legacy nodes always
+    removeNodes(ds, SlackConfig.NODE_CHANNEL);
+    removeNodes(ds, SlackConfig.NODE_MESSAGE);
+
+    // Gather all different kinds.
+    gatherRecord(ds, seqPrefix, variableContext, SlackConfig.NODE_FINISHED);
+    gatherRecord(ds, seqPrefix, variableContext, SlackConfig.NODE_ERRORABORTED);
+    gatherRecord(ds, seqPrefix, variableContext, SlackConfig.NODE_MANUALABORTED);
+    gatherRecord(ds, seqPrefix, variableContext, SlackConfig.NODE_MANUALPAUSED);
+    gatherRecord(ds, seqPrefix, variableContext, SlackConfig.NODE_SCHEDULEPAUSED);
+    gatherRecord(ds, seqPrefix, variableContext, SlackConfig.NODE_RESTARTED);
+
+    return null;
+  }
+
+  protected static void gatherRecord(Specification ds, String seqPrefix, IPostParameters variableContext, String nodeType) {
+    removeNodes(ds, nodeType);
+    SpecificationNode sn = new SpecificationNode(nodeType);
+    String channel = variableContext.getParameter(seqPrefix + nodeType + "_channel");
+    if (channel != null)
+    {
+      addNodeValue(sn, SlackConfig.NODE_CHANNEL, channel);
+    }
+    String message = variableContext.getParameter(seqPrefix + nodeType + "_message");
+    if (message != null)
+    {
+      addNodeValue(sn, SlackConfig.NODE_MESSAGE, message);
+    }
+    ds.addChild(ds.getChildCount(),sn);
+  }
+
+  /** View specification.
+  * This method is called in the body section of a job's view page.  Its purpose is to present the document
+  * specification information to the user.  The coder can presume that the HTML that is output from
+  * this configuration will be within appropriate <html> and <body> tags.
+  * The connector will be connected before this method can be called.
+  *@param out is the output to which any HTML should be sent.
+  *@param locale is the locale the output is preferred to be in.
+  *@param ds is the current document specification for this job.
+  *@param connectionSequenceNumber is the unique number of this connection within the job.
+  */
+  @Override
+  public void viewSpecification(IHTTPOutput out, Locale locale, Specification ds,
+    int connectionSequenceNumber)
+    throws ManifoldCFException, IOException {
+    Map<String, Object> paramMap = new HashMap<String, Object>();
+    paramMap.put("SeqNum", Integer.toString(connectionSequenceNumber));
+    fillInMessageTab(paramMap, ds);
+    Messages.outputResourceWithVelocity(out, locale, "SpecificationView.html", paramMap);
+  }
+
+  ///////////////////////////////////////End of specification UI///////////////////////////////////////////////
+
+  protected static void removeNodes(Specification ds, String nodeTypeName) {
+    int i = 0;
+    while (i < ds.getChildCount()) {
+      SpecificationNode sn = ds.getChild(i);
+      if (sn.getType().equals(nodeTypeName))
+        ds.removeChild(i);
+      else
+        i++;
+    }
+  }
+
+  protected static void addNodeValue(SpecificationNode ds, String nodeType, String value)
+  {
+    SpecificationNode sn = new SpecificationNode(nodeType);
+    sn.setAttribute(SlackConfig.ATTRIBUTE_VALUE,value);
+    ds.addChild(ds.getChildCount(),sn);
+  }
+
+
+  /** Handle Messaging exceptions in a consistent global manner */
+  protected static void handleIOException(IOException e, String context)
+    throws ManifoldCFException, ServiceInterruption
+  {
+    Logging.connectors.error("Slack: Error "+context+": "+e.getMessage(),e);
+    throw new ManifoldCFException("Error "+context+": "+e.getMessage(),e);
+  }
+
+  /** Class to set up connection.
+  */
+  protected static class ConnectThread extends Thread
+  {
+    protected final String webHookUrl;
+
+    // Local session handle
+    protected SlackSession session = null;
+    protected Throwable exception = null;
+
+    public ConnectThread(String webHookUrl)
+    {
+      this.webHookUrl = webHookUrl;
+      setDaemon(true);
+    }
+
+    public void run()
+    {
+      try
+      {
+        session = new SlackSession(webHookUrl);
+      }
+      catch (Throwable e)
+      {
+        exception = e;
+      }
+    }
+
+    public SlackSession finishUp()
+      throws IOException, InterruptedException
+    {
+      try
+      {
+        join();
+        if (exception != null)
+        {
+          if (exception instanceof RuntimeException)
+            throw (RuntimeException)exception;
+          else if (exception instanceof Error)
+            throw (Error)exception;
+          else if (exception instanceof IOException)
+            throw (IOException)exception;
+          else
+            throw new RuntimeException("Unknown exception type: "+exception.getClass().getName()+": "+exception.getMessage(),exception);
+        }
+        return session;
+      } catch (InterruptedException e) {
+        this.interrupt();
+        throw e;
+      }
+    }
+  }
+
+  /** Class to close the session.
+  */
+  protected static class CloseSessionThread extends Thread
+  {
+    protected final SlackSession session;
+
+    protected Throwable exception = null;
+
+    public CloseSessionThread(SlackSession session)
+    {
+      this.session = session;
+      setDaemon(true);
+    }
+
+    public void run()
+    {
+      try
+      {
+        session.close();
+      }
+      catch (Throwable e)
+      {
+        exception = e;
+      }
+    }
+
+    public void finishUp()
+      throws IOException, InterruptedException
+    {
+      try
+      {
+        join();
+        if (exception != null)
+        {
+          if (exception instanceof RuntimeException)
+            throw (RuntimeException)exception;
+          else if (exception instanceof Error)
+            throw (Error)exception;
+          else if (exception instanceof IOException)
+            throw (IOException)exception;
+          else
+            throw new RuntimeException("Unknown exception type: "+exception.getClass().getName()+": "+exception.getMessage(),exception);
+        }
+      } catch (InterruptedException e) {
+        this.interrupt();
+        throw e;
+      }
+    }
+  }
+
+  /** Class to check the connection.
+  */
+  protected static class CheckConnectionThread extends Thread
+  {
+    protected final SlackSession session;
+
+    protected Throwable exception = null;
+
+    public CheckConnectionThread(SlackSession session)
+    {
+      this.session = session;
+      setDaemon(true);
+    }
+
+    public void run()
+    {
+      try
+      {
+        session.checkConnection();
+      }
+      catch (Throwable e)
+      {
+        exception = e;
+      }
+    }
+
+    public void finishUp()
+      throws IOException, InterruptedException
+    {
+      try
+      {
+        join();
+        if (exception != null)
+        {
+          if (exception instanceof RuntimeException)
+            throw (RuntimeException)exception;
+          else if (exception instanceof Error)
+            throw (Error)exception;
+          else if (exception instanceof IOException)
+            throw (IOException)exception;
+          else
+            throw new RuntimeException("Unknown exception type: "+exception.getClass().getName()+": "+exception.getMessage(),exception);
+        }
+      } catch (InterruptedException e) {
+        this.interrupt();
+        throw e;
+      }
+    }
+  }
+
+  /** Class to send slack messages.
+  */
+  protected static class SendThread extends Thread
+  {
+    protected final SlackSession session;
+    protected final String channel;
+    protected final String message;
+
+    protected Throwable exception = null;
+
+    public SendThread(SlackSession session, String channel, String message)
+    {
+      this.session = session;
+      this.channel = channel;
+      this.message = message;
+      setDaemon(true);
+    }
+
+    public void run()
+    {
+      try
+      {
+        session.send(channel, message);
+      }
+      catch (Throwable e)
+      {
+        exception = e;
+      }
+    }
+
+    public void finishUp()
+      throws IOException, InterruptedException
+    {
+      try
+      {
+        join();
+        if (exception != null)
+        {
+          if (exception instanceof RuntimeException)
+            throw (RuntimeException)exception;
+          else if (exception instanceof Error)
+            throw (Error)exception;
+          else if (exception instanceof IOException)
+            throw (IOException)exception;
+          else
+            throw new RuntimeException("Unknown exception type: "+exception.getClass().getName()+": "+exception.getMessage(),exception);
+        }
+      } catch (InterruptedException e) {
+        this.interrupt();
+        throw e;
+      }
+    }
+  }
+
+}
\ No newline at end of file

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackMessage.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackMessage.java?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackMessage.java (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackMessage.java Fri Nov 25 09:21:13 2016
@@ -0,0 +1,53 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.crawler.notifications.slack;
+
+public class SlackMessage {
+
+  private String channel;
+
+  private String text;
+
+  private boolean mrkdwn = true;
+
+  public String getChannel() {
+    return channel;
+  }
+
+  public void setChannel(String channel) {
+    this.channel = channel;
+  }
+
+  public String getText() {
+    return text;
+  }
+
+  public void setText(String text) {
+    this.text = text;
+  }
+
+  public boolean isMrkdwn() {
+    return mrkdwn;
+  }
+
+  public void setMrkdwn(boolean mrkdwn) {
+    this.mrkdwn = mrkdwn;
+  }
+
+}

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackSession.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackSession.java?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackSession.java (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackSession.java Fri Nov 25 09:21:13 2016
@@ -0,0 +1,122 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.crawler.notifications.slack;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpStatus;
+import org.apache.http.StatusLine;
+import org.apache.http.client.HttpResponseException;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.EntityBuilder;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/** This class represents a slack web hook session, without any protection
+* from threads waiting on sockets, etc.
+*/
+public class SlackSession
+{
+
+  private CloseableHttpClient httpClient;
+  private ObjectMapper objectMapper;
+  private final String webHookUrl;
+
+  /** Create a session */
+  public SlackSession(final String webHookUrl)
+  {
+    this.webHookUrl = webHookUrl;
+    this.objectMapper = new ObjectMapper();
+    this.objectMapper.setSerializationInclusion(Include.NON_NULL);
+
+    int connectionTimeout = 60000;
+    int socketTimeout = 900000;
+
+    RequestConfig requestConfig = RequestConfig.custom()
+        .setSocketTimeout(socketTimeout)
+        .setConnectTimeout(connectionTimeout)
+        .setConnectionRequestTimeout(socketTimeout)
+        .build();
+
+    httpClient = HttpClientBuilder.create()
+        .setDefaultRequestConfig(requestConfig)
+        .build();
+  }
+
+  public void checkConnection() throws IOException
+  {
+    HttpPost headRequest = new HttpPost(webHookUrl);
+    int statusCode = -1;
+    String responseBody = null;
+
+    try (CloseableHttpResponse response = httpClient.execute(headRequest)) {
+      responseBody = EntityUtils.toString(response.getEntity());
+      StatusLine statusLine = response.getStatusLine();
+      if (statusLine != null) {
+        statusCode = statusLine.getStatusCode();
+      }
+    }
+
+    boolean connectionOk = "invalid_payload".equals(responseBody) && statusCode == HttpStatus.SC_BAD_REQUEST;
+    if (!connectionOk) {
+      throw new HttpResponseException(statusCode, "unexpected status or payload");
+    }
+  }
+
+  public void send(String channel, String message) throws IOException
+  {
+    HttpPost messagePost = new HttpPost(webHookUrl);
+
+    SlackMessage slackMessage = new SlackMessage();
+    if (StringUtils.isNotBlank(channel)) {
+      slackMessage.setChannel(channel);
+    }
+    slackMessage.setText(message);
+
+    String json = objectMapper.writeValueAsString(slackMessage);
+
+    HttpEntity entity = EntityBuilder.create()
+      .setContentType(ContentType.APPLICATION_JSON)
+      .setContentEncoding(StandardCharsets.UTF_8.name())
+      .setText(json)
+      .build();
+
+    messagePost.setEntity(entity);
+    try (CloseableHttpResponse response = httpClient.execute(messagePost)) {
+      EntityUtils.consume(response.getEntity());
+    }
+  }
+
+  public void close() throws IOException
+  {
+    httpClient.close();
+    httpClient = null;
+    objectMapper = null;
+  }
+}
\ No newline at end of file

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_en_US.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_en_US.properties?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_en_US.properties (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_en_US.properties Fri Nov 25 09:21:13 2016
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SlackConnector.WebHook=Slack WebHook
+SlackConnector.Message=Message
+
+SlackConnector.EnterAWebHookUrl=Enter a Slack WebHook URL
+
+SlackConnector.WebHookUrlColon=WebHook URL:
+
+SlackConnector.JobFinished=Job finished
+SlackConnector.JobStopErrorAbort=Job stopped due to error abort
+SlackConnector.JobStopManualAbort=Job stopped due to manual abort
+SlackConnector.JobStopManualPause=Job stopped due to manual pause
+SlackConnector.JobStopSchedulePause=Job stopped due to scheduled pause
+SlackConnector.JobStopRestart=Job stopped due to job restart
+
+SlackConnector.ChannelColon=Channel:
+SlackConnector_MessageColon=Message:

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_es_ES.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_es_ES.properties?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_es_ES.properties (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_es_ES.properties Fri Nov 25 09:21:13 2016
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SlackConnector.WebHook=Slack WebHook
+SlackConnector.Message=Message
+
+SlackConnector.EnterAWebHookUrl=Enter a Slack WebHook URL
+
+SlackConnector.WebHookUrlColon=WebHook URL:
+
+SlackConnector.JobFinished=Job finished
+SlackConnector.JobStopErrorAbort=Job stopped due to error abort
+SlackConnector.JobStopManualAbort=Job stopped due to manual abort
+SlackConnector.JobStopManualPause=Job stopped due to manual pause
+SlackConnector.JobStopSchedulePause=Job stopped due to scheduled pause
+SlackConnector.JobStopRestart=Job stopped due to job restart
+
+SlackConnector.ChannelColon=Channel:
+SlackConnector_MessageColon=Message:

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_ja_JP.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_ja_JP.properties?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_ja_JP.properties (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_ja_JP.properties Fri Nov 25 09:21:13 2016
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SlackConnector.WebHook=Slack WebHook
+SlackConnector.Message=Message
+
+SlackConnector.EnterAWebHookUrl=Enter a Slack WebHook URL
+
+SlackConnector.WebHookUrlColon=WebHook URL:
+
+SlackConnector.JobFinished=Job finished
+SlackConnector.JobStopErrorAbort=Job stopped due to error abort
+SlackConnector.JobStopManualAbort=Job stopped due to manual abort
+SlackConnector.JobStopManualPause=Job stopped due to manual pause
+SlackConnector.JobStopSchedulePause=Job stopped due to scheduled pause
+SlackConnector.JobStopRestart=Job stopped due to job restart
+
+SlackConnector.ChannelColon=Channel:
+SlackConnector_MessageColon=Message:

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_zh_CN.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_zh_CN.properties?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_zh_CN.properties (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/native2ascii/org/apache/manifoldcf/crawler/notifications/slack/common_zh_CN.properties Fri Nov 25 09:21:13 2016
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SlackConnector.WebHook=Slack WebHook
+SlackConnector.Message=Message
+
+SlackConnector.EnterAWebHookUrl=Enter a Slack WebHook URL
+
+SlackConnector.WebHookUrlColon=WebHook URL:
+
+SlackConnector.JobFinished=Job finished
+SlackConnector.JobStopErrorAbort=Job stopped due to error abort
+SlackConnector.JobStopManualAbort=Job stopped due to manual abort
+SlackConnector.JobStopManualPause=Job stopped due to manual pause
+SlackConnector.JobStopSchedulePause=Job stopped due to scheduled pause
+SlackConnector.JobStopRestart=Job stopped due to job restart
+
+SlackConnector.ChannelColon=Channel:
+SlackConnector_MessageColon=Message:

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationHeader.js
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationHeader.js?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationHeader.js (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationHeader.js Fri Nov 25 09:21:13 2016
@@ -0,0 +1,34 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<script type="text/javascript">
+<!--
+
+function checkConfigForSave()
+{
+  if (editconnection.webHookUrl.value == "")
+  {
+    alert("$Encoder.bodyJavascriptEscape($ResourceBundle.getString('SlackConnector.EnterAWebHookUrl'))");
+    SelectTab("$Encoder.bodyJavascriptEscape($ResourceBundle.getString('SlackConnector.WebHook'))");
+    editconnection.webHookUrl.focus();
+    return false;
+  }
+  return true;
+}
+
+//-->
+</script>

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationView.html
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationView.html?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationView.html (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/ConfigurationView.html Fri Nov 25 09:21:13 2016
@@ -0,0 +1,30 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<table class="displaytable">
+
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.WebHookUrlColon'))</nobr>
+    </td>
+    <td class="value">
+      <nobr>$Encoder.bodyEscape($WEBHOOK_URL)</nobr>
+    </td>
+  </tr>
+
+</table>
+

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Configuration_Server.html
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Configuration_Server.html?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Configuration_Server.html (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Configuration_Server.html Fri Nov 25 09:21:13 2016
@@ -0,0 +1,36 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+#if($TabName == $ResourceBundle.getString('SlackConnector.WebHook'))
+
+<table class="displaytable">
+  <tr><td class="separator" colspan="2"><hr/></td></tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.WebHookUrlColon'))</nobr>
+    </td>
+    <td class="value">
+      <input id="webHookUrl" name="webHookUrl" type="text" size="32" value="$Encoder.attributeEscape($WEBHOOK_URL)"/>
+    </td>
+  </tr>
+</table>
+
+#else
+
+<input type="hidden" name="webHookUrl" value="$Encoder.attributeEscape($WEBHOOK_URL)"/>
+
+#end
\ No newline at end of file

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationHeader.js
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationHeader.js?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationHeader.js (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationHeader.js Fri Nov 25 09:21:13 2016
@@ -0,0 +1,40 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<script type="text/javascript">
+<!--
+
+function s${SeqNum}_checkSpecificationForSave()
+{
+  if (s${SeqNum}_checkMessageTabForSave() == false)
+    return false;
+  return true;
+}
+
+function s${SeqNum}_SpecOp(n, opValue, anchorvalue)
+{
+  eval("editjob."+n+".value = \""+opValue+"\"");
+  postFormSetAnchor(anchorvalue);
+}
+
+function s${SeqNum}_checkMessageTabForSave()
+{
+  return true;
+}
+
+//-->
+</script>

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationView.html
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationView.html?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationView.html (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/SpecificationView.html Fri Nov 25 09:21:13 2016
@@ -0,0 +1,104 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<table class="displaytable">
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobFinished'))</nobr></td></tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr></td>
+    <td class="value">
+      <nobr>$Encoder.bodyEscape($finished_CHANNEL)</nobr>
+    </td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr></td>
+    <td class="value">
+      $Encoder.bodyEscape($finished_MESSAGE)
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopErrorAbort'))</nobr></td></tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr></td>
+    <td class="value">
+      <nobr>$Encoder.bodyEscape($erroraborted_CHANNEL)</nobr>
+    </td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr></td>
+    <td class="value">
+      $Encoder.bodyEscape($erroraborted_MESSAGE)
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopManualAbort'))</nobr></td></tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr></td>
+    <td class="value">
+      <nobr>$Encoder.bodyEscape($manualaborted_CHANNEL)</nobr>
+    </td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr></td>
+    <td class="value">
+      $Encoder.bodyEscape($manualaborted_MESSAGE)
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopManualPause'))</nobr></td></tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr></td>
+    <td class="value">
+      <nobr>$Encoder.bodyEscape($manualpaused_CHANNEL)</nobr>
+    </td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr></td>
+    <td class="value">
+      $Encoder.bodyEscape($manualpaused_MESSAGE)
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopSchedulePause'))</nobr></td></tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr></td>
+    <td class="value">
+      <nobr>$Encoder.bodyEscape($schedulepaused_CHANNEL)</nobr>
+    </td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr></td>
+    <td class="value">
+      $Encoder.bodyEscape($schedulepaused_MESSAGE)
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopRestart'))</nobr></td></tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr></td>
+    <td class="value">
+      <nobr>$Encoder.bodyEscape($restarted_CHANNEL)</nobr>
+    </td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr></td>
+    <td class="value">
+      $Encoder.bodyEscape($restarted_MESSAGE)
+    </td>
+  </tr>
+
+</table>

Added: manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Specification_Message.html
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Specification_Message.html?rev=1771259&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Specification_Message.html (added)
+++ manifoldcf/branches/CONNECTORS-1344/connectors/slack/connector/src/main/resources/org/apache/manifoldcf/crawler/notifications/slack/Specification_Message.html Fri Nov 25 09:21:13 2016
@@ -0,0 +1,152 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+#if($TabName == $ResourceBundle.getString('SlackConnector.Message') && ${SeqNum} == ${SelectedNum})
+
+<table class="displaytable">
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobFinished'))</nobr></td></tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr>
+    </td>
+    <td class="value">
+      <input type="text" name="s${SeqNum}_finished_channel" size="32" value="$Encoder.attributeEscape($finished_CHANNEL)"/>
+    </td>
+  </tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr>
+    </td>
+    <td class="value">
+      <textarea name="s${SeqNum}_finished_message" rows="10" cols="50">$Encoder.bodyEscape($finished_MESSAGE)</textarea>
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopErrorAbort'))</nobr></td></tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr>
+    </td>
+    <td class="value">
+      <input type="text" name="s${SeqNum}_erroraborted_channel" size="32" value="$Encoder.attributeEscape($erroraborted_CHANNEL)"/>
+    </td>
+  </tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr>
+    </td>
+    <td class="value">
+      <textarea name="s${SeqNum}_erroraborted_message" rows="10" cols="50">$Encoder.bodyEscape($erroraborted_MESSAGE)</textarea>
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopManualAbort'))</nobr></td></tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr>
+    </td>
+    <td class="value">
+      <input type="text" name="s${SeqNum}_manualaborted_channel" size="32" value="$Encoder.attributeEscape($manualaborted_CHANNEL)"/>
+    </td>
+  </tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr>
+    </td>
+    <td class="value">
+      <textarea name="s${SeqNum}_manualaborted_message" rows="10" cols="50">$Encoder.bodyEscape($manualaborted_MESSAGE)</textarea>
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopManualPause'))</nobr></td></tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr>
+    </td>
+    <td class="value">
+      <input type="text" name="s${SeqNum}_manualpaused_channel" size="32" value="$Encoder.attributeEscape($manualpaused_CHANNEL)"/>
+    </td>
+  </tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr>
+    </td>
+    <td class="value">
+      <textarea name="s${SeqNum}_manualpaused_message" rows="10" cols="50">$Encoder.bodyEscape($manualpaused_MESSAGE)</textarea>
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopSchedulePause'))</nobr></td></tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr>
+    </td>
+    <td class="value">
+      <input type="text" name="s${SeqNum}_schedulepaused_channel" size="32" value="$Encoder.attributeEscape($schedulepaused_CHANNEL)"/>
+    </td>
+  </tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr>
+    </td>
+    <td class="value">
+      <textarea name="s${SeqNum}_schedulepaused_message" rows="10" cols="50">$Encoder.bodyEscape($schedulepaused_MESSAGE)</textarea>
+    </td>
+  </tr>
+
+  <tr><td class="message" colspan="2"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.JobStopRestart'))</nobr></td></tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector.ChannelColon'))</nobr>
+    </td>
+    <td class="value">
+      <input type="text" name="s${SeqNum}_restarted_channel" size="32" value="$Encoder.attributeEscape($restarted_CHANNEL)"/>
+    </td>
+  </tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('SlackConnector_MessageColon'))</nobr>
+    </td>
+    <td class="value">
+      <textarea name="s${SeqNum}_restarted_message" rows="10" cols="50">$Encoder.bodyEscape($restarted_MESSAGE)</textarea>
+    </td>
+  </tr>
+
+</table>
+
+#else
+
+<input type="hidden" name="s${SeqNum}_finished_channel" value="$Encoder.attributeEscape($finished_CHANNEL)"/>
+<input type="hidden" name="s${SeqNum}_finished_message" value="$Encoder.attributeEscape($finished_MESSAGE)"/>
+
+<input type="hidden" name="s${SeqNum}_erroraborted_channel" value="$Encoder.attributeEscape($erroraborted_CHANNEL)"/>
+<input type="hidden" name="s${SeqNum}_erroraborted_message" value="$Encoder.attributeEscape($erroraborted_MESSAGE)"/>
+
+<input type="hidden" name="s${SeqNum}_manualaborted_channel" value="$Encoder.attributeEscape($manualaborted_CHANNEL)"/>
+<input type="hidden" name="s${SeqNum}_manualaborted_message" value="$Encoder.attributeEscape($manualaborted_MESSAGE)"/>
+
+<input type="hidden" name="s${SeqNum}_manualpaused_channel" value="$Encoder.attributeEscape($manualpaused_CHANNEL)"/>
+<input type="hidden" name="s${SeqNum}_manualpaused_message" value="$Encoder.attributeEscape($manualpaused_MESSAGE)"/>
+
+<input type="hidden" name="s${SeqNum}_schedulepaused_channel" value="$Encoder.attributeEscape($schedulepaused_CHANNEL)"/>
+<input type="hidden" name="s${SeqNum}_schedulepaused_message" value="$Encoder.attributeEscape($schedulepaused_MESSAGE)"/>
+
+<input type="hidden" name="s${SeqNum}_restarted_channel" value="$Encoder.attributeEscape($restarted_CHANNEL)"/>
+<input type="hidden" name="s${SeqNum}_restarted_message" value="$Encoder.attributeEscape($restarted_MESSAGE)"/>
+
+#end



Mime
View raw message