1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.store.hibernate

File DefaultHibernateSessionFactory.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart7.png
64% of files have more coverage

Code metrics

28
66
13
1
284
179
28
0.42
5.08
13
2.15

Classes

Class Line # Actions
DefaultHibernateSessionFactory 57 66 0% 28 40
0.6261682562.6%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.store.hibernate;
21   
22    import java.io.File;
23    import java.io.InputStream;
24    import java.net.URL;
25   
26    import javax.inject.Inject;
27    import javax.inject.Singleton;
28   
29    import org.apache.commons.lang3.StringUtils;
30    import org.dom4j.Attribute;
31    import org.dom4j.Element;
32    import org.hibernate.HibernateException;
33    import org.hibernate.SessionFactory;
34    import org.hibernate.cfg.Configuration;
35    import org.hibernate.cfg.Environment;
36    import org.hibernate.connection.ConnectionProvider;
37    import org.hibernate.engine.SessionFactoryImplementor;
38    import org.hibernate.util.xml.XmlDocument;
39    import org.slf4j.Logger;
40    import org.xwiki.component.annotation.Component;
41    import org.xwiki.component.annotation.DisposePriority;
42    import org.xwiki.component.manager.ComponentLifecycleException;
43    import org.xwiki.component.phase.Disposable;
44   
45    import com.xpn.xwiki.util.Util;
46   
47    /**
48    * Default implementation for {@link HibernateSessionFactory}.
49    *
50    * @version $Id: e7ad5976788b64fe57b0f6cc2eb130211ca13f66 $
51    * @since 2.0M1
52    */
53    // TODO: This was coded by Artem. Find out why we need this as a component.
54    @Component
55    @Singleton
56    @DisposePriority(10000)
 
57    public class DefaultHibernateSessionFactory implements HibernateSessionFactory, Disposable
58    {
59    /**
60    * The logger to log.
61    */
62    @Inject
63    private Logger logger;
64   
65    /**
66    * Used to get Environment permanent directory to evaluate Hibernate properties.
67    */
68    @Inject
69    private org.xwiki.environment.Environment environment;
70   
 
71  184 toggle @Override
72    public void dispose() throws ComponentLifecycleException
73    {
74    // TODO: See http://jira.xwiki.org/jira/browse/XWIKI-471. Note that this code currently duplicates
75    // XWikiHibernateBaseStore.shutdownHibernate() which is not public and getting a Store implementation from
76    // this component is very difficult since there's no XWikiContext and the store used is defined in xwiki.cfg
77  184 SessionFactory sessionFactory = getSessionFactory();
78  184 if (sessionFactory != null) {
79    // Close all connections in the Connection Pool.
80    // Note that we need to do the cast because this is how Hibernate suggests to get the Connection Provider.
81    // See http://bit.ly/QAJXlr
82  60 ConnectionProvider provider = ((SessionFactoryImplementor) sessionFactory).getConnectionProvider();
83    // If the user has specified a Data Source we shouldn't close it. Fortunately the way Hibernate works is
84    // the following: if the user has configured Hibernate to use a Data Source then Hibernate will use
85    // the DatasourceConnectionProvider class which has a close() method that doesn't do anything...
86  60 if (provider != null) {
87  60 provider.close();
88    }
89    }
90    }
91   
92    /**
93    * Hibernate configuration object.
94    */
95    private Configuration configuration = new Configuration()
96    {
97    /**
98    * The name of the property for configuring the environment permanent directory.
99    */
100    private static final String PROPERTY_PERMANENTDIRECTORY = "environment.permanentDirectory";
101   
102    private static final long serialVersionUID = 1L;
103   
104    /**
105    * Whether the Hibernate Configuration has already been initialized or not. We do this so that the Hibernate
106    * {@link org.hibernate.cfg.Configuration#configure()} methods can be called several times in a row without
107    * causing some Duplicate Mapping errors, see our overridden {@link #getConfigurationInputStream(String)} below.
108    */
109    private boolean isConfigurationInitialized;
110   
 
111  0 toggle @Override
112    public Configuration configure() throws HibernateException
113    {
114  0 Configuration configuration;
115  0 if (this.isConfigurationInitialized) {
116  0 configuration = this;
117    } else {
118  0 configuration = super.configure();
119  0 this.isConfigurationInitialized = true;
120    }
121  0 replaceVariables(configuration);
122  0 return configuration;
123    }
124   
 
125  60 toggle @Override
126    public Configuration configure(String resource) throws HibernateException
127    {
128  60 Configuration configuration;
129  60 if (this.isConfigurationInitialized) {
130  0 configuration = this;
131    } else {
132  60 configuration = super.configure(resource);
133  60 this.isConfigurationInitialized = true;
134    }
135  60 replaceVariables(configuration);
136  60 return configuration;
137    }
138   
 
139  0 toggle @Override
140    public Configuration configure(URL url) throws HibernateException
141    {
142  0 Configuration configuration;
143  0 if (this.isConfigurationInitialized) {
144  0 configuration = this;
145    } else {
146  0 configuration = super.configure(url);
147  0 this.isConfigurationInitialized = true;
148    }
149  0 replaceVariables(configuration);
150  0 return configuration;
151    }
152   
 
153  0 toggle @Override
154    public Configuration configure(File configFile) throws HibernateException
155    {
156  0 Configuration configuration;
157  0 if (this.isConfigurationInitialized) {
158  0 configuration = this;
159    } else {
160  0 configuration = super.configure(configFile);
161  0 this.isConfigurationInitialized = true;
162    }
163  0 replaceVariables(configuration);
164  0 return configuration;
165    }
166   
 
167  346 toggle @Override
168    public void add(XmlDocument metadataXml)
169    {
170  346 Element basePropertyElement = selectChildClassMappingElement(metadataXml.getDocumentTree().getRootElement(),
171    "class", "com.xpn.xwiki.objects.BaseProperty");
172  346 if (basePropertyElement != null) {
173  60 decorateDBStringListMapping(basePropertyElement);
174    }
175   
176  346 super.add(metadataXml);
177    }
178   
179    /**
180    * Select the class definition element that is an immediate child element of the given element.
181    *
182    * @param parentElement The parent element.
183    * @param elementName The element name for the given class definition ("class" or "joined-subclass").
184    * @param className The qualified class name to match.
185    */
 
186  406 toggle private Element selectChildClassMappingElement(Element parentElement, String elementName, String className)
187    {
188  406 for (Object elementObj : parentElement.elements(elementName)) {
189  1510 if (elementObj instanceof Element) {
190  1510 Element element = (Element) elementObj;
191  1510 Attribute attribute = element.attribute("name");
192  1510 if (attribute != null && className.equals(attribute.getValue())) {
193  120 return element;
194    }
195    }
196    }
197  286 return null;
198    }
199   
200    /**
201    * Decorate the hibernate mapping for the class DBStringListProperty with a collection-type attribute.
202    *
203    * @param basePropertyElement The element of the base property class mapping.
204    */
 
205  60 toggle private void decorateDBStringListMapping(Element basePropertyElement)
206    {
207  60 final String className = "com.xpn.xwiki.objects.DBStringListProperty";
208  60 final String collectionType = "com.xpn.xwiki.internal.objects.ListPropertyCollectionType";
209   
210  60 Element listClassElement = selectChildClassMappingElement(basePropertyElement, "joined-subclass",
211    className);
212   
213  60 if (listClassElement != null) {
214  60 Element listElement = listClassElement.element("list");
215  60 if (listElement != null) {
216  60 listElement.addAttribute("collection-type",
217    collectionType);
218  60 DefaultHibernateSessionFactory.this.logger.debug(
219    "Added collection-type attribute [{}] to hibernate mapping for [{}].", collectionType,
220    className);
221    }
222    }
223    }
224   
225    // There is no #configure(InputStream) so we use #configure(String) and override #getConfigurationInputStream
 
226  60 toggle @Override
227    protected InputStream getConfigurationInputStream(String resource) throws HibernateException
228    {
229  60 InputStream stream = Util.getResourceAsStream(resource);
230  60 if (stream == null) {
231  0 throw new HibernateException(String.format("Can't find [%s] for hibernate configuration", resource));
232    }
233  60 return stream;
234    }
235   
236    /**
237    * Replace variables defined in Hibernate properties using the <code>${variable}</code> notation. Note that
238    * right now the only variable being replaced is {@link #PROPERTY_PERMANENTDIRECTORY} and replaced with the
239    * value coming from the XWiki configuration.
240    *
241    * @param hibernateConfiguration the Hibernate Configuration object that we're evaluating
242    */
 
243  60 toggle private void replaceVariables(Configuration hibernateConfiguration)
244    {
245  60 String url = hibernateConfiguration.getProperty(Environment.URL);
246  60 if (StringUtils.isEmpty(url)) {
247  0 return;
248    }
249   
250    // Replace variables
251  60 if (url.matches(".*\\$\\{.*\\}.*")) {
252  55 String newURL = StringUtils.replace(url, String.format("${%s}", PROPERTY_PERMANENTDIRECTORY),
253    DefaultHibernateSessionFactory.this.environment.getPermanentDirectory().getAbsolutePath());
254   
255    // Set the new URL
256  55 hibernateConfiguration.setProperty(Environment.URL, newURL);
257  55 DefaultHibernateSessionFactory.this.logger.debug("Resolved Hibernate URL [{}] to [{}]", url, newURL);
258    }
259    }
260    };
261   
262    /**
263    * Real Hibernate session factory.
264    */
265    private SessionFactory sessionFactory;
266   
 
267  712 toggle @Override
268    public Configuration getConfiguration()
269    {
270  712 return this.configuration;
271    }
272   
 
273  227412 toggle @Override
274    public SessionFactory getSessionFactory()
275    {
276  227406 return this.sessionFactory;
277    }
278   
 
279  60 toggle @Override
280    public void setSessionFactory(SessionFactory sessionFactory)
281    {
282  60 this.sessionFactory = sessionFactory;
283    }
284    }