Package railo.runtime.orm.hibernate

Source Code of railo.runtime.orm.hibernate.CFCInfo

package railo.runtime.orm.hibernate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.hibernate.EntityMode;
import org.hibernate.SessionFactory;
import org.hibernate.engine.query.QueryPlanCache;
import org.hibernate.event.EventListeners;
import org.hibernate.event.PostDeleteEventListener;
import org.hibernate.event.PostInsertEventListener;
import org.hibernate.event.PostLoadEventListener;
import org.hibernate.event.PostUpdateEventListener;
import org.hibernate.event.PreDeleteEventListener;
import org.hibernate.event.PreLoadEventListener;
import org.hibernate.tuple.entity.EntityTuplizerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import railo.commons.io.res.Resource;
import railo.loader.util.Util;
import railo.runtime.Component;
import railo.runtime.PageContext;
import railo.runtime.db.DataSource;
import railo.runtime.db.DataSourcePro;
import railo.runtime.db.DatasourceConnection;
import railo.runtime.exp.PageException;
import railo.runtime.listener.ApplicationContext;
import railo.runtime.listener.ApplicationContextPro;
import railo.runtime.op.Duplicator;
import railo.runtime.orm.ORMConfiguration;
import railo.runtime.orm.ORMEngine;
import railo.runtime.orm.ORMSession;
import railo.runtime.orm.ORMUtil;
import railo.runtime.orm.hibernate.event.AllEventListener;
import railo.runtime.orm.hibernate.event.EventListener;
import railo.runtime.orm.hibernate.event.InterceptorImpl;
import railo.runtime.orm.hibernate.event.PostDeleteEventListenerImpl;
import railo.runtime.orm.hibernate.event.PostInsertEventListenerImpl;
import railo.runtime.orm.hibernate.event.PostLoadEventListenerImpl;
import railo.runtime.orm.hibernate.event.PostUpdateEventListenerImpl;
import railo.runtime.orm.hibernate.event.PreDeleteEventListenerImpl;
import railo.runtime.orm.hibernate.event.PreInsertEventListenerImpl;
import railo.runtime.orm.hibernate.event.PreLoadEventListenerImpl;
import railo.runtime.orm.hibernate.event.PreUpdateEventListenerImpl;
import railo.runtime.orm.hibernate.tuplizer.AbstractEntityTuplizerImpl;
import railo.runtime.text.xml.XMLCaster;
import railo.runtime.type.Collection;
import railo.runtime.type.util.ArrayUtil;

public class HibernateORMEngine implements ORMEngine {
 
  private static final int INIT_NOTHING=1;
  private static final int INIT_CFCS=2;
  private static final int INIT_ALL=2;

  private Map<String,SessionFactoryData> factories=new ConcurrentHashMap<String, SessionFactoryData>();
 
  public HibernateORMEngine() {}

  @Override
  public void init(PageContext pc) throws PageException{
    getSessionFactory(pc,INIT_CFCS);
  }
   
  @Override
  public ORMSession createSession(PageContext pc) throws PageException {
    ApplicationContextPro appContext = (ApplicationContextPro) pc.getApplicationContext();
    Object o=appContext.getORMDataSource();
   
    DataSource ds=o instanceof DataSource?
        (DataSource)o:
        CommonUtil.getDataSource(pc,CommonUtil.toString(o));
   
       
    DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc,ds);
     
    try{
      SessionFactoryData data = getSessionFactoryData(pc, INIT_NOTHING);
      return new HibernateORMSession(data,dc);
    }
    catch(PageException pe){
      //manager.releaseConnection(pc, dc);// connection is closed when session ends
      throw pe;
    }
  }
 

  QueryPlanCache getQueryPlanCache(PageContext pc) throws PageException {
    return getSessionFactoryData(pc,INIT_NOTHING).getQueryPlanCache();
  }

  @Override
  public SessionFactory getSessionFactory(PageContext pc) throws PageException{
    return getSessionFactory(pc,INIT_NOTHING);
  }
 
  public boolean reload(PageContext pc, boolean force) throws PageException {
    if(force) {
      getSessionFactoryData(pc, INIT_ALL);
    }
    else {
      if(factories.containsKey(hash(pc)))return false;
    }
    getSessionFactoryData(pc, INIT_CFCS);
    return true;
  }

  private SessionFactory getSessionFactory(PageContext pc,int initType) throws PageException {
    return getSessionFactoryData(pc, initType).getFactory();
  }

  private SessionFactoryData getSessionFactoryData(PageContext pc,int initType) throws PageException {
    ApplicationContextPro appContext = (ApplicationContextPro) pc.getApplicationContext();
    if(!appContext.isORMEnabled())
      throw ExceptionUtil.createException((ORMSession)null,null,"ORM is not enabled","");
   
   
    // datasource
    DataSource ds = ORMUtil.getDataSource(pc);
    ORMConfiguration ormConf=appContext.getORMConfiguration();
    String key = hash(ormConf,ds);
    SessionFactoryData data = factories.get(key);
    if(initType==INIT_ALL && data!=null) {
      data.reset();
      data=null;
    }
    if(data==null) {
      data=new SessionFactoryData(this,ormConf,ds);
      factories.put(key, data);
    }
   
   
    // config
    try{
      //arr=null;
      if(initType!=INIT_NOTHING){
        synchronized (data) {
         
          if(ormConf.autogenmap()){
            data.tmpList=HibernateSessionFactory.loadComponents(pc, this, ormConf);
           
            data.cfcs.clear();
          }
          else
            throw ExceptionUtil.createException(data,null,"orm setting autogenmap=false is not supported yet",null);
       
          // load entities
          if(!ArrayUtil.isEmpty(data.tmpList)) {
            data.getNamingStrategy();// caled here to make sure, it is called in the right context the first one
            DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc, ds);
            try {
              Iterator<Component> it = data.tmpList.iterator();
              while(it.hasNext()){
                createMapping(pc,it.next(),dc,ormConf,data);
              }
            }
            finally {
              CommonUtil.releaseDatasourceConnection(pc, dc);
            }
            if(data.tmpList.size()!=data.cfcs.size()){
              Component cfc;
              String name,lcName;
              Map<String,String> names=new HashMap<String,String>();
              Iterator<Component> it = data.tmpList.iterator();
              while(it.hasNext()){
                cfc=it.next();
                name=HibernateCaster.getEntityName(cfc);
                lcName=name.toLowerCase();
                if(names.containsKey(lcName))
                  throw ExceptionUtil.createException(data,null,"Entity Name ["+name+"] is ambigous, ["+names.get(lcName)+"] and ["+cfc.getPageSource().getDisplayPath()+"] use the same entity name.","");
                names.put(lcName,cfc.getPageSource().getDisplayPath());
             
            }
          }
        }
      }
    }
    finally {
      data.tmpList=null;
    }
       
    // already initialized for this application context
    if(data.getConfiguration()!=null) return data;

    //MUST
    //cacheconfig
    //cacheprovider
    //...
   
    String mappings=HibernateSessionFactory.createMappings(ormConf,data);
   
    DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc,ds);
    try{
      data.setConfiguration(mappings,dc);
    }
    catch (Exception e) {
      throw CommonUtil.toPageException(e);
    }
    finally {
      CommonUtil.releaseDatasourceConnection(pc, dc);
    }
   
    addEventListeners(pc, data);
   
    EntityTuplizerFactory tuplizerFactory = data.getConfiguration().getEntityTuplizerFactory();
    //tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, CFCEntityTuplizer.class);
    //tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, MapEntityTuplizer.class);
    tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, AbstractEntityTuplizerImpl.class);
    tuplizerFactory.registerDefaultTuplizerClass(EntityMode.POJO, AbstractEntityTuplizerImpl.class);
    //tuplizerFactory.registerDefaultTuplizerClass(EntityMode.POJO, AbstractEntityTuplizerImpl.class);
   
    //configuration.setEntityResolver(new CFCEntityResolver());
    //configuration.setEntityNotFoundDelegate(new EntityNotFoundDelegate());
   
   
   
    data.buildSessionFactory();
    return data;
  }
 
  private static void addEventListeners(PageContext pc, SessionFactoryData data) throws PageException {
    if(!data.getORMConfiguration().eventHandling()) return;
    String eventHandler = data.getORMConfiguration().eventHandler();
    AllEventListener listener=null;
    if(!Util.isEmpty(eventHandler,true)){
      //try {
        Component c = pc.loadComponent(eventHandler.trim());
       
        listener = new AllEventListener(c);
            //config.setInterceptor(listener);
      //}catch (PageException e) {e.printStackTrace();}
    }
    data.getConfiguration().setInterceptor(new InterceptorImpl(listener));
        EventListeners listeners = data.getConfiguration().getEventListeners();
       
        // post delete
    List<EventListener>
    list=merge(listener,data.cfcs,CommonUtil.POST_DELETE);
    listeners.setPostDeleteEventListeners(list.toArray(new PostDeleteEventListener[list.size()]));
   
        // post insert
    list=merge(listener,data.cfcs,CommonUtil.POST_INSERT);
    listeners.setPostInsertEventListeners(list.toArray(new PostInsertEventListener[list.size()]));
   
    // post update
    list=merge(listener,data.cfcs,CommonUtil.POST_UPDATE);
    listeners.setPostUpdateEventListeners(list.toArray(new PostUpdateEventListener[list.size()]));
   
    // post load
    list=merge(listener,data.cfcs,CommonUtil.POST_LOAD);
    listeners.setPostLoadEventListeners(list.toArray(new PostLoadEventListener[list.size()]));
   
    // pre delete
    list=merge(listener,data.cfcs,CommonUtil.PRE_DELETE);
    listeners.setPreDeleteEventListeners(list.toArray(new PreDeleteEventListener[list.size()]));
   
    // pre insert
    //list=merge(listener,cfcs,CommonUtil.PRE_INSERT);
    //listeners.setPreInsertEventListeners(list.toArray(new PreInsertEventListener[list.size()]));
   
    // pre load
    list=merge(listener,data.cfcs,CommonUtil.PRE_LOAD);
    listeners.setPreLoadEventListeners(list.toArray(new PreLoadEventListener[list.size()]));
   
    // pre update
    //list=merge(listener,cfcs,CommonUtil.PRE_UPDATE);
    //listeners.setPreUpdateEventListeners(list.toArray(new PreUpdateEventListener[list.size()]));
  }

  private static List<EventListener> merge(EventListener listener, Map<String, CFCInfo> cfcs, Collection.Key eventType) {
    List<EventListener> list=new ArrayList<EventListener>();
     
   
    Iterator<Entry<String, CFCInfo>> it = cfcs.entrySet().iterator();
    Entry<String, CFCInfo> entry;
    Component cfc;
    while(it.hasNext()){
      entry = it.next();
      cfc = entry.getValue().getCFC();
      if(EventListener.hasEventType(cfc,eventType)) {
        if(CommonUtil.POST_DELETE.equals(eventType))
          list.add(new PostDeleteEventListenerImpl(cfc));
        if(CommonUtil.POST_INSERT.equals(eventType))
          list.add(new PostInsertEventListenerImpl(cfc));
        if(CommonUtil.POST_LOAD.equals(eventType))
          list.add(new PostLoadEventListenerImpl(cfc));
        if(CommonUtil.POST_UPDATE.equals(eventType))
          list.add(new PostUpdateEventListenerImpl(cfc));
       
        if(CommonUtil.PRE_DELETE.equals(eventType))
          list.add(new PreDeleteEventListenerImpl(cfc));
        if(CommonUtil.PRE_INSERT.equals(eventType))
          list.add(new PreInsertEventListenerImpl(cfc));
        if(CommonUtil.PRE_LOAD.equals(eventType))
          list.add(new PreLoadEventListenerImpl(cfc));
        if(CommonUtil.PRE_UPDATE.equals(eventType))
          list.add(new PreUpdateEventListenerImpl(cfc));
      }
    }
   
    // general listener
    if(listener!=null && EventListener.hasEventType(listener.getCFC(),eventType))
      list.add(listener);
   
    return list;
  }

  private static Object hash(PageContext pc) throws PageException {
    ApplicationContextPro appContext=(ApplicationContextPro) pc.getApplicationContext();
    Object o=appContext.getORMDataSource();
    DataSource ds;
    if(o instanceof DataSource) ds=(DataSource) o;
    else ds=CommonUtil.getDataSource(pc,CommonUtil.toString(o));
    return hash(appContext.getORMConfiguration(),ds);
  }
 
  private static String hash(ORMConfiguration ormConf,DataSource ds) {
    if(ds instanceof DataSourcePro)
      return ((DataSourcePro)ds).id()+":"+ormConf.hash();
    return ds.getClazz()+":"+ds.getDsnTranslated()+":"+ormConf.hash();
  }

  public void createMapping(PageContext pc,Component cfc, DatasourceConnection dc, ORMConfiguration ormConf,SessionFactoryData data) throws PageException {
    String id=HibernateUtil.id(HibernateCaster.getEntityName(cfc));
    CFCInfo info=data.cfcs.get(id);
    //Long modified=cfcs.get(id);
    String xml;
    long cfcCompTime = HibernateUtil.getCompileTime(pc,cfc.getPageSource());
    if(info==null || (ORMUtil.equals(info.getCFC(),cfc) ))  {//&& info.getModified()!=cfcCompTime
      StringBuilder sb=new StringBuilder();
     
      long xmlLastMod = loadMapping(sb,ormConf, cfc);
      Element root;
      // create maaping
      if(true || xmlLastMod< cfcCompTime) {//MUSTMUST
        data.reset();
        Document doc=null;
        try {
          doc=CommonUtil.newDocument();
        }catch(Throwable t){t.printStackTrace();}
       
        root=doc.createElement("hibernate-mapping");
        doc.appendChild(root);
        pc.addPageSource(cfc.getPageSource(), true);
        try{
          HBMCreator.createXMLMapping(pc,dc,cfc,root,data);
        }
        finally{
          pc.removeLastPageSource(true);
        }
        xml=XMLCaster.toString(root.getChildNodes(),true,true);
        saveMapping(ormConf,cfc,root);
      }
      // load
      else {
        xml=sb.toString();
        root=CommonUtil.toXML(xml).getOwnerDocument().getDocumentElement();
        /*print.o("1+++++++++++++++++++++++++++++++++++++++++");
        print.o(xml);
        print.o("2+++++++++++++++++++++++++++++++++++++++++");
        print.o(root);
        print.o("3+++++++++++++++++++++++++++++++++++++++++");*/
       
      }
      data.cfcs.put(id, new CFCInfo(HibernateUtil.getCompileTime(pc,cfc.getPageSource()),xml,cfc));
    }
   
  }

  private static void saveMapping(ORMConfiguration ormConf, Component cfc, Element hm) {
    if(ormConf.saveMapping()){
      Resource res=cfc.getPageSource().getResource();
      if(res!=null){
        res=res.getParentResource().getRealResource(res.getName()+".hbm.xml");
        try{
        CommonUtil.write(res,
            XMLCaster.toString(hm,false,true,
                HibernateSessionFactory.HIBERNATE_3_PUBLIC_ID,
                HibernateSessionFactory.HIBERNATE_3_SYSTEM_ID,
                HibernateSessionFactory.HIBERNATE_3_CHARSET.name()), HibernateSessionFactory.HIBERNATE_3_CHARSET, false);
        }
        catch(Exception e){}
      }
    }
  }
 
  private static long loadMapping(StringBuilder sb,ORMConfiguration ormConf, Component cfc) {
   
    Resource res=cfc.getPageSource().getResource();
    if(res!=null){
      res=res.getParentResource().getRealResource(res.getName()+".hbm.xml");
      try{
        sb.append(CommonUtil.toString(res, CommonUtil.UTF8));
        return res.lastModified();
      }
      catch(Exception e){}
    }
    return 0;
  }

  @Override
  public int getMode() {
    //MUST impl
    return MODE_LAZY;
  }

  @Override
  public String getLabel() {
    return "Hibernate";
  }

 
 
 

  @Override
  public ORMConfiguration getConfiguration(PageContext pc) {
    ApplicationContext ac = pc.getApplicationContext();
    if(!ac.isORMEnabled())
      return null;
    return  ac.getORMConfiguration();
  }

  /**
   * @param pc
   * @param session
   * @param entityName name of the entity to get
   * @param unique create a unique version that can be manipulated
   * @param init call the nit method of the cfc or not
   * @return
   * @throws PageException
   */
  public Component create(PageContext pc, HibernateORMSession session,String entityName, boolean unique) throws PageException {
    SessionFactoryData data = session.getSessionFactoryData();
    // get existing entity
    Component cfc = _create(pc,entityName,unique,data);
    if(cfc!=null)return cfc;
   
    // reinit ORMEngine
    SessionFactory _old= getSessionFactory(pc,INIT_NOTHING);//_factory;
    SessionFactory _new = getSessionFactory(pc,INIT_CFCS);
    if(_old!=_new){
      session.resetSession(_new);
      cfc = _create(pc,entityName,unique,data);
      if(cfc!=null)return cfc;
    }
   
   
   
    ORMConfiguration ormConf = pc.getApplicationContext().getORMConfiguration();
    Resource[] locations = ormConf.getCfcLocations();
   
    throw ExceptionUtil.createException(data,null,
        "No entity (persitent component) with name ["+entityName+"] found, available entities are ["+CommonUtil.toList(data.getEntityNames(), ", ")+"] ",
        "component are searched in the following directories ["+toString(locations)+"]");
   
  }
 
 
  private String toString(Resource[] locations) {
    if(locations==null) return "";
    StringBuilder sb=new StringBuilder();
    for(int i=0;i<locations.length;i++){
      if(i>0) sb.append(", ");
      sb.append(locations[i].getAbsolutePath());
    }
    return sb.toString();
  }

  private static Component _create(PageContext pc, String entityName, boolean unique, SessionFactoryData data) throws PageException {
    CFCInfo info = data.cfcs.get(HibernateUtil.id(entityName));
    if(info!=null) {
      Component cfc = info.getCFC();
      if(unique){
        cfc=(Component)Duplicator.duplicate(cfc,false);
        if(cfc.contains(pc,CommonUtil.INIT))cfc.call(pc, "init",new Object[]{});
      }
      return cfc;
    }
    return null;
  }
}
class CFCInfo {
  private String xml;
  private long modified;
  private Component cfc;
 
  public CFCInfo(long modified, String xml, Component cfc) {
    this.modified=modified;
    this.xml=xml;
    this.cfc=cfc;
  }
  /**
   * @return the cfc
   */
  public Component getCFC() {
    return cfc;
  }
  /**
   * @return the xml
   */
  public String getXML() {
    return xml;
  }
  /**
   * @return the modified
   */
  public long getModified() {
    return modified;
  }
 
}
TOP

Related Classes of railo.runtime.orm.hibernate.CFCInfo

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.