1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.store.hibernate

File DefaultHibernateSessionFactory.java

 

Coverage histogram

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

Code metrics

28
66
13
1
283
179
28
0.42
5.08
13
2.15

Classes

Class Line # Actions
DefaultHibernateSessionFactory 56 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: fc486c48cb972b2c7d03ab7c7aad343b15742597 $
51    * @since 2.0M1
52    */
53    @Component
54    @Singleton
55    @DisposePriority(10000)
 
56    public class DefaultHibernateSessionFactory implements HibernateSessionFactory, Disposable
57    {
58    /**
59    * The logger to log.
60    */
61    @Inject
62    private Logger logger;
63   
64    /**
65    * Used to get Environment permanent directory to evaluate Hibernate properties.
66    */
67    @Inject
68    private org.xwiki.environment.Environment environment;
69   
 
70  206 toggle @Override
71    public void dispose() throws ComponentLifecycleException
72    {
73    // TODO: See https://jira.xwiki.org/browse/XWIKI-471. Note that this code currently duplicates
74    // XWikiHibernateBaseStore.shutdownHibernate() which is not public and getting a Store implementation from
75    // this component is very difficult since there's no XWikiContext and the store used is defined in xwiki.cfg
76  206 SessionFactory sessionFactory = getSessionFactory();
77  206 if (sessionFactory != null) {
78    // Close all connections in the Connection Pool.
79    // Note that we need to do the cast because this is how Hibernate suggests to get the Connection Provider.
80    // See http://bit.ly/QAJXlr
81  67 ConnectionProvider provider = ((SessionFactoryImplementor) sessionFactory).getConnectionProvider();
82    // If the user has specified a Data Source we shouldn't close it. Fortunately the way Hibernate works is
83    // the following: if the user has configured Hibernate to use a Data Source then Hibernate will use
84    // the DatasourceConnectionProvider class which has a close() method that doesn't do anything...
85  67 if (provider != null) {
86  67 provider.close();
87    }
88    }
89    }
90   
91    /**
92    * Hibernate configuration object.
93    */
94    private Configuration configuration = new Configuration()
95    {
96    /**
97    * The name of the property for configuring the environment permanent directory.
98    */
99    private static final String PROPERTY_PERMANENTDIRECTORY = "environment.permanentDirectory";
100   
101    private static final long serialVersionUID = 1L;
102   
103    /**
104    * Whether the Hibernate Configuration has already been initialized or not. We do this so that the Hibernate
105    * {@link org.hibernate.cfg.Configuration#configure()} methods can be called several times in a row without
106    * causing some Duplicate Mapping errors, see our overridden {@link #getConfigurationInputStream(String)} below.
107    */
108    private boolean isConfigurationInitialized;
109   
 
110  0 toggle @Override
111    public Configuration configure() throws HibernateException
112    {
113  0 Configuration configuration;
114  0 if (this.isConfigurationInitialized) {
115  0 configuration = this;
116    } else {
117  0 configuration = super.configure();
118  0 this.isConfigurationInitialized = true;
119    }
120  0 replaceVariables(configuration);
121  0 return configuration;
122    }
123   
 
124  76 toggle @Override
125    public Configuration configure(String resource) throws HibernateException
126    {
127  76 Configuration configuration;
128  76 if (this.isConfigurationInitialized) {
129  0 configuration = this;
130    } else {
131  76 configuration = super.configure(resource);
132  76 this.isConfigurationInitialized = true;
133    }
134  76 replaceVariables(configuration);
135  76 return configuration;
136    }
137   
 
138  0 toggle @Override
139    public Configuration configure(URL url) throws HibernateException
140    {
141  0 Configuration configuration;
142  0 if (this.isConfigurationInitialized) {
143  0 configuration = this;
144    } else {
145  0 configuration = super.configure(url);
146  0 this.isConfigurationInitialized = true;
147    }
148  0 replaceVariables(configuration);
149  0 return configuration;
150    }
151   
 
152  0 toggle @Override
153    public Configuration configure(File configFile) throws HibernateException
154    {
155  0 Configuration configuration;
156  0 if (this.isConfigurationInitialized) {
157  0 configuration = this;
158    } else {
159  0 configuration = super.configure(configFile);
160  0 this.isConfigurationInitialized = true;
161    }
162  0 replaceVariables(configuration);
163  0 return configuration;
164    }
165   
 
166  520 toggle @Override
167    public void add(XmlDocument metadataXml)
168    {
169  520 Element basePropertyElement = selectChildClassMappingElement(metadataXml.getDocumentTree().getRootElement(),
170    "class", "com.xpn.xwiki.objects.BaseProperty");
171  520 if (basePropertyElement != null) {
172  76 decorateDBStringListMapping(basePropertyElement);
173    }
174   
175  520 super.add(metadataXml);
176    }
177   
178    /**
179    * Select the class definition element that is an immediate child element of the given element.
180    *
181    * @param parentElement The parent element.
182    * @param elementName The element name for the given class definition ("class" or "joined-subclass").
183    * @param className The qualified class name to match.
184    */
 
185  596 toggle private Element selectChildClassMappingElement(Element parentElement, String elementName, String className)
186    {
187  596 for (Object elementObj : parentElement.elements(elementName)) {
188  1998 if (elementObj instanceof Element) {
189  1998 Element element = (Element) elementObj;
190  1998 Attribute attribute = element.attribute("name");
191  1998 if (attribute != null && className.equals(attribute.getValue())) {
192  152 return element;
193    }
194    }
195    }
196  444 return null;
197    }
198   
199    /**
200    * Decorate the hibernate mapping for the class DBStringListProperty with a collection-type attribute.
201    *
202    * @param basePropertyElement The element of the base property class mapping.
203    */
 
204  76 toggle private void decorateDBStringListMapping(Element basePropertyElement)
205    {
206  76 final String className = "com.xpn.xwiki.objects.DBStringListProperty";
207  76 final String collectionType = "com.xpn.xwiki.internal.objects.ListPropertyCollectionType";
208   
209  76 Element listClassElement = selectChildClassMappingElement(basePropertyElement, "joined-subclass",
210    className);
211   
212  76 if (listClassElement != null) {
213  76 Element listElement = listClassElement.element("list");
214  76 if (listElement != null) {
215  76 listElement.addAttribute("collection-type",
216    collectionType);
217  76 DefaultHibernateSessionFactory.this.logger.debug(
218    "Added collection-type attribute [{}] to hibernate mapping for [{}].", collectionType,
219    className);
220    }
221    }
222    }
223   
224    // There is no #configure(InputStream) so we use #configure(String) and override #getConfigurationInputStream
 
225  76 toggle @Override
226    protected InputStream getConfigurationInputStream(String resource) throws HibernateException
227    {
228  76 InputStream stream = Util.getResourceAsStream(resource);
229  76 if (stream == null) {
230  0 throw new HibernateException(String.format("Can't find [%s] for hibernate configuration", resource));
231    }
232  76 return stream;
233    }
234   
235    /**
236    * Replace variables defined in Hibernate properties using the <code>${variable}</code> notation. Note that
237    * right now the only variable being replaced is {@link #PROPERTY_PERMANENTDIRECTORY} and replaced with the
238    * value coming from the XWiki configuration.
239    *
240    * @param hibernateConfiguration the Hibernate Configuration object that we're evaluating
241    */
 
242  76 toggle private void replaceVariables(Configuration hibernateConfiguration)
243    {
244  76 String url = hibernateConfiguration.getProperty(Environment.URL);
245  76 if (StringUtils.isEmpty(url)) {
246  0 return;
247    }
248   
249    // Replace variables
250  76 if (url.matches(".*\\$\\{.*\\}.*")) {
251  70 String newURL = StringUtils.replace(url, String.format("${%s}", PROPERTY_PERMANENTDIRECTORY),
252    DefaultHibernateSessionFactory.this.environment.getPermanentDirectory().getAbsolutePath());
253   
254    // Set the new URL
255  70 hibernateConfiguration.setProperty(Environment.URL, newURL);
256  70 DefaultHibernateSessionFactory.this.logger.debug("Resolved Hibernate URL [{}] to [{}]", url, newURL);
257    }
258    }
259    };
260   
261    /**
262    * Real Hibernate session factory.
263    */
264    private SessionFactory sessionFactory;
265   
 
266  2919 toggle @Override
267    public Configuration getConfiguration()
268    {
269  2919 return this.configuration;
270    }
271   
 
272  1167827 toggle @Override
273    public SessionFactory getSessionFactory()
274    {
275  1167867 return this.sessionFactory;
276    }
277   
 
278  76 toggle @Override
279    public void setSessionFactory(SessionFactory sessionFactory)
280    {
281  76 this.sessionFactory = sessionFactory;
282    }
283    }