001 /*
002 * Databinder: a simple bridge from Wicket to Hibernate
003 * Copyright (C) 2006 Nathan Hamblen nathan@technically.us
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either
008 * version 2.1 of the License, or (at your option) any later version.
009 *
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public
016 * License along with this library; if not, write to the Free Software
017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
018 */
019
020 package net.databinder.hib;
021
022 import java.util.HashMap;
023
024 import net.databinder.DataApplicationBase;
025 import net.databinder.components.hib.DataBrowser;
026
027 import org.apache.wicket.Application;
028 import org.apache.wicket.Request;
029 import org.apache.wicket.RequestCycle;
030 import org.apache.wicket.Response;
031 import org.apache.wicket.WicketRuntimeException;
032 import org.apache.wicket.protocol.http.WebRequest;
033 import org.hibernate.SessionFactory;
034 import org.hibernate.cfg.AnnotationConfiguration;
035
036 /**
037 * Optional Databinder base Application class for configuration and session management.
038 * Supports multiple session factories with key objects.
039 * @author Nathan Hamblen
040 */
041 public abstract class DataApplication extends DataApplicationBase implements HibernateApplication {
042
043 /** App-wide session factories */
044 private HashMap<Object, SessionFactory> hibernateSessionFactories = new HashMap<Object, SessionFactory>();
045
046
047 /**
048 * Initializes a default Hibernate session factory and mounts a page for
049 * the data browser. This is called automatically during start-up. Applications
050 * with one session factory will not normally need to override this method;
051 * see related methods to override specific tasks.
052 * @see #buildHibernateSessionFactory(Object) aoe
053 * @see #mountDataBrowser()
054 */
055 protected void dataInit() {
056 buildHibernateSessionFactory(null);
057 if (isDataBrowserAllowed())
058 mountDataBrowser();
059 }
060
061 /**
062 * Bookmarkable subclass of DataBrowser page. Access to the page is permitted
063 * only if the current application is assignable to DataApplication
064 * and returns true for isDataBrowserAllowed().
065 * @see DataBrowser
066 */
067 public static class BmarkDataBrowser extends DataBrowser {
068 public BmarkDataBrowser() {
069 super(((DataApplication)Application.get()).isDataBrowserAllowed());
070 }
071 }
072
073 /**
074 * Mounts Data Diver to /dbrowse. Override to mount elsewhere, or not mount at all.
075 * This method is only called if isDataBrowserAllowed() returns true in init().
076 */
077 protected void mountDataBrowser() {
078 mountBookmarkablePage("/dbrowse", BmarkDataBrowser.class);
079 }
080
081 /**
082 * Called by init to create Hibernate session factory and load a configuration. Passes
083 * an empty new AnnotationConfiguration to buildHibernateSessionFactory(key, config) by
084 * default. Override if creating a configuration externally.
085 * @param key session factory key; the default key is null
086 */
087 public void buildHibernateSessionFactory(Object key) {
088 buildHibernateSessionFactory(key, new AnnotationConfiguration());
089 }
090
091 /**
092 * Builds and a session factory with the given configuration. Passes config
093 * through configureHibernate methods.
094 * @param key session factory key; the default key is null
095 * @param config annotation conifuration
096 * @see #configureHibernateEssentials(AnnotationConfiguration)
097 * @see #configureHibernate(AnnotationConfiguration, Object)
098 */
099 final public void buildHibernateSessionFactory(Object key, AnnotationConfiguration config) {
100 configureHibernateEssentials(config);
101 configureHibernate(config, key);
102 setHibernateSessionFactory(key, config.buildSessionFactory());
103 }
104
105 /**
106 * Configures the session factory associated with the key. The default implementation
107 * calls the configureHibernate(config) method and ignores the key.
108 * For applications with multiple session factories, override this method to
109 * perform key-specific configuration here instead.
110 * @param config configuration to update
111 * @param key object, or null for the default factory
112 */
113 protected void configureHibernate(AnnotationConfiguration config, Object key) {
114 configureHibernate(config);
115 }
116
117 /**
118 * For Hibernate settings that should not normally be overriden by client
119 * applications. Specifically, this method sets Hibernate for a ManagedSessionContext,
120 * the session lookup method used by DataRequestCycle.
121 * @param config Hibernate configuration
122 */
123 protected void configureHibernateEssentials(AnnotationConfiguration config) {
124 config.setProperty("hibernate.current_session_context_class","managed");
125 }
126
127 /**
128 * Configures the default session factory; override to add annotated classes
129 * but don't forget to call this super-implementation if you want its defaults.
130 * When running in development the session factory is set for
131 * hbm2ddl auto-updating to create and add columns to tables
132 * as required. For deployment it is configured for C3P0 connection pooling.
133 * @param config used to build Hibernate session factory
134 */
135 protected void configureHibernate(AnnotationConfiguration config) {
136 if (isDevelopment())
137 config.setProperty("hibernate.hbm2ddl.auto", "update");
138 else {
139 config.setProperty("hibernate.c3p0.max_size", "20")
140 .setProperty("hibernate.c3p0.timeout","3000")
141 .setProperty("hibernate.c3p0.idle_test_period", "300");
142 }
143 }
144
145 /**
146 * @param key object, or null for the default factory
147 * @return the retained session factory
148 */
149 public SessionFactory getHibernateSessionFactory(Object key) {
150 SessionFactory sf = hibernateSessionFactories.get(key);
151 if (sf == null)
152 if (key == null)
153 throw new WicketRuntimeException("The default Hibernate session factory has not been " +
154 "initialized. This is normally done in DataApplication.init().");
155 else
156 throw new WicketRuntimeException("Session factory not found for key: " + key);
157 return sf;
158 }
159
160 /**
161 * @param key object, or null for the default factory
162 * @param sf session factory to retain
163 */
164 protected void setHibernateSessionFactory(Object key, SessionFactory sf) {
165 hibernateSessionFactories.put(key, sf);
166 }
167
168
169 /**
170 * @return a DataRequestCycle
171 * @see DataRequestCycle
172 */
173 @Override
174 public RequestCycle newRequestCycle(Request request, Response response) {
175 return new DataRequestCycle(this, (WebRequest) request, response);
176 }
177
178 /**
179 * Returns true if development mode is enabled. Override for other behavior.
180 * @return true if the Data Browser page should be enabled
181 */
182 protected boolean isDataBrowserAllowed() {
183 return isDevelopment();
184 }
185 }