Friday, December 27, 2013

Java pattern matching using GLOB patterns (* and ?)

Java has partial glob support since java 7 filePath, but truly glob support I could only find in the good, old, retired, jakarta-oro lib.

Here goes a simple example of how to use it

for(String regex:regexes){
  
    //it's the unix GLOB regex. Java itself does not support it
    //but the good old jakarta oro does
    GlobCompiler compiler=new GlobCompiler();
    Perl5Matcher matcher=new Perl5Matcher();
  
    //there are some interesting options you may want to try
    //org.apache.oro.text.regex.Pattern pat = compiler.compile(regex,GlobCompiler.QUESTION_MATCHES_ZERO_OR_ONE_MASK );
    org.apache.oro.text.regex.Pattern pat = compiler.compile(regex.trim());
    if (site != null && matcher.matches(site, pat)){
        passwordPattern = pattern;
        break;
    }
}

Tuesday, December 17, 2013

Primefaces: capturing the target list item clicked

First of all, kudos to Hatem Alimam for his answer, who solved this problem.

Here's the problem.

I have a @ViewScoped managed bean with a p:pickList filtered by a p:selectMany component using a p:ajax update event.

Like this

<p:outputLabel for="siteFilter" value="Site Filter:" style="width:100px;"/>
<p:selectOneMenu converter="#{siteTypeConverter}" id="siteFilter" value="#{myMB.selectedSiteType}" style="width:200px;">              
   <f:selectItem itemLabel="Select Site Type" itemValue="#{null}" />
   <f:selectItems value="#{myMB.siteTypeFilterList}" var="st" itemLabel="#{st.name}" itemValue="#{st}" />
   <p:ajax update="sites" listener="#{myMB.handleSiteTypeFilterChange}" oncomplete="rebindClicks()"/>
</p:selectOneMenu>

<p:outputLabel for="sites" value="Sites:" style="width:100px;"/>
<p:pickList
   widgetVar="xyzabc"
   id="sites"
   value="#{myMB.sites}"
   var="site"                 
   converter="#{siteConverter}"
   itemLabel="#{site.siteType.name}.#{site.name}"
   itemValue="#{site}" /> 

The idea here is to trigger a new event when the user clicks on some pickList target list item.

So, as suggested by @Hatem, we have to bind the click event to each one of the target elements. Like this

(...)
   <p:remoteCommand name="updateCommand" action="#{myMB.updateAccounts}" update="accounts"/>
</h:form>
<h:outputScript library="js" name="pickListHack.js" />   
(...)

Notice that I had to add it AFTER the form.

and pickListHack.js is located at WebContent/resources/js/pickListHack.js

function rebindClicks() {
    xyzabc.jq.on('click','.ui-picklist-target li',function(){
        var item = $(this).attr('data-item-value');
        alert(item);
        updateCommand([{name:'param', value:item}]);
   });
};

$(document).ready(function() {
    rebindClicks();
});

The trick here seems to be that, after the update event, the binds are lost, so we have to rebind them after the update. That's  why p:ajax has that oncomplete event.

Finally, when the user clicks on the element from the target list, we call the updateCommand, declared via p:remoteCommand.

Notice that the selected item is passed as a parameter called "param". We get this parameter back in the managed bean like this

public void updateAccounts(){
   String value = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("param");
   System.out.println(">"+value);
   this.accounts = value;
}

In this case, the value is just the ID, because that's what my siteConverter does to the object.

@ManagedBean
@RequestScoped
public class SiteConverter implements Converter,Serializable{

    private static final long serialVersionUID = -194442504109002565L;

    @EJB
    private MyEJB myEJB;

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
            throws ConverterException {
        if (arg2 != null){
            Site s = myEJB.getSiteById(Long.parseLong(arg2));
            return s;
        }else{
            return null;
        }
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
            throws ConverterException {
        if (arg2 != null){
            Site s = (Site)arg2;
            return String.valueOf(s.getId());
        }else{
            return null;
        }
    }
}



Monday, December 16, 2013

Java, expect and groovy

If you need the TCL expect functionality in your java software, you basically have 4 options


TCL-Java bridges such as Jacl/TclBlend (http://tcljava.sourceforge.net) are useful to run small pieces of TCL code, but since expect contains some native C libraries, jacl is not an option. In the best case, you can write a TCL wrapper with TclBlend that calls your java code instead of the opposite.

So, from these 4 options, only ExpectJ supports expect "interact" mode. In expect, the "interact" command gives back the session control to the user. So, if the idea is to connect to a remote site after multiple hops, and get the session back (instead of running fire-and-forget scripts), ExpectJ is the way to go.

Now, you can also expose ExpectJ directives in a nice way (DSL) using groove. This is specially useful if you want to let the user write his/her own "expect" scripts.

Allowing the user to run his/her own scripts from inside an application also has security issues. For example, would you allow the user to add a "system.exit()" command? Not a good idea. We have to limit this too.

Groovy has some syntactic sugar features that lets the developer to write DSLs in a much faster and simpler way that it would be if you decide to write a full language from the scratch, with tools like ANTLR and JavaCC. You can also use eclipse to edit and run your Groovy code in a nice IDE and the learning curve, for Java developers, is nice.

To demonstrate a simple proof-of-concept, let's assume these 4 steps

  • Wrap ExpectJ engine in a java class
  • Wrap java class into a Groovy class
  • Add Groovy syntatic sugar
  • Sandbox Groovy script interpreter

We're also using Jsch (http://www.jcraft.com/jsch/), a pure java-based SSH client.

Step #1 - Wrap ExpectJ engine in a java class

    public class Expect {
       
        private ExpectJ expectinator;
        private Spawn spawn;
        private int lastPos;

        public Expect() throws IOException{
            expectinator = new ExpectJ(5);
            spawn = expectinator.spawn("localhost", 22, "leoks", "xyz");
        }
       
        public void send(String s) throws IOException{
            spawn.send(s+"\n");
        }
       
        public String expect(String s) throws IOException, TimeoutException{
            spawn.expect(s);
            return getReply();
        }
       
        private String getReply(){
            String all = spawn.getCurrentStandardOutContents();
            int newLastPos = all.length();
            String reply = all.substring(lastPos);
            lastPos = newLastPos;
            return reply;
        }
       
    }

Step #2 - Wrap java class into a Groovy class

    class ExpectGroovy {
       
        def Expect expectJava = new Expect()
       
        def expect(String expression){
            expectJava.expect(expression)
        }
       
        def send(String command){
            return expectJava.send(command)
        }
    }

Step #3 - Add Groovy syntatic sugar

    class Example {
        static main(args) {
            def binding = new Binding(exp: new ExpectGroovy())
           
            ExpectSandbox sandbox = new ExpectSandbox();
           
            def config = new CompilerConfiguration()
            config.scriptBaseClass = ExpectBaseScriptClass.class.name
            config.addCompilationCustomizers(new SandboxTransformer())
            sandbox.register()
           
            def shell = new GroovyShell(this.class.classLoader, binding, config)
            String script = ...
            try{
                shell.evaluate(script)
            }catch(e){e.printStackTrace()}
           
            sandbox.unregister()
            print "OK"
        }
    }
    abstract class ExpectBaseScriptClass extends Script{
        void expect(String expression){
            this.binding.exp.expect expression
        }
       
        void send(String command){
            this.binding.exp.send command
        }
    }

Step #4 - Sandbox Groovy script interpreter

Now, the groovy script may look like this

    expect "\\$"

    //try to uncomment - the script does not kill the process, instead this instruction
    //is blocked by groovy security restrictions
    //see http://groovy.codehaus.org/Advanced+compiler+configuration
    //System.exit(0)

    x = 0
    while (x < 5){
        result = send "hostname"
        expect "\\$"
        x++
    }

Please notice that

  •     The “expect” object is implicit (binding)
  •     Groovy loops and variable assignment for free (mallet for example needed a special code just for loop evaluation)
  •     Groovy allows to restrict certain undesired commands, as well as java packages restrictions
  •     No explicit grammar defined
  •     Groovy can be coded with eclipse, with code completion, etc

References