ADF Super Code Snippets

Oracle’s ADF (Application Developer Framework) is J2EE technology stack to rapidly develop enterprise applications. As with all enterprise applications, ADF focuses on data handling and makes it quite easy to present the data to the users in variety of ways. As you will already know that ADF is a blanket term which encompasses many layers of the full tech stack. So ADF is divided into: –
* ADF Faces – Based on Java Server Faces 1.2 specification, this provides the UI of the application. It is built over Apache MyFaces Trinidad 1.2.x. So this is the View layer of ADF stack.
* ADFc – ADF Controller controls the life cycle of a typical ADF application. In fact it is part of ADF Faces. ADF Task Flows too form part of this layer.
* ADFm – ADF Model provides the brick and mortar to bind ADF Faces to the Model layer. In fact ADFm includes the Binding layer. This allows for loose coupling between the View and Model layers.
* ADF BC – ADF Business Components form the Model layer. It forms the data abstraction layer which does quite a lot of heavy lifting for the ADF stack.

The aim of this post is to list out some tips and code snippets which you may undoubtedly need while coding in ADF.

Some Important notes first

1 Clearing the selection on a ADF tree/tree-table/table from bean

First make sure the tree or tree-table or table does not have selectedRowKeys attribute set. Now you will notice that no row will be selected when the tree loads for the first time, but when user makes a selection then tree builds and stores the RowKeySet of the node the user selected. So, now whenever the tree loads and if the last selected row is visible then it will be shown selected. To work around this, we need to manually clear the tree’s selected rowkeyset after the user has made his selection (e.g. When we hide the tree, just before the tree is shown). Use the following code for that:-

RowKeySet rks = getTree().getSelectedRowKeys();
if (rks != null) {
    rks.clear();
}

2 Get the VO bound to an iterator

Sometimes we may need to manually execute an iterator, for this we need to get the handle to the VO instance bound to an iterator.

private ViewObject getVOFromIterator(DCIteratorBinding it) {
    ViewObject vo = null;
    if (it.hasRSI()) {
        return it.getRowSetIterator().getRowSet().getViewObject();
    } else {
        return it.getViewObject();
    }
}

3 Programmatically add partial target

AdfFacesContext.getCurrentInstance().addPartialTarget(targetComponent);

Make sure that targetComponent is not null else we may get NullPointerException.

4 Get query entered by user in Adf quickQuery component

QueryDescriptor qd = queryEvent.getDescriptor();
AttributeCriterion ac = qd.getCurrentCriterion();
String attrLabel = ac.getAttribute().getLabel();
Object attrValue = ac.getValues().get(0);

Note if you try ac.getValues() then it will mention that it has zero elements, even when get(0) returns a value.

5 Building Disclosed RowKeySet for nodes in a tree/tree-table

/**
* Ref: http://www.oracle.com/technetwork/developer-tools/adf/learnmore/61search-in-rendered-trees-177577.pdf
* @param treeBinding
* @param keys
* @return
*/
private RowKeySet buildDiscloseRowKeySet(JUCtrlHierBinding treeBinding, RowKeySet keys) {
    RowKeySetImpl discloseRowKeySet = new RowKeySetImpl();
    Iterator iter = keys.iterator();
    while (iter.hasNext()) {
        List keyPath = (List)iter.next();
        JUCtrlHierNodeBinding node = treeBinding.findNodeByKeyPath(keyPath);
        if (node != null && node.getParent() != null && !node.getParent().getKeyPath().isEmpty()) {
            //store the parent path
            discloseRowKeySet.add(node.getParent().getKeyPath());
            //call method recursively until no parents are found
            RowKeySetImpl parentKeySet = new RowKeySetImpl();
            parentKeySet.add(node.getParent().getKeyPath());
            RowKeySet rks = buildDiscloseRowKeySet(treeBinding, parentKeySet);
            discloseRowKeySet.addAll(rks);
        }
    }
    return discloseRowKeySet;
}

6 Select a node in tree/tree-table

Variant 1

private void selectNode(List<List<?>> pathKeys, org.apache.myfaces.trinidad.component.UIXTree targetComponent) {
    List<Object> lstKeys = new ArrayList<Object>();
    for(int level = 0; level < pathKeys.size(); level++) {
        List<?> keys = pathKeys.get(level);
        Object[] oKeys = new Object[keys.size()];
        for (int index = 0; index < oKeys.length; index++) {
            oKeys[index] = keys.get(index);
        }
        lstKeys.add(new Key(oKeys));
    }
    if(lstKeys.size() == 1) {
        lstKeys = Collections.singletonList(lstKeys.get(0));
    } else {
        lstKeys = Collections.unmodifiableList(lstKeys);
    }
    RowKeySet keyset = new RowKeySetImpl();
    keyset.setCollectionModel((CollectionModel)(targetComponent.getValue()));
    keyset.add(lstKeys);
    targetComponent.setSelectedRowKeys(keyset); //After this targetComponent.setDisclosedRowKeys()
                                                //needs to be called to reveal the node is its parents
                                                //are collapsed.
}

Where pathKeys is of the following form:- Take an example, where we want to select node C, in the following tree.

A [Row from VO1, keys A1]
|--B [Row from VO2, keys B1, B2, B3]
    |--C [Row from VO3, keys C1, C2]

Then pathKeys will be a list like shown below:-

{ {A1}, {B1, B2, B3}, {C1, C2} }

Variant 2 (Maybe this is a better approach, but not tested)

private void selectNode(List<List<?>> pathKeys, org.apache.myfaces.trinidad.component.UIXTree targetComponent) {
    List<Object> lstKeys = new ArrayList<Object>();
    for(int level = 0; level < pathKeys.size(); level++) {
        List<?> keys = pathKeys.get(level);
        Object[] oKeys = new Object[keys.size()];
        for (int index = 0; index < oKeys.length; index++) {
            oKeys[index] = keys.get(index);
        }
        lstKeys.add(new Key(oKeys));
    }
    if(lstKeys.size() == 1) {
        lstKeys = Collections.singletonList(lstKeys.get(0));
    } else {
        lstKeys = Collections.unmodifiableList(lstKeys);
    }
    JUCtrlHierBinding treeBinding = (JUCtrlHierBinding) ((CollectionModel)targetComponent.getValue()).getWrappedData();
    JUCtrlHierNodeBinding nodeBinding = treeBinding.findNodeByKeyPath(lstKeys);
    Key rowKey = nodeBinding.getRowKey();
    JUIteratorBinding iterator = nodeBinding.getIteratorBinding();
    iterator.setCurrentRowWithKey(rowKey.toStringFormat(true));
}

7 Create a flexible query (search box) which allows you to use custom ViewCriteria with ADF quickQuery

Custom Quick Query ADF Component

Custom Quick Query ADF Component

To create search box like the one above.

UI code

<af:quickQuery id="qq1" queryListener="#{pageFlowScope.Bean.invokeSearch}"
    searchDesc="Quick Search" shortDesc="Quick Search" label="Quick Search">
    <af:inputText id="itQq1" value="#{pageFlowScope.Bean.searchKeyword}"
        simple="true" partialTriggers="cb3" shortDesc="Quick Search"/>
    <f:facet name="end">
        <af:commandButton text="Clear" id="cb3" actionListener="#{pageFlowScope.Bean.clearSearch}"/>
    </f:facet>
</af:quickQuery>

  • We have defined our own input box so that Go button and the auto-generated input boxes get disabled if quickQuery doesn’t have any model.
  • Our custom input box allows us to directly read and modify the input box’s content. This is needed by Clear functionality.
  • Input box has simple set to true, so that its label is not displayed.
  • Official quickQuery reference – http://jdevadf.oracle.com/adf-richclient-demo/docs/tagdoc/af_quickQuery.html.

Bean code (in Bean.java)

private String searchKeyword;

public String getSearchKeyword() {
    return searchKeyword;
}

public void setSearchKeyword(String keyword) {
    searchKeyword = keyword;
}

public void invokeHierSearch(QueryEvent queryEvent) {
    if (searchKeyword != null && !searchKeyword.isEmpty()) {
        DCIteratorBinding it = ADFUtil.findIterator("VOIterator");
        ViewObject vo = getVOFromIterator(it);
        vo.applyViewCriteria(vo.getViewCriteriaManager().getViewCriteria("SearchCriteria"));
        vo.setNamedWhereClauseParam("keyword", searchKeyword);
        vo.executeQuery(); //Iterator will be executed after UI is updated.
        searchVisible = true;
    } else {
        searchVisible = false;
    }
    AdfFacesContext.getCurrentInstance().addPartialTarget(...); //Update UI
}

public void clearSearch(ActionEvent e) {
    searchKeyword = null;
    invokeHierSearch(null);
}

private ViewObject getVOFromIterator(DCIteratorBinding it) {
    ViewObject vo = null;
    if (it.hasRSI()) {
        return it.getRowSetIterator().getRowSet().getViewObject();
    } else {
        return it.getViewObject();
    }
}

8 Get reference to Bindings from bean

DCBindingContainer bindings = ((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry());

9 Programmatically execute iterator

DCBindingContainer bindings = ((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry());
bindings.findIteratorBinding("Iterator").executeQuery();

10 Get reference to method binding (operation binding) in bean

Get bindings from 8.

OperationBinding meth = bindings.getOperationBinding("methodBindingId");
Map args = meth.getParamsMap();
args.put(“arg1”, arg1Value);
…
meth.execute();

11 Get reference to pageFlowScope in bean

AdfFacesContext.getCurrentInstance().getPageFlowScope()

This returns a Map which we can use to read or set values.

12 Evaluate random EL value expressions in bean

FacesContext fc = FacesContext.getCurrentInstance();
ELContext elContext = fc.getELContext();
ExpressionFactory ef = fc.getApplication().getExpressionFactory();
ValueExpression exp = ef.createValueExpression(elContext, "#{expression}", ClassOfOutcomeOfExpression.class);
ClassOfOutcomeOfExpression obj = (ClassOfOutcomeOfExpression) exp.getValue(elContext);

ClassOfOutcomeOfExpression can be Object if you don’t care about the outcome. It has too much boilerplate code.

So place the following code in bean.

private <T> T evaluateEL(String el, Class<T> type) {
    FacesContext fc = FacesContext.getCurrentInstance();
    ELContext elContext = fc.getELContext();
    ExpressionFactory ef = fc.getApplication().getExpressionFactory();
    ValueExpression exp = ef.createValueExpression(elContext, el, type);
    return (T) exp.getValue(elContext);
}

13 Evaluate random EL method expressions in bean

FacesContext fc = FacesContext.getCurrentInstance();
ELContext elContext = fc.getELContext();
ExpressionFactory ef = fc.getApplication().getExpressionFactory();
MethodExpression meth = ef.createMethodExpression(elContext, "#{expression}", Outcome.class, new Class[]{Arg1.class, Arg2.class, …});
Outcome obj = (Outcome) meth.invoke(elContext, new Object[]{arg1Obj, arg2Obj, …});

Example: You need to code the below if you override treetable’s selectionListener.

MethodExpression meth = ef.createMethodExpression(elContext, "#{bindings.treeBinding.treeModel.makeCurrent}",
    Object.class, new Class[]{SelectionEvent.class});
meth.invoke(elContext, new Object[]{selectionEvent});

14 Get value from attribute binding in bean

Get bindings from 8.

((oracle.binding.AttributeBinding)bindings.getControlBinding("bindingName")).getInputValue();

15 Get value from list binding in bean

Get bindings from 8.

((JUCtrlListBinding)bindings.getControlBinding("bindingName")) .attributeValue();

16 Implementing custom selection listener

In this use-case we are providing our own selection listener for the TreeTable because we are interested in capturing the selected node’s VO row instance.

public void onTreeSelect(SelectionEvent selectionEvent) {
    //Invoking makeCurrent manually since it will no longer be called as we have provided our own.
    FacesContext fc = FacesContext.getCurrentInstance();
    ELContext elContext = fc.getELContext();
    ExpressionFactory ef = fc.getApplication().getExpressionFactory();
    MethodExpression meth = ef.createMethodExpression(elContext, "#{bindings.treeBinding.treeModel.makeCurrent}",
        Object.class, new Class[]{SelectionEvent.class});
    meth.invoke(elContext, new Object[]{selectionEvent}); //Selection done now getting data from model.
    RichTreeTable myTree = (RichTreeTable) selectionEvent.getSource(); //changed for Serialization
    RowKeySet rowKeys = selectionEvent.getAddedSet();
    if (rowKeys != null) {
        CollectionModel treeModel = (CollectionModel) myTree.getValue();
        JUCtrlHierBinding treeBinding = (JUCtrlHierBinding) treeModel.getWrappedData();
        Iterator selection = rowKeys.iterator();
        while (selection.hasNext()) {
            //Will loop only once since we have allowed single selection.
            List key = (List) selection.next();
            JUCtrlHierNodeBinding nodeBinding = treeBinding.findNodeByKeyPath(key);
            Row row = nodeBinding.getRow(); //Your custom code which will use row.
                                            //row will be the instance of ViewRowImpl
                                            //which backs the currently selected node.
        }
    }
}

17 Get all rows (nodes) of a Tree or TreeTable

In my use-case I wanted to iterate over all the rows in the TreeTable to find if it has any rows with pending changes. This was to prevent the user from carrying out some actions if there were unsaved changes. There are many ways to achieve this, like check if transaction or view port is dirty, but I did not care about the state of various other components on the page which are outside the tree.

public List<Row> getTreeNodes(CollectionModel treeModel) {
    List<Row> rows = new ArrayList<Row>();
    JUCtrlHierBinding treeBinding = (JUCtrlHierBinding) treeModel.getWrappedData();
    Queue<JUCtrlHierNodeBinding> nodeBindings = new LinkedList<JUCtrlHierNodeBinding>();
    nodeBindings.add(treeBinding.getRootNodeBinding());
    while (!nodeBindings.isEmpty()) {
        List<JUCtrlHierNodeBinding> childNodes = nodeBindings.remove().getChildren();
        if (childNodes != null) {
            for (JUCtrlHierNodeBinding _node : childNodes) {
                nodeBindings.add(_node); rows.add(_node.getRow());
            }
        }
    }
    return rows;
}

18 Programmatically loading resource bundle

Recently I had one requirement where I needed to programmatically load a resource bundle from a managed bean and read the translated strings. I could not find any official documentation on this, and the net is rife with many alternatives which did not work for me. Anyway here is my version which is simple and works well for me.

//import java.util.ResourceBundle;
//import oracle.javatools.resourcebundle.BundleFactory;
ResourceBundle myBundle = BundleFactory.getBundle("fully.qualified.class_name.of.the.bundle");
String msg = getMsg(myBundle, "myKey");

Where the method getMsg() is

public String getMsg(ResourceBundle bundle, String key) {
    if (bundle == null) {
        return "";
    }
    try {
        return bundle.getString(key);
    } catch (MissingResourceException ex) { //Log error here. }
    return "";
}

Please make sure that the bundle class is available on the classpath.

Disclaimer: The views expressed on this blog are my own and do not necessarily reflect the views of my employer. This is may or may not be the recommended way. This is provided here merely in the spirit of sharing. You are more than welcome to post a correction or make an addition in the comment section below. I will happily update this post accordingly.

iFlickr PHP Script: Create mRSS feed of interesting pictures on Flickr.com

Did you notice the “Flickr Gallery” on top right corner of the home page of this blog? The picture slide show is provided by Google’s Ajax Slide Show, but this post is not about that. Google’s Slide Show needs a mRSS feed, which it parses to get the list of thumbnails it wants to present. mRSS is just a normal RSS feed particularly tailored for presenting media. It gets its ‘m’ from media. In this case it is picture media. For my blog’s “Flickr Gallery”, I have scheduled a cron job which runs every day at 5.30 am UTC. This way every day my blog gets fresh set of interesting pictures to present. You can get a good example of mRSS feed on my site at http://www.applegrew.com/util/if.xml. Safari and Firefox will use their own styling rules to style this XML. If you want to check it out the way I want it, then view it in Google Chrome.

The Script

This PHP script spits out mRSS feed of the interesting pictures on Flickr.com. This script can be invoked from web or directly from command line. When invoked it connects to Flickr using its API and gets the list and all related infos from there. Flickr likes to call this list – Flickr Interestigness.

Download package (License GPL v2)

How to use this script

This scripts accepts a number of parameters:-

  • api_key (Default: NoKeyGiven) – The Flickr API key. Get it from here.
  • pg (Default: 1) – Which page to fetch. This is to help you paginate if that makes sense for you.
  • per_pg (Default: 10) – How many pictures you want per page. So, if you want 11th to 20th most interesting pictures then set pg to 2 and per_pg to 10.
  • thumbnail_type (Default: , i.e. not set) – Possible values are – SquareThumbnail, Small, Medium or *Large. *The picture of the type set here is set as thumbnail picture. If the type specified is not available then no thumbnail is mentioned. If this is not set then all possible picture sizes would be listed as thumbnails in the feed, with the bigger pics at the top.
  • min_size (Default: 0, i.e. not set) – If set (i.e. it is not set to zero) then the pic which is equal or just larger than this dimension will be chosen as thumbnail.

This script can be run from command line as shown below:-

$ /usr/bin/php iflickr.php --api_key=key_here --min_size=240 > mrss.xml

When run from web:-

http://example.com/iflickr.php?api_key=key_here&min_size=240

Please note: To be able to run this from web, you need to set $bind_address variable in the script as empty string.

Script that notifies via email when your server has updates

If you are the administrator of a server then you definitely understand the importance of keeping your system updated always.

The following script will send you a mail whenever your server needs an update. The content of the mail will list out all the available updates.

The script

[code lang=”shell”]
#!/bin/bash
# Author: AppleGrew
# Site: www.applegrew.com
# License: GPL v2

yum check-update > /tmp/checkupdate.log
if [[ $? == 100 ]]
then
mail -s "New YUM updates available" -r admin@example.com $MAILTO < /tmp/checkupdate.log
fi
[/code]

Notes:

  • This script has been tested on CentOS 6 but should run on all RedHat based systems.
  • In the above script, change admin@example.com to any valid email id which your server is authorized to send. This the email id for the ‘From’ field. For example you can not set this to (say) someone@gmail.com. Since Google did not authorize your server to send emails on behalf of gmail.com.

Installation notes

  • Copy this script to some directory in your server and give it execute permission.
  • Now schedule a cron job for this script. You can set this job for any user, since this script does not need root privileges.
  • In the cronjob make sure to set the MAILTO environment variable. The script uses this variable to determine the recipient of the notification.

Example cronjob

[code lang=”plain”]
MAILTO=yourmail@email.com
0 0 * * * /home/user1/checkupdate.sh
[/code]

CInk version 2 finally released!

Finally CInk version 2 has been released.

Some key new things

  • New website with complete API documentation and guides on how you can use CInk JS code.
  • Finally released the full source code of CInk renderer and compiler. License – GPL v3.
  • CInk finally supports all the features of original CFDG, including Paths.
  • CInk has introduced support for texts which extends the capabilities of CFDG considerably. Check out the cool demo – Neon Letters. To learn more about it see – “Text transforms” section here.

Last but not the least, you can post comments on CInk website. The comments section is at the bottom of each page.

Goto Cink website – cink.applegrew.com.

Create your own Cyberoam client in Python!

This is a very old post. Reposting it since while migrating it from blogger.com to here it got lost. Found it recently. Not sure how relevant or correct is this now.


Cyberthon updated to version 2.5 by Vinit and Siddhartha Sahu:-
Get the latest code from https://github.com/siddharthasahu/Cyberthon-enhanced.
Cyberthon updated to version 1.2:-
Added a new feature in this version. Now Cyberthon won’t exit ever, once started, even when it can’t connect to Cyberoam server. If liked its old behavior then set never_quit to False
Code fixed now. Sorry, I didn’t notice before (for 2 months since posting it here) that the code here was not working. I think it is fixed now. The problem was that the tabs were being expaded here differently. So, I just ran expand cyberthon.py command to expand all tabs in it beforehand.

My college uses the software Cyberoam for controlling the bandwidth and timing allocated to us for surfing the internet. If you don’t know what is it then visit here. So, to access the internet we all need to install the client software and login via that. But I don’t like to install it because it feels like a college spy on my computer, you may find it irrational but I can’t help being a paranoid. I have always used the web login page of Cyberoam but it is not a very good solution, first because I will always need to keep the browser open. (The Cyberoam page refreshes at a specific time periodically. If it fails to do so then you get logged out.) Second problem is that on my Linux platform if I work from console mode then I can’t login because no browser can run without GUI support (I know of Lynx but I haven’t been able to use it for it.)

Recently I thought of investigating the working of the web login page of Cyberoam. After bringing up the login page of Cyberoam I changed the value of attribute method of form tag to GET from POST. So after filling-up the username and password when I hit enter key, there it was all the details that are sent from my browser to Cyberoam server in my browser address bar. I thought of simulating the POST action using a Python code. It required only a pinch of Python to do this. I tried the following Python code to simulate that and it worked, as it should. You too can try the following code and login to Cyberoam.

Code:

[code lang=”python” wraplines=”false”]
import urllib
urllib.urlopen("http://192.168.5.10:8090/corporate/servlet/CyberoamHTTPClient","mode=191&isAccessDenied=null&url=null&message=&username=YourUserName&password=YourPassword&saveinfo=saveinfo&login=Login")[/code]

Be sure to substitute YourUserName and YourPasswordfor your username and password respectively. The above will get you logged in but won’t keep you logged it because you need to re-post the login data at every (usually) 3 minutes. So, I got down to work again. Below is quick and dirty shell script to get around this problem. Note the above code has been distorted and compressed into single line and passed via piping to Python in script below.

Code:

[code lang=”bash” wraplines=”false”]
while [[ 1 == 1 ]]
do
printf "%s\n%s\n" "import urllib" "urllib.urlopen(\"http://192.168.5.10:8090/corporate/servlet/CyberoamHTTPClient\",\"mode=191&isAccessDenied=null&url=null&message=&username=YourUserName&password=YourPassword&saveinfo=saveinfo&login=Login\")" |python
sleep 3m
done[/code]

Again in the above code do replace YourUserName and YourPassword for your actual username and password respectively. Well now it was working great. 🙂 As usual I was again not satisfied because how will I know if I have logged in successfully or not? The only way for that was by parsing the returned page after logging-in for the message. I noticed that returned page’s source code contained…

[code lang=”html”][/code]

Please notice the part message. The value after that is the message I was seeking. So, all I needed is to parse this page for the value of attribute src of the tag frame. Also, note this very string also contains some more very useful values, viz. – loginstatus and liverequesttime. I noticed that value of loginstatus becomes true when logged in otherwise it remains false, and the value of liverequesttimegiave the time (in seconds) in which to re-post the login data.

The HTML parsing class in the Python script (which I wrote) below is based on the code from the great HTML parsing tutorial located here. Note the script uses the zenity command to display GUI dialog boxes. If you do not have this installed or simply don’t want to display GUI dialog boxes then start the script with -nogui argument. If you want the script to remain completely silent then use the -silent argument. I call this script Cyberthon (=Cyberoam+Python) 😉

Requirement(s):-
1) Python 2.5 (may work with previous versions, but not tested)
2) Zenity (needed to show the dialog boxes, use -nogui switch if you want the messages to appear on the console.)
Code:

[code lang=”python” wraplines=”false”]#!/usr/bin/python
#!/usr/bin/python

#Program Name: Cyberthon (Python Cyberoam Client)
#Coder AppleGrew
#License GPL
#Version 1.2
cyberroamIP = "192.168.5.10" #The IP of the Cyberoam site.
cyberroamPort = "8090" #Set to "" if not using.
username = "your_username" #Your username
passwordFile = "/home/you/.passwd" #Path file containing a single string, your password.
sleeptime = 0 #in minutes or set to 0, it will then parse this value from the cyberoam returned page dynamically.
never_quit = True #Once started cyberthon will never, even when the cyberoam server cannot be connected.

import sys

silent = False
nogui = False
for arg in sys.argv:
if "-silent" == arg:
silent = True
if "-nogui" == arg:
nogui = True

#Parsing and logging in too.
import sgmllib

class MyCyberroamParser(sgmllib.SGMLParser):
"A simple parser class."

def parse(self, s):
"Parse the given string ‘s’."
self.feed(s)
self.close()

def __init__(self, verbose=0):
"Initialise an object, passing ‘verbose’ to the superclass."

sgmllib.SGMLParser.__init__(self, verbose)
self.required_entities = [‘message’,’loginstatus’,’liverequesttime’]
self.frames_attr = []
self.in_required_entity = False
self.current_entity = ""
self.entity_values = {}

def do_frame(self, attributes):
for name, value in attributes:
if name == "src":
self.frames_attr.append(value)

def unknown_entityref(self,ref):
self.current_entity = ref
if ref in self.required_entities:
self.in_required_entity=True

def handle_data(self, data):
"Try to get the value of entity &message. Used in 2nd pass of parsing."

if self.in_required_entity:
self.entity_values[self.current_entity] = data[1:] #To remove the preceeding =
self.in_required_entity = False

def get_src(self,index=-1):
"Return the list of src targets."
if index == -1:
return self.frames_attr
else:
return self.frames_attr[index]

import urllib, sgmllib,time,commands,os

pf = open(passwordFile)
passwd = pf.readline()
pf.close()
if passwd[-1] == ‘\n’: #Removing terminating newline character.
passwd = passwd[:-1]

cyberroamAddress = cyberroamIP
if cyberroamPort != "":
cyberroamAddress = cyberroamAddress+":"+cyberroamPort

sec2sleep = 60*sleeptime
lastmsg = ""
msgChanged = True
lastMsgWasFailMsg = False
sec2sleepOnError = 6
while True:
try:
# Logging in and fetching the Cyberroam login page.
f = urllib.urlopen("http://"+cyberroamAddress+"/corporate/servlet/CyberoamHTTPClient","mode=191&isAccessDenied=null&url=null&message=&username="+username+"&password="+passwd+"&saveinfo=saveinfo&login=Login")
sec2sleepOnError = 6
except IOError, (errno, strerror):
if not silent:
print "Connection to Cyberoam server timed out. Error(%s): %s" % (errno, strerror)

if sec2sleepOnError > 30:
if not silent:
if nogui:
print "Quitting program."
else:
if never_quit:
if not lastMsgWasFailMsg:
os.popen(‘zenity –info –text="Failed to connect to server, but I am NOT quitting." –title="Cyberthon" >/dev/null’)
lastMsgWasFailMsg = True
else:
commands.getoutput(‘zenity –info –text="Could not connect to the server. Quitting program." –title="Cyberthon"’)
if not never_quit:
sys.exit(1)
else:
sec2sleepOnError = 6

if not silent:
print "Retrying in %s seconds" % sec2sleepOnError

time.sleep(sec2sleepOnError)
sec2sleepOnError = sec2sleepOnError*2
continue

s = f.read()

# Try and process the page.
# The class should have been defined first, remember.
myparser = MyCyberroamParser()
myparser.parse(s)

# Get the the src targets. It contains the status message. And then parse it again for entity &message.
qindex = myparser.get_src(1).index(‘?’)
srcstr = myparser.get_src(1)[:qindex+1]+’&’+myparser.get_src(1)[qindex+1:]

myparser.parse(srcstr)

message = myparser.entity_values[‘message’]
if lastmsg != message or lastMsgWasFailMsg:
lastmsg = message
msgChanged = True
lastMsgWasFailMsg = False

if (not silent) and msgChanged:
msgChanged = False

msg=”
i=0
while i < len(message): #Converting hex nos. to characters. t=message[i] if message[i]==’%’: no=int(message[i+1:i+3],16) t=chr(no) i=i+2 msg=msg+t i=i+1 message = "" for x in msg:#Changing all + to space. if x == ‘+’: x = " " message=message+x if nogui: print message else: os.popen(‘zenity –info –text="From Cyberoam: ‘+message+’" –title="Cyberthon" >/dev/null’)

if myparser.entity_values[‘loginstatus’].lower()!="true":
break;

if sleeptime==0:
sec2sleep = int(myparser.entity_values[‘liverequesttime’])
time.sleep(sec2sleep)
[/code]

Please copy the file very carefully. A single extra space here and there may throw Python haywire, making it throw up all sorts of nasty syntax errors. Paste the contents of this code in a file and name it – Cyberthon.py.