Thursday, May 26, 2011

The dynamic stylesheet language

Hi,

Recently i was searching for compacting heavy css for my website in less css with dynamic css code, i came across lesscss.org, it's a fabulous website which provides dynamic integration of css.

"LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions. LESS runs on both the client-side (IE 6+, Webkit, Firefox) and server-side, with Node.js."

http://lesscss.org/

Cheers,

Ujjwal Soni

Wednesday, May 11, 2011

Redirect all 404's to index page in php

This given PHP example redirect to index page if there is 404 error in your site.



Create the file app/app_error.php with the following code.

Code Example:


class AppError extends ErrorHandler {
    function error404($params) {
        // redirect to homepage
        $this->controller->redirect('/');
    }
}

 


Friday, April 29, 2011

Oracle SSO configuration with Alfresco

Hi,

I finally configured Oracle SSO with Alfresco. Below is how i achieved that.

I need to run Alfresco on tomcat deployed on other virtual terminal, i created a class file as under

-> STEP 1

package my.custom;

import java.io.IOException; 
import java.util.List;
import java.util.Locale;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.AbstractAuthenticationFilter;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.LanguagesConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.config.ConfigService;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.alfresco.web.bean.repository.Repository;



public class OSSOAuthenticationFilter extends AbstractAuthenticationFilter implements Filter {
private static final String LOCALE = "locale";
public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";
private static Log logger = LogFactory.getLog(OSSOAuthenticationFilter.class);
private ServletContext context;
private String loginPage;
private AuthenticationComponent authComponent;
private AuthenticationService authService;
private TransactionService transactionService;
private PersonService personService;
private NodeService nodeService;
private List m_languages;

public OSSOAuthenticationFilter() {
super();
}

public void destroy() {
// Nothing to do
}

/**
* Run the filter
*
* @param sreq
* ServletRequest
* @param sresp
* ServletResponse
* @param chain
* FilterChain
* @exception IOException
* @exception ServletException
*/
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain) throws IOException, ServletException {
// Get the HTTP request/response/session
HttpServletRequest req = (HttpServletRequest) sreq;
HttpServletResponse resp = (HttpServletResponse) sresp;
HttpSession httpSess = req.getSession(true);

String userName = null;
//Get headers setted by the oracle sigle sign one server
java.util.Enumeration reqMap = req.getHeaders("Osso-User-Dn");

if (reqMap == null) {
logger.error("No user logged in");
} else {
while (reqMap.hasMoreElements()){
//Get from the full dn the username
userName = ((String)reqMap.nextElement()).split(",")[0].trim().toString().split("=")[1].trim().toString();
//String tmp = value.split(",")[0].trim().toString();
//userName = tmp.split("=")[1].trim().toString();
}
}

if (logger.isDebugEnabled()) {
logger.debug("OSSO : User = " + userName);
}

// See if there is a user in the session and test if it matches
User user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);

if (user != null) {
try {
// Debug
if (logger.isDebugEnabled())
logger.debug("OSSO : User " + user.getUserName() + " validate ticket");

if (user.getUserName().equals(userName)) {
UserTransaction tx1 = transactionService.getUserTransaction();
try {
tx1.begin();
authComponent.setCurrentUser(user.getUserName());
tx1.commit();
}catch(Exception ex){
logger.error("Failed due to transaction " + ex);
try {
tx1.rollback();
} catch (Exception ex2) {
logger.error("Failed to rollback transaction", ex2);
}

}
I18NUtil.setLocale(Application.getLanguage(httpSess));
chain.doFilter(sreq, sresp);
return;
} else {
// No match
//setAuthenticatedUser(req, httpSess, userName);
//below url is th oracle portal url
resp.sendRedirect("http://hostname:7778/alfresco");
return;
}
} catch (AuthenticationException ex) {
if (logger.isErrorEnabled())
logger.error("Failed to validate user " + user.getUserName(), ex);
}
}

setAuthenticatedUser(req, httpSess, userName);

// Redirect the login page as it is never seen as we always login by name
if (req.getRequestURI().endsWith(getLoginPage()) == true)
{
if (logger.isDebugEnabled())
logger.debug("Login page requested, chaining ...");

resp.sendRedirect(req.getContextPath() + "/faces/jsp/browse/browse.jsp");
return;
}
else
{
//below url is th oracle portal url
resp.sendRedirect("http://hostname:7778/alfresco");
//chain.doFilter(sreq, sresp);
return;
}

}

/**
* Set the authenticated user.
*
* It does not check that the user exists at the moment.
*
* @param req
* @param httpSess
* @param userName
*/
private void setAuthenticatedUser(HttpServletRequest req, HttpSession httpSess, String userName) {
if (userName != null){
UserTransaction tx1 = transactionService.getUserTransaction();
// Set the authentication
try {
tx1.begin();
authComponent.setCurrentUser(userName);
tx1.commit();
} catch (Throwable ex) {
logger.error(ex);
try {
tx1.rollback();
} catch (Exception ex2) {
logger.error("Failed to rollback transaction", ex2);
}
}

// Set up the user information
UserTransaction tx = transactionService.getUserTransaction();
NodeRef homeSpaceRef = null;
User user;
try {
tx.begin();
user = new User(userName, authService.getCurrentTicket(), personService.getPerson(userName));
homeSpaceRef = (NodeRef) nodeService.getProperty(personService.getPerson(userName), ContentModel.PROP_HOMEFOLDER);
if(homeSpaceRef == null) {
logger.warn("Home Folder is null for user '"+userName+"', using company_home.");
homeSpaceRef = (NodeRef) nodeService.getRootNode(Repository.getStoreRef());
}
user.setHomeSpaceId(homeSpaceRef.getId());
tx.commit();
} catch (Throwable ex) {
logger.error(ex);

try {
tx.rollback();
} catch (Exception ex2) {
logger.error("Failed to rollback transaction", ex2);
}

if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
} else {
throw new RuntimeException("Failed to set authenticated user", ex);
}
}

// Store the user
httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);

// Set the current locale from the Accept-Lanaguage header if available
Locale userLocale = parseAcceptLanguageHeader(req, m_languages);

if (userLocale != null) {
httpSess.setAttribute(LOCALE, userLocale);
httpSess.removeAttribute(MESSAGE_BUNDLE);
}

// Set the locale using the session
I18NUtil.setLocale(Application.getLanguage(httpSess));
}
}

public void init(FilterConfig config) throws ServletException {
this.context = config.getServletContext();
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
transactionService = serviceRegistry.getTransactionService();
nodeService = serviceRegistry.getNodeService();

authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
authService = (AuthenticationService) ctx.getBean("authenticationService");
personService = (PersonService) ctx.getBean("personService");

// Get a list of the available locales
ConfigService configServiceService = (ConfigService) ctx.getBean("webClientConfigService");
LanguagesConfigElement configElement = (LanguagesConfigElement) configServiceService.getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);

m_languages = configElement.getLanguages();
}

/**
* Return the login page address
*
* @return String
*/
private String getLoginPage() {
if (loginPage == null) {
loginPage = Application.getLoginPage(context);
}

return loginPage;
}
}



-> STEP 2 Place this class file under
C:\Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\my\custom

-> STEP 3 Now you need to configure proxy pass in oc4j's httpd.conf file


$ORACLE_HOME/Apache/Apache/conf/httpd.conf, add the following entries:                                                                                    ProxyPass /alfresco/ http://host:8080/alfresco/

ProxyPass /alfresco http://host:8080/alfresco/


ProxyPassReverse /alfresco/ http://host:8080/alfresco/

ProxyPassReverse /alfresco http://host:8080/alfresco/


-> STEP 4 Now you need to enable sso on oracle portal

edit $ORACLE_HOME/Apache/Apache/conf/mod_osso.conf, add the following lines just before the :

require valid-user
AuthType Basic


require valid-user
AuthType Basic


Please restart apache after you have made this configuration

-> STEP 5 If alfresco is already running then stop and start alfresco service from start menu under start -> alfresco -> stop alfreco virtual server

Thats it, now oracle sso is configured successfully for Alfreco

Try opening http://oc4jserverhost/alfresco, it will redirect to oracle portal sso login page, enter credentials, it will then redirect you to alfresco home page on successful login.

LOGOUT Link

Coming towards logout functionality, i need to make some changes to use oracle portal logout instead of alfresco built in logout.

You need to edit file C:\Alfresco\tomcat\webapps\alfresco\jsp\parts\titlebar.jsp


search for
a:actionLink


now replace that line with
a:actionLink id="logout" image="/images/icons/logout.gif" value="#{msg.logout} (#{NavigationBean.currentUser.userName})" rendered="#{!NavigationBean.isGuest}" href="http://hostname/pls/orasso/orasso.wwsso_app_admin.ls_logout?p_done_url=http%3A%2F%2Fhostname%2Falfresco" immediate="true"


Thats it, now logout functionality is integrated with oracle sso.

Any issues implementing this, feel free to contact me..

Cheers,

Ujjwal Soni

Tuesday, April 26, 2011

A nice book on smaller, faster, better way to build software

Last week, my friend sent me a link which contains great amount of information for building, testing and all other phases for software development.

Check out this link :: http://gettingreal.37signals.com/toc.php

Cheers,

Ujjwal Soni

Tuesday, March 15, 2011

Jquery Autocomplete with DataSource

Hi All,

Recently i needed an autocomplete textbox in which i need to store an ID and display a list. So, i gone for Jquery autocomplete which i was very used to. I have used this before but it was just for single list where i was not storing any ID. I tried my hands on with JSON using Jquery autocomplete but it was not giving me results the way i wanted.

So, finally, i found a solution as mentioned below ::

1) A textbox for autocomplete


<input type="text" id="input" name="input"/>


2) An onload script


function loadData(){
$("#input").autocomplete('<%=request.getContextPath()%>/showMyCity.do' , {
        extraParams: { locationName : function() { 
        return document.getElementById('input').value; 
            }
         },
        minChars: 0,
        width: 185,
        matchContains: "word",
        autoFill: false,
        max:50,
        formatItem:function(row) {
            return row[0];
        },
        formatResult: function(row) {
            return row[0];
        }
    });
    
    
    $("#input").result(function(event, data, formatted) {
        if (data)
            document.getElementById("selectedLocation").value=data[1];
            
            
    });

}



3) Jsp page which results your search :


<c:forEach items="${LOCATION_LIST}" var="bean">

<c:out value="${bean.description}"/>|<c:out value="${bean.code}"/>
</c:forEach>




With a pipe character added in between, you can hide/show text on autocomplete.

This resoved my issue and i need not  have to use JSON for that.

Cheers,

Ujjwal Soni

UBS



Monday, March 14, 2011

URL rewriting for multi country website like /countryname/cityname


Hello Everyone,


Recently, i had to develop a website which needed a different URL mapping, it needed a url mapping like /France/Paris (ie: country/city).I looked out for many options, first of all i tried it with url rewriting servlet and implemented a filter with it, but it was not exactly the thing i wanted. So i looked out for other options and finally i found UrlRewriteFilter from tuckey.


I downloaded the jars from www.tuckey.org/urlrewrite and configured that in web.xml file.


I found its configuration too easy, you need to configure that in web.xml under filter tag.
<filter>
     <filter-name>UrlRewriteFilter</filter-name>
     <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
  </filter>
 
  <filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


Secondly, there is a seperate xml file called urlrewrite.xml that is needed by this filter.

You need to configure url rewriting rules in there. You can also use expression language to define a rule for your URL type.


So, i did someting like this to achieve my goal.

 <rule>
     <from>^/([a-z\s-] )$</from>
         <to type="redirect">%{context-path}/redirectAction.do?country=$1</to>
    </rule>
   
    <rule>
     <from>^/([a-z\s-] )/$</from>
         <to type="redirect">%{context-path}/redirectAction.do?country=$1</to>
    </rule>
   
    <rule>
     <from>^/([a-z/\s/-] )/([a-z/\s/-] )$</from>
         <to type="redirect">%{context-path}/redirectAction.do?country=$1&amp;city=$2</to>
    </rule>
      
    <rule>
     <from>^/([a-z/\s/-] )/([a-z/\s/-] )/$</from>
         <to type="redirect">%{context-path}/redirectAction.do?country=$1&amp;city=$2</to>
    </rule>


The above configuration helped me to accept multi spaced url's like www.ujjwalbsoni.blogspot.com/United States Of America/New York



I created an action in struts that gets me the names of countries and cities accordingly and i finally got what i wanted.


Expression for redirect rule was really tedious since i was having multiple spaces in country/city names. But finally, i created and succeeded in making one and using that.




Cheers!!!


Ujjwal Soni


UBS


Thursday, March 3, 2011

A great new java framework playframework

Hi,




Today, my friend told me about a new emerging java framework, its known as Play Framework.

Its new and really awesome...Its not a game framework, but its like an MVC framework, a bit simpler one.

Check out this link http://www.playframework.org/documentation/1.1.1/5things

Cheers!!!

Ujjwal Soni