The Kapow Extension - Example

This example shows the full source code, error messages and manifest for the Kapow SMS gateway extension.

KapowSMS.java

/* Copyright 2024 TomorrowX Pty Ltd.
 *
 * This is licensed software. 
 * 
 * You must not distribute, alter or copy this code unless you have a current and valid 
 * Tomorrow Software license. Where you have a current and valid license, you may use 
 * this code as an example for further rules development only for use within your organisation.
 * 
 * You must not distribute or allow to be distributed whether by act or omission this code 
 * to any third party without written permission from the Chief Executive Officer of 
 * TomorrowX Pty Ltd.
 *  
 * To the extent permitted by law or agreed to in writing by the Chief Executive Officer of 
 * TomorrowX Pty Ltd, 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 agreement for the specific language governing permissions and limitations 
 * under the license.
 */

package com.tomorrowx.rules.extensions;

import com.tomorrowx.core.rules.base.ChainPoint;
import com.tomorrowx.core.rules.base.Encoding;
import com.tomorrowx.core.rules.base.HttpBrowser;
import com.tomorrowx.core.rules.base.HttpResponseAsString;
import com.tomorrowx.core.rules.base.LogAdapter;
import com.tomorrowx.core.rules.base.Rule;
import com.tomorrowx.core.rules.base.VariableAttributeObject;

public class KapowSMS extends Rule {

	private String messageAttr;
	private int messageType;
	private String phoneAttr;
	private int phoneType;
	
	private String user;
	private String password;
	
	
	/**
	 * Initialize the rule upon load of the rule set
	 */
	public void initialize() {
		// Read the user ID and password from the credentials vault
		user = getCredentialsValue("KapowSMS","UserID");
		password = getCredentialsValue("KapowSMS","Password");
		
		// Check that the credentials are available
		if (user==null || password==null) {
			String[] errorInfo = { };
			setError("KPOW001", errorInfo);
		}

		// Read the message
		messageAttr = (String)getProperties().get("MessageAttribute");
		if (messageAttr==null || messageAttr.trim().equals("")) {
			String[] errorInfo = { };
			setError("KPOW003", errorInfo);
		}
		// Determine the type of value used. It can be a variable or a String in quotes
		messageType = getValueType(messageAttr);
		if (messageType==VAR_STRING) {
			messageAttr = getValueString(messageAttr);
		}

		// Read the phone number
		phoneAttr = (String)getProperties().get("PhoneAttribute");
		if (phoneAttr==null || phoneAttr.trim().equals("")) {
			String[] errorInfo = { };
			setError("KPOW004", errorInfo);
		}
		// Determine the type of value used. It can be a variable or a String in quotes
		phoneType = getValueType(phoneAttr);
		if (phoneType==VAR_STRING) {
			phoneAttr = getValueString(phoneAttr);
		}
		
	}
	
	/**
	 * Clean up resources upon unload of the rule set
	 */
	public void cleanup() {
		// Nothing here
	}

	/**
	 * Process the rule and send the provided message to Vodafone via it's Kapow service
	 * @return The updated VariableAttributeObject
	 */
	public VariableAttributeObject processRule(VariableAttributeObject vao, ChainPoint source) 
					throws Throwable {

		// Default to the error chain point
		ChainPoint cp = (ChainPoint)getRuleChainPoints().get("Failed");

		// Late determination of the value type. If it is a variable (not a constant), 
		// we must retrieve it now.
		String messageInp = messageAttr;
		if (messageType==VAR_VARIABLE) {
			messageInp = vao.getAttribute(messageAttr);
		}
		
		// Late determination of the value type. If it is a variable (not a constant), 
		// we must retrieve it now.
		String phone = phoneAttr;
		if (phoneType==VAR_VARIABLE) {
			phone = vao.getAttribute(phoneAttr);
		}
		
		// Prepare to send the SMS. It can be a real SMS or just a simulation on the test server
		if ((getRunType() & Rule.RUNTYPE_SEND_ALERTS)==0) {
			// This is a simulation - just let it through
			writeConsole("SMS: "+messageInp+" >> "+phone);
			cp = (ChainPoint)getRuleChainPoints().get("OK");
		} else {
			// Send SMS via Vodafone Kapow
			// Escape the message, so that special characters get encoded
			String message = Encoding.escape(messageInp);
			
			// Strip any special characters from the phone number
			StringBuffer no = new StringBuffer();
			for (int loop=0; loop<phone.length(); loop++) {
				char nc = phone.charAt(loop);
				if (nc=='+' || nc=='0' || nc=='1' || nc=='2' || nc=='3' || nc=='4' 	
					|| nc=='5' || nc=='6' || nc=='7' || nc=='8' || nc=='9') {
					no.append(nc);
				}
			}
			phone = no.toString();
				
			// Prepare the URL for sending
			HttpBrowser browser = new HttpBrowser(getRuleSet().getRulesEngine());
			try {
				HttpResponseAsString rsp = browser.doHttpGet("http://www.kapow.co.uk/scripts/sendsms.php?username="
						+user+"&password="+password+"&mobile="+phone+"&sms="+message,"UTF-8");
				browser.close();


				// Check if the reply contains an OK message
			    if (rsp.getResponse().indexOf("OK")>-1) {
					cp = (ChainPoint)getRuleChainPoints().get("OK");
			    } else {
					vao.setAttribute("ERROR",rsp.getResponse());
					writeConsole("WARNING: Kapow SMS fail >> "+phone+" >> "+rsp.getResponse());
			    }
				
			} catch(Exception ex) {
				// In case of an exception, ignore and set the ERROR attribute to the exception
				vao.setAttribute("ERROR",ex.toString());
				writeConsole("WARNING: Kapow SMS fail >> "+phone+" >> "+ex.toString());
				// Also log it
				String[] errorInfo = { "\""+ex.getLocalizedMessage()+"\"" };
				log(LogAdapter.LOGLEVEL_WARNING,renderMessage("BASE070", errorInfo),ex,this,null);
			} finally {
				browser.close();
			}
		}
		// Chain through to the correct chain point
		if (cp!=null) vao = cp.chain(vao,this);
		return vao;
	}
	
}

RulesInstaller.java

rules.xml

errors.properties

Last updated