/*
 * $Id: VKCRequestProcessor.java,v 1.14 2007/08/08 12:14:59 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 * 
 * Created on 08.07.2004
 *
 * $Log: VKCRequestProcessor.java,v $
 * Revision 1.14  2007/08/08 12:14:59  marbobo
 * + License-Funktionalität komplett umgeschrieben
 * + Bugfix bzgl. Beschreibungsfelder von Entitäten
 * + Bugfix mailing
 *
 * Revision 1.13  2006/11/06 11:10:07  korowa
 * "License akzeptieren" als Preloginaktion eingefügt
 *
 * Revision 1.12  2006/10/04 03:15:14  marbobo
 * + Vollständige Unterstützung für Templates implementiert
 * + Alles von Virtoweb auf ProCoBa umgestellt
 *
 * Revision 1.11  2005/09/01 08:32:00  korowa
 * Es werden mehrere URL angeboten, welche direkten Zugriff auf Dateien
 *  und automatisches Anmelden als Gast erlauben.
 *
 * Revision 1.10  2005/03/24 12:57:05  marbobo
 * + Unnötige Anweisungen entfernt
 *
 * Revision 1.9  2005/02/15 15:52:51  bigmac
 * ${template.name} wird jetzt auch bei nicht angemeldeten Usern
 * für ActionForward ersetzt
 *
 * Revision 1.8  2005/02/15 09:50:53  bigmac
 * processActionPerform() überschreibt keine Templatevariablen mehr
 *
 * Revision 1.7  2005/02/15 09:45:00  bigmac
 * processActionPerform() überschreibt keine Templatevariablen mehr
 *
 * Revision 1.6  2004/11/10 15:02:49  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.5  2004/10/28 19:41:58  marbobo
 * + Bugfix wegen Kontextpfad
 * + Anpassung wegen Loginseite
 *
 * Revision 1.4  2004/10/28 14:17:49  marbobo
 * + Kategorieparameter berücksichtigen
 *
 * Revision 1.3  2004/09/05 19:19:36  marbobo
 * + Einige Anpassungen damit wieder verschieden pre-Loginaktionen funktionieren
 *
 * Revision 1.2  2004/08/26 13:07:10  koppy
 * Weiterleitung zum Referer wieder entfernt
 *
 * Revision 1.1  2004/08/20 12:55:41  koppy
 * VKC spezifischer Request-Processor für Struts.
 * Wesentliche Aufgaben sind: Überprüfung, ob Benutzer eingeloggt,
 * Ersetzung von Variablen in ActionForward-Pfadangaben
 * durch benutzerspezifische Werte (z.B. template.name)
 *
 */
package vkc.servlets;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.RequestProcessor;

import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCUser;
import vkc.misc.VKCLogManager;
import vkc.util.ServletUtils;
import vkc.util.StringUtils;
import vkc.view.WebShare;
import vkc.view.form.SysLinkForm;

/**
 * This class represents a custom
 * request processor for struts.
 * 
 * @author Andreas Koop
 */
public class VKCRequestProcessor extends RequestProcessor {
    /** 
     * (non-Javadoc)
     * @see org.apache.struts.action.RequestProcessor#process(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    public void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        VKCUser user = ServletUtils.getUser(request);
        String servletPath = request.getServletPath().toLowerCase();
        
        if (user == null && servletPath.indexOf("login.do") == -1
                		 && servletPath.indexOf("loginchangepassword.do") == -1
                		 && servletPath.indexOf("showrecentnewsframeset.do") == -1
                		 && servletPath.indexOf("showrecentnews.do") == -1
                		 && servletPath.indexOf("forgotpassword.do") == -1
                		 && servletPath.indexOf("syslink.do") == -1
                		 && servletPath.indexOf("registernewuser.do") == -1 
        				 && servletPath.indexOf("loginlicense.do") == -1
                         && servletPath.indexOf("loginlicenseframeset.do") == -1 ) {
            ServletUtils.removeSessionAttributes(request.getSession());
    		
            if (request.getParameter("categoryId") == null) {
                VKCLogManager.infoLog(this, "Forwarding to " + WebShare.getLoginPage());
                response.sendRedirect(request.getContextPath() + WebShare.getLoginPage());
            } else {
                Integer categoryId = null;
                
                try {
                    categoryId = Integer.valueOf(request.getParameter("categoryId"));
                } catch (NumberFormatException e) {
                    categoryId = new Integer(VKCCategory.ROOT_CATEGORY_ID);
                }
                
                response.sendRedirect(request.getContextPath() + SysLinkForm.getCategorySysLink(categoryId, SysLinkForm.LOGINTYPE_NORMAL_USER));
            }

            return;
        }
        
        super.process(request, response);
    }
    
    /**
     * Replace user variables and do a forward to specified uri 
     * using request dispatcher.
     * This method is used by all internal method needing to do a forward.
     * @param uri Context-relative URI to forward to
     * @param request Current page request
     * @param response Current page response
     */
    protected void doForward(String uri, 
            				 HttpServletRequest request, 
            				 HttpServletResponse response) 
    throws IOException, ServletException {
        uri = replaceVars(uri, request, response);
        
        super.doForward(uri, request, response);
    }
    
    /** 
     * (non-Javadoc)
     * @see org.apache.struts.action.RequestProcessor#processActionPerform(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.apache.struts.action.Action, org.apache.struts.action.ActionForm, org.apache.struts.action.ActionMapping)
     */
    protected ActionForward processActionPerform(HttpServletRequest request,
            									 HttpServletResponse response, 
            									 Action action, 
            									 ActionForm form,
            									 ActionMapping mapping) 
    throws IOException, ServletException {
    	ActionForward forward = super.processActionPerform(request, response, action, form, mapping);

    	if (forward == null) {
        	return null;
        }

    	ActionForward realForward = new ActionForward();
        realForward.setContextRelative(forward.getContextRelative());
        realForward.setName(forward.getName());
        realForward.setPath(replaceVars(forward.getPath(), request, response));
        realForward.setRedirect(forward.getRedirect());

        return realForward;
    }
    
    /**
     * Replaces the ${userproperty}
     * @param input
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    private String replaceVars(String input, 
            				   HttpServletRequest request,
            				   HttpServletResponse response) 
    throws IOException {
        if (input.indexOf("${") < 0) {
            return input; // nothing to replace
        }
        
        VKCUser user = ServletUtils.getUser(request);
        
        if (user == null) {
        	input = StringUtils.replaceToken(input, "${template.name}", WebShare.DEFAULT_TEMPLATE);
            
        	return input;
        }
        
        StringBuffer newInput = new StringBuffer();
        
        Pattern p = Pattern.compile("\\$\\{(.)+\\}");
        Matcher m = p.matcher(input);
        
        try {
            while (m.find()) {
                String property = m.group();
                property = property.substring(2, property.length() - 1);

                m.appendReplacement(newInput, BeanUtils.getNestedProperty(user, property));
            }
        } catch (Exception e) {
            VKCLogManager.errorLog(this, "", e.getMessage(), e);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getLocalizedMessage());
            
            return input;
        }
        
        m.appendTail(newInput);
        
        return newInput.toString();
    }
}