Thursday, 29 September 2011

Java-XML - Reverse the order of child elements

The below sample program will tell you how to reverse the order of child elements.


private void reverseChildElements() {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  Document doc = null;
  try {
  DocumentBuilder builder = factory.newDocumentBuilder();
        //Parse the input xml file
doc = builder.parse("src/xml/input_reverse.xml");
Node firstChild = doc.getFirstChild();
        // Get the child nodes which we want to reverse
NodeList childNodes = firstChild.getChildNodes();
Stack<Node> nodeStack = new Stack<Node>();
        // Put all the nodes into a Stack
for(int i = 0; i < childNodes.getLength(); i++) {
nodeStack.push(childNodes.item(i));
}
        // Remove the nodes and add the one which we get from pop().
        //This is the last one which we entered
while(!nodeStack.empty()) {
firstChild.appendChild(firstChild.removeChild(nodeStack.pop()));
}
doc.replaceChild(firstChild, doc.getFirstChild());
outputXml(doc, "output_reverse_elements.xml");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

Wednesday, 28 September 2011

Acegi security for LDAP autentication


In this blob we will discuss how to use acegi security for LDAP authentication. I'm using maven for building the project and JSF as the MVC framework. Acegi can be used for other tools and framework also, e.g. ant/struts.
Acegi Security is now Spring Security, the official security project of the Spring Portfolio. If you are planning a new project, we'd recommend you consider using Spring Security. Acegi Security 1.0.7 will be the last non-critical release of the 1.0.x series.

pom.xml: Define the dependency in the pom.xml for acegi security.

<dependency>
    <groupId>org.acegisecurity</groupId>
    <artifactId>acegi-security</artifactId>
    <version>1.0.5</version>
</dependency>

I'm using the 1.0.5 version for the acegisecurity.


Spring context file: We need to define the spring context file for Acegi security. The mandatory things that needs to be there in this file are given below. This should be loaded in the classpath. For maven if you put it in 'src/main/resources' it's fine.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
        <property name="filterInvocationDefinitionSource">
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /a4j*/**=#NONE#
                /logon.jsf=httpSessionContextIntegrationFilter,authenticationProcessingFilter
                /logout.jsf=httpSessionContextIntegrationFilter,logoutFilter
                /secure/roleerror.jsf=#NONE#
                /secure/**=httpSessionContextIntegrationFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor
            </value>
        </property>
    </bean> 
 
    <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
        <property name="context">
            <value>org.acegisecurity.context.SecurityContextImpl</value>
        </property>
    </bean>

    <bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />
 
 
    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
            <ref local="authenticationProcessingFilterEntryPoint" />
        </property>
     
        <property name="accessDeniedHandler">
            <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
                <property name="errorPage" value="/secure/roleerror.jsf" />
            </bean>
        </property>
    </bean>

    <bean id="authenticationProcessingFilterEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
        <property name="loginFormUrl">
            <value>/logon.jsf</value>
        </property>

        <property name="forceHttps">
            <value>false</value>
        </property>
    </bean>
 
 
    <bean id="authenticationProcessingFilter" class="org.hhnt.common.gui.filter.AuthenticationProcessingFilter">
        <property name="authenticationManager">
            <ref bean="authenticationManager" />
        </property>

        <property name="authenticationFailureUrl">
            <value>/</value>
        </property>
     
        <property name="defaultTargetUrl">
            <value>/not_used</value>
        </property>
     
        <property name="filterProcessesUrl">
            <value>/logon.jsf</value>
        </property>
     
        <property name="formUsernameKey">
            <value>logonform:username</value>
        </property>
     
        <property name="formPasswordKey">
            <value>logonform:password</value>
        </property>
    </bean>
 
    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref local="ldapAuthProvider" />
            </list>
        </property>
    </bean>
 
    <bean id="initialDirContextFactory" class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
        <constructor-arg value="ldap://${ldap.connection.host}:${ldap.connection.port}/"/>
        <property name="managerDn"><value>${ldap.connection.dn}</value></property>
        <property name="managerPassword"><value>${ldap.connection.password}</value></property>
        <property name="extraEnvVars">
            <map>
                <entry key="java.naming.referral" value="follow"/>
            </map>
        </property>
    </bean>
 
    <bean id="userSearch" class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
        <constructor-arg index="0">
            <value>${ldap.base}</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>(sAMAccountName={0})</value>
        </constructor-arg>
        <constructor-arg index="2">
            <ref local="initialDirContextFactory"/>
        </constructor-arg>
        <property name="searchSubtree">
            <value>true</value>
        </property>
    </bean>

    <bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
        <constructor-arg>
            <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
                <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
                <property name="userSearch"><ref bean="userSearch"/></property>
            </bean>
        </constructor-arg>
        <constructor-arg>
            <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
                <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
                <constructor-arg><value>${ldap.application.dn}</value></constructor-arg>
                <property name="groupRoleAttribute"><value>cn</value></property>
            </bean>
        </constructor-arg>
    </bean>

 
    <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
        <property name="authenticationManager">
            <ref bean="authenticationManager" />
        </property>
     
        <property name="accessDecisionManager">
            <ref local="httpRequestAccessDecisionManager" />
        </property>
     
        <property name="objectDefinitionSource">
            <value>
                PATTERN_TYPE_APACHE_ANT
             
                /secure/newStudy.jsf=ROLE_AU                        
             
            </value>
        </property>
    </bean>
 
    <bean id="httpRequestAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
        <property name="allowIfAllAbstainDecisions">
            <value>false</value>
        </property>
     
        <property name="decisionVoters">
            <list>
                <bean class="org.acegisecurity.vote.RoleVoter" />
            </list>
        </property>
    </bean> 
 
    <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
        <property name="filterProcessesUrl">
            <value>/logout.jsf</value>
        </property>
        <constructor-arg value="/logon.jsf" />
        <!-- URL redirected to after logout -->
        <constructor-arg>
            <list>
                <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
            </list>
        </constructor-arg>
    </bean>
</beans>

web.xml: In the web.xml file we need to define these filter mapping.

<filter>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
    <init-param>
        <param-name>targetClass</param-name>
        <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
    </init-param>
</filter>
   
<filter-mapping>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <url-pattern>*.jsf</url-pattern>
</filter-mapping>

Make sure that the id of the input field in the logon page matches with the one defined in the spring context file. In this case it's 'username' and 'password'

Use ant to do runtime deployment for the changes


In this blog we will discuss how to deploy your static(views/css) changes at runtime. If you make some changes in your views(html, xhtml, jsp) or in cascading style sheet(css), you don't need to restart your app server to deploy these changes. You can use Ant to deploy the changes at runtime. I'm using Tomcat as the webserver and Eclipse as the IDE.

Define this xml file.

<project basedir="." default="deployView" name="Deploy">  
   
    <target name="deployView">
        <copy todir="${basedir}/target/${application_context}"   includeemptydirs="false">
            <fileset dir="${basedir}/src/main/webapp" >
                <include name="**/*.xhtml"/>
                <include name="**/*.css"/>  
            </fileset>
        </copy>  
    </target>  
</project>

In Eclipse go to Windows->Show View->Ant.
In the Ant window right click and select 'Add Buildfiles...'. Select the above xml file. You will see 'Deploy' -> 'deployView'.
Whenever you want to deploy the changes in your views just double click on this.