Skip to content

Commit 710e1f0

Browse files
committed
HHH-9899 Enable integrators to plug in custom MetadataBuilder and Metadata
1 parent 83f4d4b commit 710e1f0

8 files changed

+738
-8
lines changed

hibernate-core/src/main/java/org/hibernate/boot/MetadataBuilder.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.hibernate.type.BasicType;
2727
import org.hibernate.usertype.CompositeUserType;
2828
import org.hibernate.usertype.UserType;
29-
3029
import org.jboss.jandex.IndexView;
3130

3231
/**
@@ -395,6 +394,15 @@ public interface MetadataBuilder {
395394
// */
396395
// public MetadataBuilder with(PersistentAttributeMemberResolver resolver);
397396

397+
/**
398+
* Allows unwrapping this builder as another, more specific type.
399+
*
400+
* @param type
401+
* @param <T>
402+
*
403+
* @return The unwrapped builder.
404+
*/
405+
public <T extends MetadataBuilder> T unwrap(Class<T> type);
398406

399407
/**
400408
* Actually build the metamodel

hibernate-core/src/main/java/org/hibernate/boot/MetadataSources.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import java.util.List;
2020
import java.util.jar.JarFile;
2121
import java.util.zip.ZipEntry;
22+
2223
import javax.xml.transform.dom.DOMSource;
2324

25+
import org.hibernate.HibernateException;
2426
import org.hibernate.boot.archive.spi.InputStreamAccess;
2527
import org.hibernate.boot.internal.MetadataBuilderImpl;
2628
import org.hibernate.boot.jaxb.Origin;
@@ -32,12 +34,14 @@
3234
import org.hibernate.boot.registry.BootstrapServiceRegistry;
3335
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
3436
import org.hibernate.boot.registry.StandardServiceRegistry;
37+
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
38+
import org.hibernate.boot.spi.MetadataBuilderFactory;
3539
import org.hibernate.boot.spi.XmlMappingBinderAccess;
3640
import org.hibernate.internal.CoreLogging;
3741
import org.hibernate.internal.CoreMessageLogger;
42+
import org.hibernate.internal.util.StringHelper;
3843
import org.hibernate.service.ServiceRegistry;
3944
import org.hibernate.type.SerializationException;
40-
4145
import org.w3c.dom.Document;
4246

4347
/**
@@ -118,7 +122,8 @@ public ServiceRegistry getServiceRegistry() {
118122
* @return The built metadata.
119123
*/
120124
public MetadataBuilder getMetadataBuilder() {
121-
return new MetadataBuilderImpl( this );
125+
MetadataBuilderImpl defaultBuilder = new MetadataBuilderImpl( this );
126+
return getCustomBuilderOrDefault( defaultBuilder );
122127
}
123128

124129
/**
@@ -127,7 +132,40 @@ public MetadataBuilder getMetadataBuilder() {
127132
* @return The built metadata.
128133
*/
129134
public MetadataBuilder getMetadataBuilder(StandardServiceRegistry serviceRegistry) {
130-
return new MetadataBuilderImpl( this, serviceRegistry );
135+
MetadataBuilderImpl defaultBuilder = new MetadataBuilderImpl( this, serviceRegistry );
136+
return getCustomBuilderOrDefault( defaultBuilder );
137+
}
138+
139+
/**
140+
* In case a custom {@link MetadataBuilderFactory} creates a custom builder, return that one, otherwise the default
141+
* builder.
142+
*/
143+
private MetadataBuilder getCustomBuilderOrDefault(MetadataBuilderImpl defaultBuilder) {
144+
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
145+
final java.util.Collection<MetadataBuilderFactory> discoveredBuilderFactories = cls.loadJavaServices( MetadataBuilderFactory.class );
146+
147+
MetadataBuilder builder = null;
148+
List<String> activeFactoryNames = null;
149+
150+
for ( MetadataBuilderFactory discoveredBuilderFactory : discoveredBuilderFactories ) {
151+
final MetadataBuilder returnedBuilder = discoveredBuilderFactory.getMetadataBuilder( this, defaultBuilder );
152+
if ( returnedBuilder != null ) {
153+
if ( activeFactoryNames == null ) {
154+
activeFactoryNames = new ArrayList<String>();
155+
}
156+
activeFactoryNames.add( discoveredBuilderFactory.getClass().getName() );
157+
builder = returnedBuilder;
158+
}
159+
}
160+
161+
if ( activeFactoryNames != null && activeFactoryNames.size() > 1 ) {
162+
throw new HibernateException(
163+
"Multiple active MetadataBuilder definitions were discovered : " +
164+
StringHelper.join( ", ", activeFactoryNames )
165+
);
166+
}
167+
168+
return builder != null ? builder : defaultBuilder;
131169
}
132170

133171
/**

hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.HashMap;
1313
import java.util.List;
1414
import java.util.Map;
15+
1516
import javax.persistence.AttributeConverter;
1617
import javax.persistence.SharedCacheMode;
1718

@@ -74,7 +75,6 @@
7475
import org.hibernate.type.CustomType;
7576
import org.hibernate.usertype.CompositeUserType;
7677
import org.hibernate.usertype.UserType;
77-
7878
import org.jboss.jandex.IndexView;
7979

8080
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
@@ -385,6 +385,12 @@ public MetadataBuilder applyIdGenerationTypeInterpreter(IdGeneratorStrategyInter
385385
// return this;
386386
// }
387387

388+
@Override
389+
@SuppressWarnings("unchecked")
390+
public <T extends MetadataBuilder> T unwrap(Class<T> type) {
391+
return (T) this;
392+
}
393+
388394
@Override
389395
public MetadataImplementor build() {
390396
final CfgXmlAccessService cfgXmlAccessService = options.serviceRegistry.getService( CfgXmlAccessService.class );

hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import org.hibernate.service.spi.ServiceRegistryImplementor;
5454
import org.hibernate.tuple.entity.EntityTuplizer;
5555
import org.hibernate.tuple.entity.EntityTuplizerFactory;
56-
5756
import org.jboss.logging.Logger;
5857

5958
import static org.hibernate.cfg.AvailableSettings.AUTO_CLOSE_SESSION;
@@ -78,6 +77,7 @@
7877
import static org.hibernate.cfg.AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER;
7978
import static org.hibernate.cfg.AvailableSettings.ORDER_INSERTS;
8079
import static org.hibernate.cfg.AvailableSettings.ORDER_UPDATES;
80+
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
8181
import static org.hibernate.cfg.AvailableSettings.QUERY_CACHE_FACTORY;
8282
import static org.hibernate.cfg.AvailableSettings.QUERY_STARTUP_CHECKING;
8383
import static org.hibernate.cfg.AvailableSettings.QUERY_SUBSTITUTIONS;
@@ -98,7 +98,6 @@
9898
import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE;
9999
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
100100
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
101-
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
102101

103102
/**
104103
* @author Gail Badner
@@ -110,7 +109,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
110109
private final MetadataImplementor metadata;
111110
private final SessionFactoryOptionsStateStandardImpl options;
112111

113-
SessionFactoryBuilderImpl(MetadataImplementor metadata) {
112+
public SessionFactoryBuilderImpl(MetadataImplementor metadata) {
114113
this.metadata = metadata;
115114
this.options = new SessionFactoryOptionsStateStandardImpl( metadata.getMetadataBuildingOptions().getServiceRegistry() );
116115

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* Hibernate OGM, Domain model persistence for NoSQL datastores
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.boot.spi;
8+
9+
import java.util.Collection;
10+
import java.util.Map;
11+
import java.util.Set;
12+
import java.util.UUID;
13+
14+
import org.hibernate.MappingException;
15+
import org.hibernate.SessionFactory;
16+
import org.hibernate.boot.SessionFactoryBuilder;
17+
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
18+
import org.hibernate.boot.model.TypeDefinition;
19+
import org.hibernate.boot.model.relational.Database;
20+
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
21+
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
22+
import org.hibernate.dialect.function.SQLFunction;
23+
import org.hibernate.engine.ResultSetMappingDefinition;
24+
import org.hibernate.engine.spi.FilterDefinition;
25+
import org.hibernate.engine.spi.NamedQueryDefinition;
26+
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
27+
import org.hibernate.id.factory.IdentifierGeneratorFactory;
28+
import org.hibernate.internal.NamedQueryRepository;
29+
import org.hibernate.internal.SessionFactoryImpl;
30+
import org.hibernate.mapping.FetchProfile;
31+
import org.hibernate.mapping.MappedSuperclass;
32+
import org.hibernate.mapping.PersistentClass;
33+
import org.hibernate.mapping.Table;
34+
import org.hibernate.type.Type;
35+
import org.hibernate.type.TypeResolver;
36+
37+
/**
38+
* Convenience base class for custom implementors of {@link MetadataImplementor} using delegation.
39+
*
40+
* @author Gunnar Morling
41+
*
42+
*/
43+
public abstract class AbstractDelegatingMetadata implements MetadataImplementor {
44+
45+
private final MetadataImplementor delegate;
46+
47+
public AbstractDelegatingMetadata(MetadataImplementor delegate) {
48+
this.delegate = delegate;
49+
}
50+
51+
@Override
52+
public IdentifierGeneratorFactory getIdentifierGeneratorFactory() {
53+
return delegate.getIdentifierGeneratorFactory();
54+
}
55+
56+
@Override
57+
public Type getIdentifierType(String className) throws MappingException {
58+
return delegate.getIdentifierType( className );
59+
}
60+
61+
@Override
62+
public String getIdentifierPropertyName(String className) throws MappingException {
63+
return delegate.getIdentifierPropertyName( className );
64+
}
65+
66+
@Override
67+
public Type getReferencedPropertyType(String className, String propertyName) throws MappingException {
68+
return delegate.getReferencedPropertyType( className, propertyName );
69+
}
70+
71+
@Override
72+
public SessionFactoryBuilder getSessionFactoryBuilder() {
73+
return delegate.getSessionFactoryBuilder();
74+
}
75+
76+
@Override
77+
public SessionFactory buildSessionFactory() {
78+
return delegate.buildSessionFactory();
79+
}
80+
81+
@Override
82+
public UUID getUUID() {
83+
return delegate.getUUID();
84+
}
85+
86+
@Override
87+
public Database getDatabase() {
88+
return delegate.getDatabase();
89+
}
90+
91+
@Override
92+
public Collection<PersistentClass> getEntityBindings() {
93+
return delegate.getEntityBindings();
94+
}
95+
96+
@Override
97+
public PersistentClass getEntityBinding(String entityName) {
98+
return delegate.getEntityBinding( entityName );
99+
}
100+
101+
@Override
102+
public Collection<org.hibernate.mapping.Collection> getCollectionBindings() {
103+
return delegate.getCollectionBindings();
104+
}
105+
106+
@Override
107+
public org.hibernate.mapping.Collection getCollectionBinding(String role) {
108+
return delegate.getCollectionBinding( role );
109+
}
110+
111+
@Override
112+
public Map<String, String> getImports() {
113+
return delegate.getImports();
114+
}
115+
116+
@Override
117+
public NamedQueryDefinition getNamedQueryDefinition(String name) {
118+
return delegate.getNamedQueryDefinition( name );
119+
}
120+
121+
@Override
122+
public Collection<NamedQueryDefinition> getNamedQueryDefinitions() {
123+
return delegate.getNamedQueryDefinitions();
124+
}
125+
126+
@Override
127+
public NamedSQLQueryDefinition getNamedNativeQueryDefinition(String name) {
128+
return delegate.getNamedNativeQueryDefinition( name );
129+
}
130+
131+
@Override
132+
public Collection<NamedSQLQueryDefinition> getNamedNativeQueryDefinitions() {
133+
return delegate.getNamedNativeQueryDefinitions();
134+
}
135+
136+
@Override
137+
public Collection<NamedProcedureCallDefinition> getNamedProcedureCallDefinitions() {
138+
return delegate.getNamedProcedureCallDefinitions();
139+
}
140+
141+
@Override
142+
public ResultSetMappingDefinition getResultSetMapping(String name) {
143+
return delegate.getResultSetMapping( name );
144+
}
145+
146+
@Override
147+
public Map<String, ResultSetMappingDefinition> getResultSetMappingDefinitions() {
148+
return delegate.getResultSetMappingDefinitions();
149+
}
150+
151+
@Override
152+
public TypeDefinition getTypeDefinition(String typeName) {
153+
return delegate.getTypeDefinition( typeName );
154+
}
155+
156+
@Override
157+
public Map<String, FilterDefinition> getFilterDefinitions() {
158+
return delegate.getFilterDefinitions();
159+
}
160+
161+
@Override
162+
public FilterDefinition getFilterDefinition(String name) {
163+
return delegate.getFilterDefinition( name );
164+
}
165+
166+
@Override
167+
public FetchProfile getFetchProfile(String name) {
168+
return delegate.getFetchProfile( name );
169+
}
170+
171+
@Override
172+
public Collection<FetchProfile> getFetchProfiles() {
173+
return delegate.getFetchProfiles();
174+
}
175+
176+
@Override
177+
public NamedEntityGraphDefinition getNamedEntityGraph(String name) {
178+
return delegate.getNamedEntityGraph( name );
179+
}
180+
181+
@Override
182+
public Map<String, NamedEntityGraphDefinition> getNamedEntityGraphs() {
183+
return delegate.getNamedEntityGraphs();
184+
}
185+
186+
@Override
187+
public IdentifierGeneratorDefinition getIdentifierGenerator(String name) {
188+
return delegate.getIdentifierGenerator( name );
189+
}
190+
191+
@Override
192+
public Collection<Table> collectTableMappings() {
193+
return delegate.collectTableMappings();
194+
}
195+
196+
@Override
197+
public Map<String, SQLFunction> getSqlFunctionMap() {
198+
return delegate.getSqlFunctionMap();
199+
}
200+
201+
@Override
202+
public MetadataBuildingOptions getMetadataBuildingOptions() {
203+
return delegate.getMetadataBuildingOptions();
204+
}
205+
206+
@Override
207+
public TypeResolver getTypeResolver() {
208+
return delegate.getTypeResolver();
209+
}
210+
211+
@Override
212+
public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory) {
213+
return delegate.buildNamedQueryRepository( sessionFactory );
214+
}
215+
216+
@Override
217+
public void validate() throws MappingException {
218+
delegate.validate();
219+
}
220+
221+
@Override
222+
public Set<MappedSuperclass> getMappedSuperclassMappingsCopy() {
223+
return delegate.getMappedSuperclassMappingsCopy();
224+
}
225+
}

0 commit comments

Comments
 (0)