Package com.googlecode.s2hibernate.struts2.plugin.interceptors

Source Code of com.googlecode.s2hibernate.struts2.plugin.interceptors.HibernateSessionTransactionInfo

package com.googlecode.s2hibernate.struts2.plugin.interceptors;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.hibernate.LazyInitializationException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.exception.JDBCConnectionException;

import com.googlecode.s2hibernate.lang.SessionInjectionException;
import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;
import com.googlecode.s2hibernate.struts2.plugin.util.Constants;
import com.googlecode.s2hibernate.struts2.plugin.util.HibernatePluginUtils;
import com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory;
import com.googlecode.s2hibernate.struts2.plugin.util.SessionInfo;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.inject.Inject;


/**
* Interceptor for Hibernate Session and Transaction Injection
*
* <br/><br/>
*
* Interceptor para inje��o da Sess�o Hibernate e da Transa��o
*
* @author Jose Yoshiriro - jyoshiriro@gmail.com
*
*/

public class SessionTransactionInjectorInterceptor extends GenericInterceptor implements ServletRequestAware{

  /**
   *
   */
  private static final long serialVersionUID = 2222692750520221708L;

  private String sessionTarget;
     
  private String transactionTarget;
 
  private String customSessionFactoryClass;
 
  private String getSessionMethod;
 
  private String staticGetSessionMethod = "true";
 
  private String closeSessionAfterInvoke = "true";

  private String configurationFiles = HibernateSessionFactory.DEFAULT_HIBERATE_CONFIGFILE;

  private String closeSessionMethod;

  private boolean useSessionObjectInCloseMethod = true;

  private String sourceSessionFactory = null;

  private static Set<String> excludedPackages;
 
  private boolean searchInsideJars = false;

  private HttpServletRequest request;
 
  private static Set<Class> actionsWithoutInjection = new HashSet<Class>();
 
  static {
    excludedPackages = new LinkedHashSet<String>();
    excludedPackages.add("org.apache.");
    excludedPackages.add("org.hibernate.");
    excludedPackages.add("com.opensymphony.");
    excludedPackages.add("org.springframework.");
    excludedPackages.add("org.jboss.");
    excludedPackages.add("java.");
    excludedPackages.add("javax.");
    excludedPackages.add("sun.");
    excludedPackages.add("com.sun.");
    excludedPackages.add("javassist.");
  }
 
  private static void markMappgingNoInjection(Class actionClass) {
    actionsWithoutInjection.add(actionClass);
    log.debug("Action "+actionClass.getName()+" makerd as permanent for no Session/Transaction Injection into Injection Cache");
  }
 
  private static boolean isNotMappedAction(Class actionClass) {
    boolean notmapped = actionsWithoutInjection.contains(actionClass);
    if (notmapped) {
      log.debug("Action "+actionClass.getName()+" has no candidate object for Session/Transaction Injection according the Injection Cache");
    }
    return notmapped;
  }
 
  @Override
  public String intercept(ActionInvocation invocation) throws Exception {
   
    readedObjectsByRequest.put(ServletActionContext.getRequest(),new HashSet());
   
    HibernateSessionFactory.finishUnitOfWork();
   
    Object action = invocation.getAction();

    String namespaceName = invocation.getProxy().getNamespace();
    String actionName = invocation.getProxy().getActionName();
    String methodName = invocation.getProxy().getMethod();
    StringBuilder sbMapping = new StringBuilder(namespaceName);
    if (!namespaceName.equals("/"))
      sbMapping.append("/");
    sbMapping.append(actionName);
    sbMapping.append(" - Method: ");
    sbMapping.append(action.getClass().getName());
    sbMapping.append(".");
    sbMapping.append(methodName);
    sbMapping.append("()");
   
    if (action.getClass().equals(ActionSupport.class)) {
      log.warn("Action class \""+action.getClass().getName()+
          "\" from mapping \""+namespaceName+actionName+"\" does not extends \""+
          ActionSupport.class.getName()+"\". " +
          "Hibernate Session and Transaction will not be injected!");
      return invocation.invoke();
    }
   
    Set<Session> injectedSessions = new LinkedHashSet<Session>();
   
    StringBuilder sbErrorMessage = new StringBuilder("Error! Please, check your JDBC/JDNI Configurations and Database Server avaliability. \n ");
    sbErrorMessage.append("at "+sbMapping.toString()+"\n ");
   
    if (!isNotMappedAction(action.getClass())) {
   
      log.debug("Preparing Injection Hibernate Session and Transaction process: "+sbMapping.toString());
     
      List<Field> fields = getFieldsFromAction(invocation.getAction());
     
     
      boolean sessionNotInjected = false;
     
      try {
        if (sessionTarget!=null && (!sessionTarget.equals(""))) {
          injectedSessions = injectHibernateSessionByConfiguration(fields, invocation);
        }
       
        int countOfInjectedSessionsByConfiguration = injectedSessions.size();
       
        injectHibernateCoreSessionByAnnotation(action, injectedSessions);
        int countOfInjectedSessionsByAnnotation = injectedSessions.size();
       
        sessionNotInjected = (countOfInjectedSessionsByAnnotation==countOfInjectedSessionsByConfiguration);
       
        if (sessionNotInjected) {
          log.debug("No target setted for Hibernate Session object at "+sbMapping.toString()+". Use the *"+Constants.HIBERNATEPLUGIN_SESSIONTARGET+"* property or the SessionTarget Annotation. " +
              "If any annotated Session object be found, will be closed after the request.");
          markMappgingNoInjection(action.getClass());
        }
       
      } catch (Exception e) {
        sbErrorMessage.append("Could not open or inject a Hibernate Session in ValueStack: ");
        sbErrorMessage.append(e.getMessage());
        String message = sbErrorMessage.toString();
        System.err.println(message);
        e.printStackTrace();
        throw new SessionInjectionException(message);
      }
     
      if (!sessionNotInjected) {
        try {
          if (transactionTarget!=null && (!transactionTarget.equals(""))) {
            injectHibernateTransactionByConfiguration(fields, injectedSessions, invocation);
          }
          injectHibernateTransactionByAnnotation(action, injectedSessions.iterator().next(), false);
          for (Session hibernateSession:injectedSessions) {
            Transaction hibernateTransation = hibernateSession.getTransaction();
            if (!hibernateTransation.isActive())
              hibernateTransation.begin();
          }
        } catch (Exception e) {
          sbErrorMessage.append("Could not open or put a Hibernate Transaction in ValueStack: ");
          sbErrorMessage.append(e.getMessage());
          String message = sbErrorMessage.toString();
          System.err.println(message);
          e.printStackTrace();
          throw new TransactionException(message);
        }
      }
   
    }
   
    String returnName = "";
    try {
//      ServletActionContext.getRequest().setAttribute("ss", injectedSessions.iterator().next().hashCode());
      returnName = invocation.invoke();
     
      for (Session hibernateSession:injectedSessions) {
        Transaction hibernateTransation = hibernateSession.getTransaction();
       
        try {
          commitHibernateTransaction(hibernateTransation);
          closeHibernateSession(hibernateSession);
          log.debug("Hibernate Transaction Committed");
        }
        catch (Exception e) {
          hibernateSession.clear();
          sbErrorMessage.append("Could not commit the Hibernate Transaction: ");
          sbErrorMessage.append(e.getMessage());
          String message = sbErrorMessage.toString();
          System.err.println(message);
          closeHibernateSession(hibernateSession);
          detectAndCloseHibernateCoreSessionCreatedLater(action);
          e.printStackTrace();
          throw new SessionInjectionException(message);
        }
   
      }

      detectAndCommitHibernateTransactionCreatedLater(action);
      detectAndCloseHibernateCoreSessionCreatedLater(action);
     
      log.debug("Injection Hibernate Session and Transaction process for "+sbMapping.toString()+" finished");
     
     
    } catch (Exception e) {
      if ((e instanceof JDBCConnectionException) || ( (e.getCause()!=null) && (e.getCause() instanceof JDBCConnectionException) ) ) {
        if ( (customSessionFactoryClass==null) || (customSessionFactoryClass.equals("plugin")) ) {
          if (HibernateSessionFactory.isAutoRebuidOnJdbcConnectionError()) {
            log.debug("Full Hibernate Plugin's Session Factory marked for auto rebuild on JDBCConnectionException");
            HibernateSessionFactory.rebuildSessionFactory();
          }
        }
      }
      detectAndRollbackHibernateTransactionCreatedLater(action);
      detectAndCloseHibernateCoreSessionCreatedLater(action);
      throw e;
    }
    return returnName ;
   
  }

  private void commitHibernateTransaction(Transaction hibernateTransation) {
    if (hibernateTransation==null)
      return;
   
    if ( (hibernateTransation.isActive()) && (!hibernateTransation.wasCommitted()) && (!hibernateTransation.wasRolledBack())) {
      hibernateTransation.commit();
      log.debug("Hibernate Transation  "+hibernateTransation+" rolledback by Full Hibernate Plugin");
    }
  }

  private void closeHibernateSession(Session hibernateSession) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    if ( (hibernateSession==null) || (!hibernateSession.isOpen()) )
      return;
    if (isCloseSessionAfterInvoke()) {
      // If using the Plugin's Session Factory
      if ( (customSessionFactoryClass==null) || (customSessionFactoryClass.equalsIgnoreCase("plugin")) ) {
        HibernateSessionFactory.closeSession(hibernateSession);
        log.debug("Hibernate Session closed by Full Hibernate Plugin's Hibernate Session Factory");
      }
      else {
        // Using a custom Session Factory Class
        Object sessionFactory = null;
        sessionFactory = Class.forName(customSessionFactoryClass, false, this.getClass().getClassLoader());
        if (useSessionObjectInCloseMethod) {
          Method method = Class.forName(customSessionFactoryClass).getDeclaredMethod(closeSessionMethod, hibernateSession.getClass());
          method.invoke(sessionFactory, hibernateSession);
        }
        else {
          Method method = Class.forName(customSessionFactoryClass).getDeclaredMethod(closeSessionMethod, null);
          method.invoke(sessionFactory, null);
        }
        log.debug("Hibernate Session closed by custom Hibernate Session Factory ("+sessionFactory.getClass().getName()+")");
      }
    } else {
      //TODO: verificar se o Hibernate Manager est� Habilitado antes de por as sess�es no contexto de aplica��o para economizar mem�ria!
      Set<SessionInfo> hibernateSessions = (Set<SessionInfo>) ActionContext.getContext().getApplication().get("struts2HibernatePlugin_Sessions");
      if (hibernateSessions==null)
        hibernateSessions = new LinkedHashSet<SessionInfo>();
      SessionInfo info = new SessionInfo(hibernateSession,new Date(),request.getSession());
      hibernateSessions.add(info);
      ActionContext.getContext().getApplication().put("struts2HibernatePlugin_Sessions", hibernateSessions);
    }   
  }

  private Set<Session> injectHibernateSessionByConfiguration(List<Field> fields, ActionInvocation invocation) throws Exception {
    Set<Session> sessions = new LinkedHashSet<Session>();
    for (Field field:fields) {
      String[] sessionTargets = sessionTarget.split(",");
      String[] sessionFactoryTargets = sourceSessionFactory.split(",");
      for (int i=0;i<sessionTargets.length;i++) {
        String sessionTarget = sessionTargets[i];
        String trueTarget = "";
        Session hibernateSession = null;
        String[] targetAsArray = sessionTarget.replace(".", ",").split(",");
       
        if (!Pattern.matches(HibernatePluginUtils.wildcardToRegex(targetAsArray[0]), field.getName()))
          continue;
       
        targetAsArray[0] = field.getName();
        trueTarget = Arrays.toString(targetAsArray).replace("[", "").replace("]", "").replace(", ",".");
       
        if (hibernateSession==null) {
          String sourceSessionFactory = sessionFactoryTargets[i];
          hibernateSession = getHibernateSessionFromFactory(sourceSessionFactory);
        }
        invocation.getStack().setValue(trueTarget, hibernateSession, true);
        sessions.add(hibernateSession);
        log.debug("Hibernate Session injected (by configuration) into Action. Field \""+trueTarget+"\"");       
      }
    }
    return sessions;
  }

  /**
   * Transactions injected using the same order of the Session objects
   * @param fields
   * @param sessions
   * @param invocation
   * @return
   * @throws Exception
   */
  private Set<HibernateSessionTransactionInfo> injectHibernateTransactionByConfiguration(List<Field> fields,
      Set<Session> sessions, ActionInvocation invocation) throws Exception {
   
    Set<HibernateSessionTransactionInfo> infos = new LinkedHashSet<HibernateSessionTransactionInfo>();
    for (Field field:fields) {     
      String trueTarget = "";
      Transaction transaction = null;
      String[] transactionTargets = transactionTarget.split(",");
      for (String transactionTarget : transactionTargets) {
      String[] targetAsArray = transactionTarget.replace(".", ",").split(",");
     
      if (!Pattern.matches(HibernatePluginUtils.wildcardToRegex(targetAsArray[0]), field.getName()))
        continue;
     
      targetAsArray[0] = field.getName();
      trueTarget = Arrays.toString(targetAsArray).replace("[", "").replace("]", "").replace(", ",".");
     
      for (Session session:sessions) {
        transaction = session.beginTransaction();
      }
     
      invocation.getStack().setValue(trueTarget, transaction);
      HibernateSessionTransactionInfo transactionInfo = new HibernateSessionTransactionInfo();
      transactionInfo.setTransactionObject(transaction);
      transactionInfo.setTransactionTarget(trueTarget);
      infos.add(transactionInfo);
      log.debug("Hibernate Transaction injected (by configuration) into Action. Field \""+trueTarget+"\"");
      }
    }
   
    return infos;
  }
 
  private Session getHibernateSessionFromFactory(String sessionFactoryName) throws Exception {
    Session hibernateSession = null;
    // Using the PLUGIN Session Factory Class
    if ( (customSessionFactoryClass==null) || (customSessionFactoryClass.equalsIgnoreCase("plugin")) ) {
      if (!HibernateSessionFactory.hasSessionFactories()) {
        HibernateSessionFactory.setConfigFiles(configurationFiles);
      }
      hibernateSession  = HibernateSessionFactory.getSession(sessionFactoryName);
      log.debug("Hibernate Session from Full Hibernate Plugin's Hibernate Session Factory");
    }
    else {
    // Using a custom Session Factory Class
      Object sessionFactory = null;
      if (isStaticGetSessionMethod())
        sessionFactory = Class.forName(customSessionFactoryClass, false, this.getClass().getClassLoader());
      else
        sessionFactory = Class.forName(customSessionFactoryClass).newInstance();       
      Method method = Class.forName(customSessionFactoryClass).getDeclaredMethod(getSessionMethod, null);
      hibernateSession = (Session) method.invoke(sessionFactory, null);
      log.debug("Hibernate Session from custom Hibernate Session Factory ("+sessionFactory.getClass().getName()+")");
    }
    return hibernateSession;
  }
 
 
  /**
   * Tests if the class is not a class from JDK or commons Libraries like Hibernate, XWork, Apache Commons, JBoss and Spring<br/>
   * Enums, annotations never are "candidate classes"<br/>
   * if <b>hibernatePlugin.searchMappingsInsideJars</b> property is "true", class inside *jar* files will be searched. 
   * @param testClass
   * @return
   */
  private boolean isCandidadeClass(Class testClass) {
    if (!searchInsideJars) {
      if ( (testClass.getResource("")==null) || (testClass.getResource("").getProtocol().equals("jar")) ) {
        return false;
      }
    }
    if (testClass.isEnum())
      return false;
    if (testClass.isAnnotation())
      return false;
    if ( (testClass==null) || (testClass.getPackage()==null) || (testClass.equals(Object.class)) )
      return false;

    String testPackage = testClass.getPackage().getName();
    for (String excludedPackage : excludedPackages) {
      if (testPackage.startsWith(excludedPackage))
        return false;
    }
    return true;
  }

  /**
   * Inject the current Hibernate Session object into annotated fields.
   * @param targetObject the target object where the {@link @SessionTarget} will be searched
   * @param sessions Set of Hibernate Sessions to be used
   * @throws Exception
   */
  private void injectHibernateCoreSessionByAnnotation(Object targetObject,
      Set<Session> sessions) throws Exception {
    Class testClass = targetObject.getClass();
    Class actionClass = ActionContext.getContext().getActionInvocation().getAction().getClass();
    while (isCandidadeClass(testClass)) {
      Field[] campos = testClass.getDeclaredFields();
     
      for (Field campo : campos) {
        if (campo.isEnumConstant())
          continue;
        // test for "singletons"
        campo.setAccessible(true);
        Object fieldValue = campo.get(targetObject);
       
        if ( (fieldValue!=null) && (campo.get(targetObject).equals(targetObject)) )
          continue;

        isCandidateToInjectionCache(actionClass,campo.getName());
       
        if (campo.getType().getName().equals(Session.class.getName())) {
         
          if (campo.isAnnotationPresent(SessionTarget.class)) {
            String sessionFactoryName = campo.getAnnotation(SessionTarget.class).value();
            Session hibernateSession = getHibernateSessionFromFactory(sessionFactoryName);
            String setterName = getSetterName(campo.getName());
            try {
              Method setterMethod = targetObject.getClass().getDeclaredMethod(setterName, Session.class);
              setterMethod.invoke(targetObject, hibernateSession);
            } catch (Exception e) {
              campo.set(targetObject, hibernateSession);
            }
            debugInfoSessionInjectedByAnnotation(campo,testClass);
//            System.out.println(campo.getName()+" "+campo.getDeclaringClass());
            sessions.add(hibernateSession);
          }
        } else {
          campo.setAccessible(true);
          Object subField = campo.get(targetObject);
          if ( (subField!=null) && (isCandidadeClass(campo.getType()) ))
            injectHibernateCoreSessionByAnnotation(subField, sessions);
        }
      }
     
      testClass = testClass.getSuperclass();
    }

  }
 
  /**
   * For future cache implementation
   */
  private static HashMap<Class, Set<String>> cacheInjectionMap = new HashMap<Class, Set<String>>();

  /**
   * Not implemented
   * @param actionClass
   * @param name
   */
  private void isCandidateToInjectionCache(Class actionClass, String name) {
    /*ValueStack valueStack = ActionContext.getContext().getValueStack();
   
    // tenta obter o Set de valores de valuestack da action
    Set<String> candidates = cacheInjectionMap.get(actionClass);
    if (candidates==null)
      candidates = new HashSet<String>();

    // procura pela chave de valuestack possivel
    if (valueStack.findValue(name)!=null)
      candidates.add(name);
    for (String candidate : candidates) {
      if (valueStack.findValue(candidate+"."+name)!=null)
        candidates.add(name);
    }
    cacheInjectionMap.put(actionClass, candidates);*/
  }

  private void debugInfoSessionInjectedByAnnotation(Field campo, Class testClass) {
    log.debug("Hibernate Session injected (by annotation) into Action. Field \""+campo.getName()+"\". Class \""+testClass.getName()+"\"");
  }

    /**
   * Returns <b>true</b> if was found at least 1 annotated target for the Transaction in the ValueStack. Returns <b>false</b> instead.
   * @param targetObject
   * @param defaultSession - Default Hibernate Session Object for the annotated transaction object (if no value used in the @TransactionTarget)
     * @param hibernateTransaction
   * @param foundTarget
   * @return
   * @throws SecurityException
   * @throws NoSuchMethodException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws InvocationTargetException
   * @throws ClassNotFoundException
     * @throws NoSuchFieldException
   */
  private boolean injectHibernateTransactionByAnnotation(Object targetObject,
      Session defaultSession, boolean foundTarget) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, NoSuchFieldException {
    Class testClass = targetObject.getClass();
    while (isCandidadeClass(testClass)) {
      Field[] campos = testClass.getDeclaredFields();
     
      for (Field campo : campos) {
        if (campo.isEnumConstant())
          continue;
        // test for "singletons"
        campo.setAccessible(true);
        Object fieldValue = campo.get(targetObject);
       
        if ( (fieldValue!=null) && (campo.get(targetObject).equals(targetObject)) )
          continue;
       
        if (campo.getType().getName().equals(Transaction.class.getName())) {
          if (campo.isAnnotationPresent(TransactionTarget.class)) {
           
            String sessionName = campo.getAnnotation(TransactionTarget.class).value();
            Transaction hibernateTransaction = null;
            if ((sessionName==null) || (sessionName.equals("")) ) {
              hibernateTransaction = defaultSession.getTransaction();
            } else {
              Session sessionObject = null;
              try {
                String sessionGetterName = getGetterName(sessionName);
                Method sessionGetterMethod = targetObject.getClass().getDeclaredMethod(sessionGetterName, Session.class);
                sessionObject =  (Session) sessionGetterMethod.invoke(targetObject);
              } catch (NoSuchMethodException e) {
                Field sessionField = targetObject.getClass().getDeclaredField(sessionName);
                sessionField.setAccessible(true);
                sessionObject = (Session) sessionField.get(targetObject);
              }
              hibernateTransaction = sessionObject.getTransaction();

            }
           
            String setterName = getSetterName(campo.getName());
            try {
              Method setterMethod = targetObject.getClass().getDeclaredMethod(setterName, Transaction.class);
              setterMethod.invoke(targetObject, hibernateTransaction);
              foundTarget = true;
              debugInfoTransactionInjectedByAnnotation(campo, testClass);
            } catch (NoSuchMethodException e) {
              campo.setAccessible(true);
              campo.set(targetObject, hibernateTransaction);
              foundTarget = true;
              debugInfoTransactionInjectedByAnnotation(campo, testClass);
            }
            if (!hibernateTransaction.isActive())
              hibernateTransaction.begin();
          }
        } else {
          campo.setAccessible(true);
          Object subField = campo.get(targetObject);
          if (subField!=null) {
            if (isCandidadeClass(campo.getType())) {
              if (injectHibernateTransactionByAnnotation(subField, defaultSession, foundTarget))
                foundTarget = true;
           
          }
        }
      }
     
      testClass = testClass.getSuperclass();
    }

    return foundTarget;
  }
 

  private void debugInfoTransactionInjectedByAnnotation(Field campo, Class testClass) {
    log.debug("Hibernate Transaction injected (by annotation) into Action. Field \""+campo.getName()+"\". Class \""+testClass.getName()+"\"");
  }
 

  private synchronized void detectAndCloseHibernateCoreSessionCreatedLater(Object targetObject) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
   
    if (readedObjectsByRequest.get(ServletActionContext.getRequest()).contains(targetObject))
      return;
    readedObjectsByRequest.get(ServletActionContext.getRequest()).add(targetObject);
   
    Class testClass = targetObject.getClass();
    while (isCandidadeClass(testClass)) {
      Field[] campos = testClass.getDeclaredFields();
     
      for (Field campo : campos) {
       
        if (campo.isEnumConstant())
          continue;
       
        // test for "singletons"
        campo.setAccessible(true);
        Object fieldValue = campo.get(targetObject);
       
        if ((fieldValue==null) || !isCandidadeClass(fieldValue.getClass()))
          continue;
       
        try {
          if ((campo.get(targetObject).equals(targetObject)) )
            continue;
        } catch (LazyInitializationException e) {
          e.printStackTrace();
          continue;
        }
       
        if (campo.getType().getName().equals(Session.class.getName())) {
          if (campo.isAnnotationPresent(SessionTarget.class)) {
            campo.setAccessible(true);
            Session hibernateSession = (Session) campo.get(targetObject);
            closeHibernateSession(hibernateSession);
          }
        } else {
          campo.setAccessible(true);
          Object subField = campo.get(targetObject);
          if (subField!=null) {
            detectAndCloseHibernateCoreSessionCreatedLater(subField);
          }
        }
      }
     
      testClass = testClass.getSuperclass();
    }
  }
 
  private synchronized void detectAndCommitHibernateTransactionCreatedLater(Object targetObject) throws Exception {
    try {
      if (readedObjectsByRequest.get(ServletActionContext.getRequest()).contains(targetObject))
        return;
      readedObjectsByRequest.get(ServletActionContext.getRequest()).add(targetObject);
      Class testClass = targetObject.getClass();
      while (isCandidadeClass(testClass)) {
        Field[] campos = testClass.getDeclaredFields();
       
        for (Field campo : campos) {
         
          if (campo.isEnumConstant())
            continue;
         
          // test for "singletons"
          campo.setAccessible(true);
          Object fieldValue = campo.get(targetObject);
         
          if ((fieldValue==null) || !isCandidadeClass(fieldValue.getClass()))
            continue;
         
          try {
            if ( (fieldValue!=null) && (campo.get(targetObject).equals(targetObject)) )
              continue;
          } catch (LazyInitializationException e) {
            e.printStackTrace();
            continue;
          }
         
          if (campo.getType().getName().equals(Session.class.getName())) {
            if (campo.isAnnotationPresent(TransactionTarget.class)) {
              campo.setAccessible(true);
              Transaction hibernateTransaction = (Transaction) campo.get(targetObject);
              commitHibernateTransaction(hibernateTransaction);
            }
          } else {
            campo.setAccessible(true);
            Object subField = campo.get(targetObject);
            if (subField!=null) {
              detectAndCommitHibernateTransactionCreatedLater(subField);
            }
          }
        }
       
        testClass = testClass.getSuperclass();
      }
    } catch (LazyInitializationException e) {
      e.printStackTrace();
      return;
    }
      catch (Exception e) {
      e.printStackTrace();
      throw e;
    }
  }
 
  private static Map<HttpServletRequest, Set> readedObjectsByRequest = new HashMap<HttpServletRequest, Set>();
 
  private synchronized void detectAndRollbackHibernateTransactionCreatedLater(Object targetObject) throws Exception {
    try {
      if (readedObjectsByRequest.get(ServletActionContext.getRequest()).contains(targetObject))
        return;
      readedObjectsByRequest.get(ServletActionContext.getRequest()).add(targetObject);
     
      Class testClass = targetObject.getClass();
      while (isCandidadeClass(testClass)) {
        Field[] campos = testClass.getDeclaredFields();
       
        for (Field campo : campos) {
         
          if (campo.isEnumConstant())
            continue;
         
          // test for "singletons"
          campo.setAccessible(true);
          Object fieldValue = campo.get(targetObject);
         
          if ((fieldValue==null) || !isCandidadeClass(fieldValue.getClass()))
            continue;
         
          try {
            if ( (fieldValue!=null) && (campo.get(targetObject).equals(targetObject)) )
              continue;
          } catch (LazyInitializationException e) {
            e.printStackTrace();
            continue;
          }
         
          if (campo.getType().getName().equals(Session.class.getName())) {
            if (campo.isAnnotationPresent(TransactionTarget.class)) {
              campo.setAccessible(true);
              Transaction hibernateTransaction = (Transaction) campo.get(targetObject);
              rollbackHibernateTransaction(hibernateTransaction);
            }
          } else {
            campo.setAccessible(true);
            Object subField = campo.get(targetObject);
            if (subField!=null) {
              detectAndRollbackHibernateTransactionCreatedLater(subField);
            }
          }
        }
        testClass = testClass.getSuperclass();
      }
    }catch (Exception e) {
      e.printStackTrace();
      throw e;
    }
  }

  private void rollbackHibernateTransaction(Transaction hibernateTransaction) {
    if (hibernateTransaction==null)
      return;

    if ((hibernateTransaction.isActive()) && (!hibernateTransaction.wasRolledBack()) && (!hibernateTransaction.wasCommitted())) {
      hibernateTransaction.rollback();
      log.debug("Hibernate Transaction "+hibernateTransaction+" rolledback");
    }
  }

  private String getSetterName(String name) {
    String firstUpper = name.substring(0,1).toUpperCase();
    String secondOn = name.substring(1,name.length());
    String setterName = "set"+firstUpper+secondOn;
    return setterName;
  }
 
  private String getGetterName(String name) {
    String firstUpper = name.substring(0,1).toUpperCase();
    String secondOn = name.substring(1,name.length());
    String setterName = "get"+firstUpper+secondOn;
    return setterName;
  }

  public static List<Field> getFieldsFromAction(Object action) {
    List<Field> fields = new ArrayList<Field>();
    Class clazz = action.getClass();
    do {
      Field[] fieldsArray = clazz.getDeclaredFields();
      CollectionUtils.addAll(fields, fieldsArray);
      clazz=clazz.getSuperclass();
    } while (!clazz.equals(Object.class));
    return fields;
  }

  public String getSessionTarget() {
    return sessionTarget;
  }

  @Inject(value=Constants.HIBERNATEPLUGIN_SESSIONTARGET, required=false)
  public void setSessionTarget(String sessionTarget) {
    this.sessionTarget = sessionTarget;
  }

  public String getCustomSessionFactoryClass() {
    return customSessionFactoryClass;
  }
 
  @Inject(value=Constants.HIBERNATEPLUGIN_CUSTOMSESSIONFACTORYCLASS, required=false)
  public void setCustomSessionFactoryClass(String customSessionFactoryClass) {
    this.customSessionFactoryClass = customSessionFactoryClass;
  }

  public String getGetSessionMethod() {
    return getSessionMethod;
  }

  @Inject(value=Constants.HIBERNATEPLUGIN_GETSESSIONMETHOD, required=false)
  public void setGetSessionMethod(String getSessionMethod) {
    this.getSessionMethod = getSessionMethod;
  }

  public String getCloseSessionAfterInvoke() {
    return closeSessionAfterInvoke;
  }
 
  public Boolean isCloseSessionAfterInvoke() {
    Boolean resultado = new Boolean(closeSessionAfterInvoke);
    return resultado;
  }

  @Inject(value=Constants.HIBERNATEPLUGIN_CLOSESESSIONAFTERINVOKE,required=false)
  public void setCloseSessionAfterInvoke(String closeSessionAfterInvoke) {
    this.closeSessionAfterInvoke = closeSessionAfterInvoke;
  }

  public String getStaticGetSessionMethod() {
    return staticGetSessionMethod;
  }
 
  public Boolean isStaticGetSessionMethod() {
    Boolean resultado = new Boolean(staticGetSessionMethod);
    return resultado;
  }

  @Inject(value=Constants.HIBERNATEPLUGIN_STATICGETSESSIONMETHOD,required=false)
  public void setStaticGetSessionMethod(String staticGetSessionMethod) {
    this.staticGetSessionMethod = staticGetSessionMethod;
  }
 
 
  public String[] getConfigurationFiles() {
    if (configurationFiles==null)
      configurationFiles="";
    return configurationFiles.split(",");
  }
 
  @Inject(value=Constants.HIBERNATEPLUGIN_CONFIGURATIONFILES, required=false)
  public void setConfigurationFiles(String configurationFiles) {
    this.configurationFiles = configurationFiles;
  }

  @Inject(value=Constants.HIBERNATEPLUGIN_TRANSACTIONTARGET, required=false)
  public void setTransactionTarget(String transactionTarget) {
    this.transactionTarget = transactionTarget;
  }
 
  @Inject(value=Constants.HIBERNATEPLUGIN_CLOSESESSIONMETHOD, required=false)
  public void setCloseSessionMethod(String closeSessionMethod) {
    this.closeSessionMethod = closeSessionMethod;
  }

  @Inject(value=Constants.HIBERNATEPLUGIN_USESESSIONOBJECTINCLOSESESSIONMETHOD, required=false)
  public void setUseSessionObjectInCloseMethod(
      boolean useSessionObjectInCloseMethod) {
    this.useSessionObjectInCloseMethod = useSessionObjectInCloseMethod;
  }
 

  @Inject(value=Constants.HIBERNATEPLUGIN_SOURCESESSIONFACTORY, required=false)
  public void setSourceSessionFactory(String sourceSessionFactory) {
    this.sourceSessionFactory = sourceSessionFactory;
  }
 
  @Inject(value=Constants.HIBERNATEPLUGIN_AUTOREBUILD, required=false)
  public void setAutoRebuidOnJdbcConnectionError(
      String autoRebuidOnJdbcConnectionError) {
    HibernateSessionFactory.setAutoRebuidOnJdbcConnectionError(new Boolean(autoRebuidOnJdbcConnectionError));
  }

  public boolean isSearchInsideJars() {
    return searchInsideJars;
  }

  @Inject(value=Constants.HIBERNATEPLUGIN_SEARCHMAPPINGINSIDEJARS, required=false)
  public void setSearchInsideJars(boolean searchInsideJars) {
    this.searchInsideJars = searchInsideJars;
  }

  public void setServletRequest(HttpServletRequest request) {
    this.request = request;
   
  }

}



class HibernateSessionTransactionInfo {
  Session sessionObject;
  String sessionTarget;

  Transaction transactionObject;
  String transactionTarget;
 
  String sessionFactoryName;

  public Session getSessionObject() {
    return sessionObject;
  }
  public void setSessionObject(Session sessionObject) {
    this.sessionObject = sessionObject;
  }
  public String getSessionTarget() {
    return sessionTarget;
  }
  public void setSessionTarget(String sessionTarget) {
    this.sessionTarget = sessionTarget;
  }
  public Transaction getTransactionObject() {
    return transactionObject;
  }
  public void setTransactionObject(Transaction transactionObject) {
    this.transactionObject = transactionObject;
  }
  public String getTransactionTarget() {
    return transactionTarget;
  }
  public void setTransactionTarget(String transactionTarget) {
    this.transactionTarget = transactionTarget;
  }
  public String getSessionFactoryName() {
    return sessionFactoryName;
  }
  public void setSessionFactoryName(String sessionFactoryName) {
    this.sessionFactoryName = sessionFactoryName;
  }
 
  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof HibernateSessionTransactionInfo))
      return false;
    HibernateSessionTransactionInfo info = (HibernateSessionTransactionInfo) obj;
    boolean isEqual = (
        ((sessionObject!=null) && (sessionObject.equals(info.getSessionObject())) ) ||
        ((transactionObject!=null) && ((transactionObject.equals(info.getTransactionObject()))) )
        );
    return isEqual;
  }
 
  @Override
  public int hashCode() {
    int hc = 0;
    if (sessionObject!=null)
      hc+=sessionObject.hashCode();
    if (transactionObject!=null)
      hc+=transactionObject.hashCode();
    return hc;
  }
 
  @Override
  public String toString() {
    StringBuffer sb = new StringBuffer("");
    if (sessionObject!=null) {
      sb.append("Session: ");
      sb.append(sessionObject.hashCode());
      sb.append(" - ");
      sb.append(sessionObject);
    }
    if (transactionObject!=null) {
      sb.append("\n\nTransaction: ");
      sb.append(transactionObject.hashCode());
      sb.append(" - ");
      sb.append(transactionObject);
    }
    return sb.toString();
  }
}
TOP

Related Classes of com.googlecode.s2hibernate.struts2.plugin.interceptors.HibernateSessionTransactionInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.