/** Overrides the default behaviour to including binding of Grails domain classes. */
  @Override
  protected void secondPassCompile() throws MappingException {
    final Thread currentThread = Thread.currentThread();
    final ClassLoader originalContextLoader = currentThread.getContextClassLoader();
    if (!configLocked) {
      if (LOG.isDebugEnabled())
        LOG.debug(
            "[GrailsAnnotationConfiguration] ["
                + domainClasses.size()
                + "] Grails domain classes to bind to persistence runtime");

      // do Grails class configuration
      configureDomainBinder(binder, grailsApplication, domainClasses);

      for (GrailsDomainClass domainClass : domainClasses) {

        final String fullClassName = domainClass.getFullName();

        String hibernateConfig = fullClassName.replace('.', '/') + ".hbm.xml";
        final ClassLoader loader = originalContextLoader;
        // don't configure Hibernate mapped classes
        if (loader.getResource(hibernateConfig) != null) continue;

        final Mappings mappings = super.createMappings();
        if (!GrailsHibernateUtil.usesDatasource(domainClass, dataSourceName)) {
          continue;
        }

        LOG.debug(
            "[GrailsAnnotationConfiguration] Binding persistent class [" + fullClassName + "]");

        Mapping m = binder.getMapping(domainClass);
        mappings.setAutoImport(m == null || m.getAutoImport());
        binder.bindClass(domainClass, mappings, sessionFactoryBeanName);
      }
    }

    try {
      currentThread.setContextClassLoader(grailsApplication.getClassLoader());
      super.secondPassCompile();
      createSubclassForeignKeys();
    } finally {
      currentThread.setContextClassLoader(originalContextLoader);
    }

    configLocked = true;
  }
  /**
   * Checks availability of a classpath resource.
   *
   * @param name Resource name.
   * @return {@code true} if resource is available and ready for read, {@code false} otherwise.
   */
  private boolean resourceAvailable(String name) {
    InputStream cfgStream =
        Thread.currentThread().getContextClassLoader().getResourceAsStream(name);

    if (cfgStream == null) {
      log.error("Classpath resource not found: " + name);

      return false;
    }

    try {
      // Read a single byte to force actual content access by JVM.
      cfgStream.read();

      return true;
    } catch (IOException e) {
      log.error("Failed to read classpath resource: " + name, e);

      return false;
    } finally {
      U.close(cfgStream, log);
    }
  }
  @Override
  public SessionFactory buildSessionFactory() throws HibernateException {

    // set the class loader to load Groovy classes
    if (grailsApplication != null) {
      LOG.debug(
          "[GrailsAnnotationConfiguration] Setting context class loader to Grails GroovyClassLoader");
      Thread.currentThread().setContextClassLoader(grailsApplication.getClassLoader());
    }

    // work around for HHH-2624
    Map<String, Type> empty = new HashMap<String, Type>();
    addFilterDefinition(new FilterDefinition("dynamicFilterEnabler", "1=1", empty));

    SessionFactory sessionFactory = null;

    ClassLoader appClassLoader =
        (ClassLoader) getProperties().get(AvailableSettings.APP_CLASSLOADER);
    Thread currentThread = Thread.currentThread();
    ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
    boolean overrideClassLoader =
        (appClassLoader != null && !appClassLoader.equals(threadContextClassLoader));
    if (overrideClassLoader) {
      currentThread.setContextClassLoader(appClassLoader);
    }

    try {
      ConfigurationHelper.resolvePlaceHolders(getProperties());

      EventListenerIntegrator eventListenerIntegrator =
          new EventListenerIntegrator(hibernateEventListeners, eventListeners);
      BootstrapServiceRegistry bootstrapServiceRegistry =
          new BootstrapServiceRegistryBuilder().with(eventListenerIntegrator).build();

      setSessionFactoryObserver(
          new SessionFactoryObserver() {
            private static final long serialVersionUID = 1;

            public void sessionFactoryCreated(SessionFactory factory) {}

            public void sessionFactoryClosed(SessionFactory factory) {
              ((ServiceRegistryImplementor) serviceRegistry).destroy();
            }
          });

      StandardServiceRegistryBuilder standardServiceRegistryBuilder =
          new StandardServiceRegistryBuilder(bootstrapServiceRegistry)
              .applySettings(getProperties());
      sessionFactory = super.buildSessionFactory(standardServiceRegistryBuilder.build());
      serviceRegistry = ((SessionFactoryImplementor) sessionFactory).getServiceRegistry();
    } finally {
      if (overrideClassLoader) {
        currentThread.setContextClassLoader(threadContextClassLoader);
      }
    }

    if (grailsApplication != null) {
      GrailsHibernateUtil.configureHibernateDomainClasses(
          sessionFactory, sessionFactoryBeanName, grailsApplication);
    }

    return sessionFactory;
  }