1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.connector.store.jpa;
25
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Enumeration;
31 import java.util.HashMap;
32 import java.util.Hashtable;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Properties;
36 import java.util.UUID;
37 import javax.naming.Context;
38 import javax.naming.InitialContext;
39 import javax.naming.RefAddr;
40 import javax.naming.Reference;
41 import javax.naming.StringRefAddr;
42 import javax.naming.spi.ObjectFactory;
43 import javax.persistence.EntityManager;
44 import javax.persistence.EntityManagerFactory;
45 import javax.sql.DataSource;
46 import net.jcip.annotations.Immutable;
47 import net.jcip.annotations.ThreadSafe;
48 import org.hibernate.SessionFactory;
49 import org.hibernate.ejb.Ejb3Configuration;
50 import org.modeshape.common.i18n.I18n;
51 import org.modeshape.common.util.CheckArg;
52 import org.modeshape.common.util.Logger;
53 import org.modeshape.common.util.StringUtil;
54 import org.modeshape.connector.store.jpa.model.simple.SimpleModel;
55 import org.modeshape.connector.store.jpa.util.StoreOptionEntity;
56 import org.modeshape.connector.store.jpa.util.StoreOptions;
57 import org.modeshape.graph.ExecutionContext;
58 import org.modeshape.graph.cache.CachePolicy;
59 import org.modeshape.graph.connector.RepositoryConnection;
60 import org.modeshape.graph.connector.RepositoryContext;
61 import org.modeshape.graph.connector.RepositorySource;
62 import org.modeshape.graph.connector.RepositorySourceCapabilities;
63 import org.modeshape.graph.connector.RepositorySourceException;
64
65
66
67
68
69
70 @ThreadSafe
71 public class JpaSource implements RepositorySource, ObjectFactory {
72
73 private final Logger LOGGER = Logger.getLogger(JpaSource.class);
74
75
76
77
78
79
80 public static class Models {
81 public static final Model SIMPLE = new SimpleModel();
82 private static final Model[] ALL_ARRAY = new Model[] {SIMPLE};
83 private static final List<Model> MODIFIABLE_MODELS = new ArrayList<Model>(Arrays.asList(ALL_ARRAY));
84 public static final Collection<Model> ALL = Collections.unmodifiableCollection(MODIFIABLE_MODELS);
85 public static final Model DEFAULT = SIMPLE;
86
87 public static boolean addModel( Model model ) {
88 CheckArg.isNotNull(model, "modelName");
89 for (Model existing : MODIFIABLE_MODELS) {
90 if (existing.getName().equals(model.getName())) return false;
91 }
92 return MODIFIABLE_MODELS.add(model);
93 }
94
95 public static Model getModel( String name ) {
96 CheckArg.isNotEmpty(name, "name");
97 name = name.trim();
98 for (Model existing : ALL) {
99 if (existing.getName().equals(name)) return existing;
100 }
101 return null;
102 }
103 }
104
105 protected static final String SOURCE_NAME = "sourceName";
106 protected static final String ROOT_NODE_UUID = "rootNodeUuid";
107 protected static final String DATA_SOURCE_JNDI_NAME = "dataSourceJndiName";
108 protected static final String DIALECT = "dialect";
109 protected static final String USERNAME = "username";
110 protected static final String PASSWORD = "password";
111 protected static final String URL = "url";
112 protected static final String DRIVER_CLASS_NAME = "driverClassName";
113 protected static final String DRIVER_CLASSLOADER_NAME = "driverClassloaderName";
114 protected static final String MAXIMUM_CONNECTIONS_IN_POOL = "maximumConnectionsInPool";
115 protected static final String MINIMUM_CONNECTIONS_IN_POOL = "minimumConnectionsInPool";
116 protected static final String MAXIMUM_CONNECTION_IDLE_TIME_IN_SECONDS = "maximumConnectionIdleTimeInSeconds";
117 protected static final String MAXIMUM_SIZE_OF_STATEMENT_CACHE = "maximumSizeOfStatementCache";
118 protected static final String NUMBER_OF_CONNECTIONS_TO_BE_ACQUIRED_AS_NEEDED = "numberOfConnectionsToBeAcquiredAsNeeded";
119 protected static final String IDLE_TIME_IN_SECONDS_BEFORE_TESTING_CONNECTIONS = "idleTimeInSecondsBeforeTestingConnections";
120 protected static final String CACHE_TIME_TO_LIVE_IN_MILLISECONDS = "cacheTimeToLiveInMilliseconds";
121 protected static final String RETRY_LIMIT = "retryLimit";
122 protected static final String MODEL_NAME = "modelName";
123 protected static final String LARGE_VALUE_SIZE_IN_BYTES = "largeValueSizeInBytes";
124 protected static final String COMPRESS_DATA = "compressData";
125 protected static final String ENFORCE_REFERENTIAL_INTEGRITY = "enforceReferentialIntegrity";
126 protected static final String DEFAULT_WORKSPACE = "defaultWorkspace";
127 protected static final String PREDEFINED_WORKSPACE_NAMES = "predefinedWorkspaceNames";
128 protected static final String ALLOW_CREATING_WORKSPACES = "allowCreatingWorkspaces";
129 protected static final String AUTO_GENERATE_SCHEMA = "autoGenerateSchema";
130
131
132
133
134 protected static final boolean SUPPORTS_EVENTS = true;
135
136
137
138 protected static final boolean SUPPORTS_SAME_NAME_SIBLINGS = true;
139
140
141
142 protected static final boolean SUPPORTS_REFERENCES = true;
143
144
145
146
147 public static final boolean DEFAULT_ALLOWS_UPDATES = true;
148
149
150
151 public static final boolean DEFAULT_SHOW_SQL = false;
152
153
154
155 public static final boolean DEFAULT_SUPPORTS_CREATING_WORKSPACES = true;
156
157
158
159
160 public static final String DEFAULT_ROOT_NODE_UUID = "1497b6fe-8c7e-4bbb-aaa2-24f3d4942668";
161
162
163
164
165 public static final String DEFAULT_NAME_OF_DEFAULT_WORKSPACE = "default";
166
167 private static final int DEFAULT_RETRY_LIMIT = 0;
168 private static final int DEFAULT_CACHE_TIME_TO_LIVE_IN_SECONDS = 60 * 5;
169 private static final int DEFAULT_MAXIMUM_FETCH_DEPTH = 3;
170 private static final int DEFAULT_MAXIMUM_CONNECTIONS_IN_POOL = 5;
171 private static final int DEFAULT_MINIMUM_CONNECTIONS_IN_POOL = 0;
172 private static final int DEFAULT_MAXIMUM_CONNECTION_IDLE_TIME_IN_SECONDS = 60 * 10;
173 private static final int DEFAULT_MAXIMUM_NUMBER_OF_STATEMENTS_TO_CACHE = 100;
174 private static final int DEFAULT_NUMBER_OF_CONNECTIONS_TO_ACQUIRE_AS_NEEDED = 1;
175 private static final int DEFAULT_IDLE_TIME_IN_SECONDS_BEFORE_TESTING_CONNECTIONS = 60 * 3;
176 private static final int DEFAULT_LARGE_VALUE_SIZE_IN_BYTES = 1 << 10;
177 private static final boolean DEFAULT_COMPRESS_DATA = true;
178 private static final boolean DEFAULT_ENFORCE_REFERENTIAL_INTEGRITY = true;
179
180
181
182
183
184 public static final String DEFAULT_AUTO_GENERATE_SCHEMA = "validate";
185
186
187
188
189 private static final long serialVersionUID = 1L;
190
191 private volatile String name;
192 private volatile String dataSourceJndiName;
193 private volatile String dialect;
194 private volatile String username;
195 private volatile String password;
196 private volatile String url;
197 private volatile String driverClassName;
198 private volatile String driverClassloaderName;
199 private volatile String rootNodeUuid = DEFAULT_ROOT_NODE_UUID;
200 private volatile int maximumConnectionsInPool = DEFAULT_MAXIMUM_CONNECTIONS_IN_POOL;
201 private volatile int minimumConnectionsInPool = DEFAULT_MINIMUM_CONNECTIONS_IN_POOL;
202 private volatile int maximumConnectionIdleTimeInSeconds = DEFAULT_MAXIMUM_CONNECTION_IDLE_TIME_IN_SECONDS;
203 private volatile int maximumSizeOfStatementCache = DEFAULT_MAXIMUM_NUMBER_OF_STATEMENTS_TO_CACHE;
204 private volatile int numberOfConnectionsToAcquireAsNeeded = DEFAULT_NUMBER_OF_CONNECTIONS_TO_ACQUIRE_AS_NEEDED;
205 private volatile int idleTimeInSecondsBeforeTestingConnections = DEFAULT_IDLE_TIME_IN_SECONDS_BEFORE_TESTING_CONNECTIONS;
206 private volatile int retryLimit = DEFAULT_RETRY_LIMIT;
207 private volatile int cacheTimeToLiveInMilliseconds = DEFAULT_CACHE_TIME_TO_LIVE_IN_SECONDS * 1000;
208 private volatile long largeValueSizeInBytes = DEFAULT_LARGE_VALUE_SIZE_IN_BYTES;
209 private volatile boolean showSql = DEFAULT_SHOW_SQL;
210 private volatile boolean compressData = DEFAULT_COMPRESS_DATA;
211 private volatile boolean referentialIntegrityEnforced = DEFAULT_ENFORCE_REFERENTIAL_INTEGRITY;
212 private volatile String autoGenerateSchema = DEFAULT_AUTO_GENERATE_SCHEMA;
213 private volatile String defaultWorkspace = DEFAULT_NAME_OF_DEFAULT_WORKSPACE;
214 private volatile String[] predefinedWorkspaces = new String[] {};
215 private volatile RepositorySourceCapabilities capabilities = new RepositorySourceCapabilities(
216 SUPPORTS_SAME_NAME_SIBLINGS,
217 DEFAULT_ALLOWS_UPDATES,
218 SUPPORTS_EVENTS,
219 DEFAULT_SUPPORTS_CREATING_WORKSPACES,
220 SUPPORTS_REFERENCES);
221 private volatile String modelName;
222 private transient Model model;
223 private transient DataSource dataSource;
224 private transient EntityManagers entityManagers;
225 private transient CachePolicy cachePolicy;
226 private transient RepositoryContext repositoryContext;
227 private transient UUID rootUuid = UUID.fromString(rootNodeUuid);
228
229
230
231
232
233
234 public String getName() {
235 return name;
236 }
237
238 protected Logger getLogger() {
239 return LOGGER;
240 }
241
242
243
244
245
246
247 public void setName( String name ) {
248 if (name != null) {
249 name = name.trim();
250 if (name.length() == 0) name = null;
251 }
252 this.name = name;
253 }
254
255
256
257
258
259
260 public RepositorySourceCapabilities getCapabilities() {
261 return capabilities;
262 }
263
264
265
266
267
268
269 public boolean areUpdatesAllowed() {
270 return capabilities.supportsUpdates();
271 }
272
273
274
275
276
277
278 public synchronized void setAllowsUpdates( boolean allowsUpdates ) {
279 capabilities = new RepositorySourceCapabilities(capabilities.supportsSameNameSiblings(), allowsUpdates,
280 capabilities.supportsEvents(), capabilities.supportsCreatingWorkspaces(),
281 capabilities.supportsReferences());
282 }
283
284
285
286
287
288
289 public boolean getShowSql() {
290 return this.showSql;
291 }
292
293
294
295
296
297
298 public synchronized void setShowSql( boolean showSql ) {
299 this.showSql = showSql;
300 }
301
302
303
304
305
306
307
308 public String getAutoGenerateSchema() {
309 return this.autoGenerateSchema;
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332 public synchronized void setAutoGenerateSchema( String autoGenerateSchema ) {
333 this.autoGenerateSchema = autoGenerateSchema != null ? autoGenerateSchema.trim() : DEFAULT_AUTO_GENERATE_SCHEMA;
334 }
335
336
337
338
339
340
341 public int getRetryLimit() {
342 return retryLimit;
343 }
344
345
346
347
348
349
350 public synchronized void setRetryLimit( int limit ) {
351 if (limit < 0) limit = 0;
352 this.retryLimit = limit;
353 }
354
355
356
357
358
359
360 public int getCacheTimeToLiveInMilliseconds() {
361 return cacheTimeToLiveInMilliseconds;
362 }
363
364
365
366
367
368
369
370 public synchronized void setCacheTimeToLiveInMilliseconds( int cacheTimeToLive ) {
371 if (cacheTimeToLive < 0) cacheTimeToLive = DEFAULT_CACHE_TIME_TO_LIVE_IN_SECONDS;
372 this.cacheTimeToLiveInMilliseconds = cacheTimeToLive;
373 this.cachePolicy = cacheTimeToLiveInMilliseconds > 0 ? new JpaCachePolicy(cacheTimeToLiveInMilliseconds) : null;
374 }
375
376
377
378
379
380
381 public CachePolicy getCachePolicy() {
382 return cachePolicy;
383 }
384
385
386
387
388
389
390 public EntityManagers getEntityManagers() {
391 return entityManagers;
392 }
393
394
395
396
397 public String getRootNodeUuid() {
398 return rootNodeUuid;
399 }
400
401
402
403
404 public UUID getRootUuid() {
405 return rootUuid;
406 }
407
408
409
410
411
412 public void setRootNodeUuid( String rootNodeUuid ) {
413 if (rootNodeUuid != null && rootNodeUuid.trim().length() == 0) rootNodeUuid = DEFAULT_ROOT_NODE_UUID;
414 this.rootUuid = UUID.fromString(rootNodeUuid);
415 this.rootNodeUuid = rootNodeUuid;
416 }
417
418
419
420
421
422
423 public String getDefaultWorkspaceName() {
424 return defaultWorkspace;
425 }
426
427
428
429
430
431
432
433 public synchronized void setDefaultWorkspaceName( String nameOfDefaultWorkspace ) {
434 this.defaultWorkspace = nameOfDefaultWorkspace != null ? nameOfDefaultWorkspace : DEFAULT_NAME_OF_DEFAULT_WORKSPACE;
435 }
436
437
438
439
440
441
442
443
444 public synchronized String[] getPredefinedWorkspaceNames() {
445 String[] copy = new String[predefinedWorkspaces.length];
446 System.arraycopy(predefinedWorkspaces, 0, copy, 0, predefinedWorkspaces.length);
447 return copy;
448 }
449
450
451
452
453
454
455
456
457
458 public synchronized void setPredefinedWorkspaceNames( String[] predefinedWorkspaceNames ) {
459 if (predefinedWorkspaceNames != null && predefinedWorkspaceNames.length == 1) {
460 predefinedWorkspaceNames = predefinedWorkspaceNames[0].split("\\s*,\\s*");
461 }
462 this.predefinedWorkspaces = predefinedWorkspaceNames != null ? predefinedWorkspaceNames : new String[] {};
463 }
464
465
466
467
468
469
470
471
472
473
474 public boolean isCreatingWorkspacesAllowed() {
475 return capabilities.supportsCreatingWorkspaces();
476 }
477
478
479
480
481
482
483
484
485
486
487 public synchronized void setCreatingWorkspacesAllowed( boolean allowWorkspaceCreation ) {
488 capabilities = new RepositorySourceCapabilities(capabilities.supportsSameNameSiblings(), capabilities.supportsUpdates(),
489 capabilities.supportsEvents(), allowWorkspaceCreation,
490 capabilities.supportsReferences());
491 }
492
493
494
495
496 public String getDialect() {
497 return dialect;
498 }
499
500
501
502
503 public synchronized void setDialect( String dialect ) {
504 if (dialect != null && dialect.trim().length() == 0) dialect = null;
505 this.dialect = dialect;
506 }
507
508
509
510
511 public String getDataSourceJndiName() {
512 return dataSourceJndiName;
513 }
514
515
516
517
518 public void setDataSourceJndiName( String dataSourceJndiName ) {
519 if (dataSourceJndiName != null && dataSourceJndiName.trim().length() == 0) dataSourceJndiName = null;
520 this.dataSourceJndiName = dataSourceJndiName;
521 }
522
523
524
525
526 public String getDriverClassName() {
527 return driverClassName;
528 }
529
530
531
532
533 public synchronized void setDriverClassName( String driverClassName ) {
534 if (driverClassName != null && driverClassName.trim().length() == 0) driverClassName = null;
535 this.driverClassName = driverClassName;
536 }
537
538
539
540
541 public String getDriverClassloaderName() {
542 return driverClassloaderName;
543 }
544
545
546
547
548 public void setDriverClassloaderName( String driverClassloaderName ) {
549 if (driverClassloaderName != null && driverClassloaderName.trim().length() == 0) driverClassloaderName = null;
550 this.driverClassloaderName = driverClassloaderName;
551 }
552
553
554
555
556 public String getUsername() {
557 return username;
558 }
559
560
561
562
563 public synchronized void setUsername( String username ) {
564 this.username = username;
565 }
566
567
568
569
570 public String getPassword() {
571 return password;
572 }
573
574
575
576
577 public synchronized void setPassword( String password ) {
578 this.password = password;
579 }
580
581
582
583
584 public String getUrl() {
585 return url;
586 }
587
588
589
590
591 public synchronized void setUrl( String url ) {
592 if (url != null && url.trim().length() == 0) url = null;
593 this.url = url;
594 }
595
596
597
598
599 public int getMaximumConnectionsInPool() {
600 return maximumConnectionsInPool;
601 }
602
603
604
605
606 public synchronized void setMaximumConnectionsInPool( int maximumConnectionsInPool ) {
607 if (maximumConnectionsInPool < 0) maximumConnectionsInPool = DEFAULT_MAXIMUM_CONNECTIONS_IN_POOL;
608 this.maximumConnectionsInPool = maximumConnectionsInPool;
609 }
610
611
612
613
614 public int getMinimumConnectionsInPool() {
615 return minimumConnectionsInPool;
616 }
617
618
619
620
621 public synchronized void setMinimumConnectionsInPool( int minimumConnectionsInPool ) {
622 if (minimumConnectionsInPool < 0) minimumConnectionsInPool = DEFAULT_MINIMUM_CONNECTIONS_IN_POOL;
623 this.minimumConnectionsInPool = minimumConnectionsInPool;
624 }
625
626
627
628
629 public int getMaximumConnectionIdleTimeInSeconds() {
630 return maximumConnectionIdleTimeInSeconds;
631 }
632
633
634
635
636 public synchronized void setMaximumConnectionIdleTimeInSeconds( int maximumConnectionIdleTimeInSeconds ) {
637 if (maximumConnectionIdleTimeInSeconds < 0) maximumConnectionIdleTimeInSeconds = DEFAULT_MAXIMUM_CONNECTION_IDLE_TIME_IN_SECONDS;
638 this.maximumConnectionIdleTimeInSeconds = maximumConnectionIdleTimeInSeconds;
639 }
640
641
642
643
644 public int getMaximumSizeOfStatementCache() {
645 return maximumSizeOfStatementCache;
646 }
647
648
649
650
651 public synchronized void setMaximumSizeOfStatementCache( int maximumSizeOfStatementCache ) {
652 if (maximumSizeOfStatementCache < 0) maximumSizeOfStatementCache = DEFAULT_MAXIMUM_NUMBER_OF_STATEMENTS_TO_CACHE;
653 this.maximumSizeOfStatementCache = maximumSizeOfStatementCache;
654 }
655
656
657
658
659 public int getNumberOfConnectionsToAcquireAsNeeded() {
660 return numberOfConnectionsToAcquireAsNeeded;
661 }
662
663
664
665
666 public synchronized void setNumberOfConnectionsToAcquireAsNeeded( int numberOfConnectionsToAcquireAsNeeded ) {
667 if (numberOfConnectionsToAcquireAsNeeded < 0) numberOfConnectionsToAcquireAsNeeded = DEFAULT_NUMBER_OF_CONNECTIONS_TO_ACQUIRE_AS_NEEDED;
668 this.numberOfConnectionsToAcquireAsNeeded = numberOfConnectionsToAcquireAsNeeded;
669 }
670
671
672
673
674 public int getIdleTimeInSecondsBeforeTestingConnections() {
675 return idleTimeInSecondsBeforeTestingConnections;
676 }
677
678
679
680
681 public synchronized void setIdleTimeInSecondsBeforeTestingConnections( int idleTimeInSecondsBeforeTestingConnections ) {
682 if (idleTimeInSecondsBeforeTestingConnections < 0) idleTimeInSecondsBeforeTestingConnections = DEFAULT_IDLE_TIME_IN_SECONDS_BEFORE_TESTING_CONNECTIONS;
683 this.idleTimeInSecondsBeforeTestingConnections = idleTimeInSecondsBeforeTestingConnections;
684 }
685
686
687
688
689
690
691
692
693
694 return dataSource;
695 }
696
697
698
699
700
701
702
703
704
705 this.dataSource = dataSource;
706 }
707
708
709
710
711
712
713
714 public String getModel() {
715 return modelName;
716 }
717
718
719
720
721
722
723
724 public synchronized void setModel( String modelName ) {
725 if (modelName != null) {
726 modelName = modelName.trim();
727 if (modelName.length() == 0) modelName = null;
728 }
729 if (modelName == null) {
730 model = null;
731 return;
732 }
733 Model model = Models.getModel(modelName);
734 if (model == null) {
735 StringBuilder sb = new StringBuilder();
736 boolean first = true;
737 for (Model existing : Models.ALL) {
738 if (!first) {
739 first = false;
740 sb.append(", ");
741 }
742 sb.append('"').append(existing.getName()).append('"');
743 }
744 String modelNames = sb.toString();
745 throw new IllegalArgumentException(JpaConnectorI18n.unknownModelName.text(model, modelNames));
746 }
747 this.model = model;
748 this.modelName = modelName;
749 }
750
751
752
753
754 public long getLargeValueSizeInBytes() {
755 return largeValueSizeInBytes;
756 }
757
758
759
760
761 public void setLargeValueSizeInBytes( long largeValueSizeInBytes ) {
762 if (largeValueSizeInBytes < 0) largeValueSizeInBytes = DEFAULT_LARGE_VALUE_SIZE_IN_BYTES;
763 this.largeValueSizeInBytes = largeValueSizeInBytes;
764 }
765
766
767
768
769 public boolean isCompressData() {
770 return compressData;
771 }
772
773
774
775
776 public void setCompressData( boolean compressData ) {
777 this.compressData = compressData;
778 }
779
780
781
782
783 public boolean isReferentialIntegrityEnforced() {
784 return referentialIntegrityEnforced;
785 }
786
787
788
789
790 public void setReferentialIntegrityEnforced( boolean referentialIntegrityEnforced ) {
791 this.referentialIntegrityEnforced = referentialIntegrityEnforced;
792 }
793
794
795
796
797
798
799 public void initialize( RepositoryContext context ) throws RepositorySourceException {
800 this.repositoryContext = context;
801 }
802
803
804
805
806
807
808 public Reference getReference() {
809 String className = getClass().getName();
810 String factoryClassName = this.getClass().getName();
811 Reference ref = new Reference(className, factoryClassName, null);
812
813 ref.add(new StringRefAddr(SOURCE_NAME, getName()));
814 ref.add(new StringRefAddr(ROOT_NODE_UUID, getRootNodeUuid()));
815 ref.add(new StringRefAddr(DATA_SOURCE_JNDI_NAME, getDataSourceJndiName()));
816 ref.add(new StringRefAddr(DIALECT, getDialect()));
817 ref.add(new StringRefAddr(USERNAME, getUsername()));
818 ref.add(new StringRefAddr(PASSWORD, getPassword()));
819 ref.add(new StringRefAddr(URL, getUrl()));
820 ref.add(new StringRefAddr(DRIVER_CLASS_NAME, getDriverClassName()));
821 ref.add(new StringRefAddr(DRIVER_CLASSLOADER_NAME, getDriverClassloaderName()));
822 ref.add(new StringRefAddr(MAXIMUM_CONNECTIONS_IN_POOL, Integer.toString(getMaximumConnectionsInPool())));
823 ref.add(new StringRefAddr(MINIMUM_CONNECTIONS_IN_POOL, Integer.toString(getMinimumConnectionsInPool())));
824 ref.add(new StringRefAddr(MAXIMUM_CONNECTION_IDLE_TIME_IN_SECONDS,
825 Integer.toString(getMaximumConnectionIdleTimeInSeconds())));
826 ref.add(new StringRefAddr(MAXIMUM_SIZE_OF_STATEMENT_CACHE, Integer.toString(getMaximumSizeOfStatementCache())));
827 ref.add(new StringRefAddr(NUMBER_OF_CONNECTIONS_TO_BE_ACQUIRED_AS_NEEDED,
828 Integer.toString(getNumberOfConnectionsToAcquireAsNeeded())));
829 ref.add(new StringRefAddr(IDLE_TIME_IN_SECONDS_BEFORE_TESTING_CONNECTIONS,
830 Integer.toString(getIdleTimeInSecondsBeforeTestingConnections())));
831 ref.add(new StringRefAddr(CACHE_TIME_TO_LIVE_IN_MILLISECONDS, Integer.toString(getCacheTimeToLiveInMilliseconds())));
832 ref.add(new StringRefAddr(LARGE_VALUE_SIZE_IN_BYTES, Long.toString(getLargeValueSizeInBytes())));
833 ref.add(new StringRefAddr(COMPRESS_DATA, Boolean.toString(isCompressData())));
834 ref.add(new StringRefAddr(ENFORCE_REFERENTIAL_INTEGRITY, Boolean.toString(isReferentialIntegrityEnforced())));
835 ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getDefaultWorkspaceName()));
836 ref.add(new StringRefAddr(ALLOW_CREATING_WORKSPACES, Boolean.toString(isCreatingWorkspacesAllowed())));
837 ref.add(new StringRefAddr(AUTO_GENERATE_SCHEMA, getAutoGenerateSchema()));
838 String[] workspaceNames = getPredefinedWorkspaceNames();
839 if (workspaceNames != null && workspaceNames.length != 0) {
840 ref.add(new StringRefAddr(PREDEFINED_WORKSPACE_NAMES, StringUtil.combineLines(workspaceNames)));
841 }
842 if (getModel() != null) {
843 ref.add(new StringRefAddr(MODEL_NAME, getModel()));
844 }
845 ref.add(new StringRefAddr(RETRY_LIMIT, Integer.toString(getRetryLimit())));
846 return ref;
847 }
848
849
850
851
852
853
854 public RepositoryContext getRepositoryContext() {
855 return repositoryContext;
856 }
857
858
859
860
861 public Object getObjectInstance( Object obj,
862 javax.naming.Name name,
863 Context nameCtx,
864 Hashtable<?, ?> environment ) throws Exception {
865 if (obj instanceof Reference) {
866 Map<String, String> values = new HashMap<String, String>();
867 Reference ref = (Reference)obj;
868 Enumeration<?> en = ref.getAll();
869 while (en.hasMoreElements()) {
870 RefAddr subref = (RefAddr)en.nextElement();
871 if (subref instanceof StringRefAddr) {
872 String key = subref.getType();
873 Object value = subref.getContent();
874 if (value != null) values.put(key, value.toString());
875 }
876 }
877 String sourceName = values.get(SOURCE_NAME);
878 String rootNodeUuid = values.get(ROOT_NODE_UUID);
879 String dataSourceJndiName = values.get(DATA_SOURCE_JNDI_NAME);
880 String dialect = values.get(DIALECT);
881 String username = values.get(USERNAME);
882 String password = values.get(PASSWORD);
883 String url = values.get(URL);
884 String driverClassName = values.get(DRIVER_CLASS_NAME);
885 String driverClassloaderName = values.get(DRIVER_CLASSLOADER_NAME);
886 String maxConnectionsInPool = values.get(MAXIMUM_CONNECTIONS_IN_POOL);
887 String minConnectionsInPool = values.get(MINIMUM_CONNECTIONS_IN_POOL);
888 String maxConnectionIdleTimeInSec = values.get(MAXIMUM_CONNECTION_IDLE_TIME_IN_SECONDS);
889 String maxSizeOfStatementCache = values.get(MAXIMUM_SIZE_OF_STATEMENT_CACHE);
890 String acquisitionIncrement = values.get(NUMBER_OF_CONNECTIONS_TO_BE_ACQUIRED_AS_NEEDED);
891 String idleTimeInSeconds = values.get(IDLE_TIME_IN_SECONDS_BEFORE_TESTING_CONNECTIONS);
892 String cacheTtlInMillis = values.get(CACHE_TIME_TO_LIVE_IN_MILLISECONDS);
893 String modelName = values.get(MODEL_NAME);
894 String retryLimit = values.get(RETRY_LIMIT);
895 String largeModelSize = values.get(LARGE_VALUE_SIZE_IN_BYTES);
896 String compressData = values.get(COMPRESS_DATA);
897 String refIntegrity = values.get(ENFORCE_REFERENTIAL_INTEGRITY);
898 String defaultWorkspace = values.get(DEFAULT_WORKSPACE);
899 String createWorkspaces = values.get(ALLOW_CREATING_WORKSPACES);
900 String autoGenerateSchema = values.get(AUTO_GENERATE_SCHEMA);
901
902 String combinedWorkspaceNames = values.get(PREDEFINED_WORKSPACE_NAMES);
903 String[] workspaceNames = null;
904 if (combinedWorkspaceNames != null) {
905 List<String> paths = StringUtil.splitLines(combinedWorkspaceNames);
906 workspaceNames = paths.toArray(new String[paths.size()]);
907 }
908
909
910 JpaSource source = new JpaSource();
911 if (sourceName != null) source.setName(sourceName);
912 if (rootNodeUuid != null) source.setRootNodeUuid(rootNodeUuid);
913 if (dataSourceJndiName != null) source.setDataSourceJndiName(dataSourceJndiName);
914 if (dialect != null) source.setDialect(dialect);
915 if (username != null) source.setUsername(username);
916 if (password != null) source.setPassword(password);
917 if (url != null) source.setUrl(url);
918 if (driverClassName != null) source.setDriverClassName(driverClassName);
919 if (driverClassloaderName != null) source.setDriverClassloaderName(driverClassloaderName);
920 if (maxConnectionsInPool != null) source.setMaximumConnectionsInPool(Integer.parseInt(maxConnectionsInPool));
921 if (minConnectionsInPool != null) source.setMinimumConnectionsInPool(Integer.parseInt(minConnectionsInPool));
922 if (maxConnectionIdleTimeInSec != null) source.setMaximumConnectionIdleTimeInSeconds(Integer.parseInt(maxConnectionIdleTimeInSec));
923 if (maxSizeOfStatementCache != null) source.setMaximumSizeOfStatementCache(Integer.parseInt(maxSizeOfStatementCache));
924 if (acquisitionIncrement != null) source.setNumberOfConnectionsToAcquireAsNeeded(Integer.parseInt(acquisitionIncrement));
925 if (idleTimeInSeconds != null) source.setIdleTimeInSecondsBeforeTestingConnections(Integer.parseInt(idleTimeInSeconds));
926 if (cacheTtlInMillis != null) source.setCacheTimeToLiveInMilliseconds(Integer.parseInt(cacheTtlInMillis));
927 if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit));
928 if (modelName != null) source.setModel(modelName);
929 if (largeModelSize != null) source.setLargeValueSizeInBytes(Long.parseLong(largeModelSize));
930 if (compressData != null) source.setCompressData(Boolean.parseBoolean(compressData));
931 if (refIntegrity != null) source.setReferentialIntegrityEnforced(Boolean.parseBoolean(refIntegrity));
932 if (defaultWorkspace != null) source.setDefaultWorkspaceName(defaultWorkspace);
933 if (createWorkspaces != null) source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces));
934 if (workspaceNames != null && workspaceNames.length != 0) source.setPredefinedWorkspaceNames(workspaceNames);
935 if (autoGenerateSchema != null) source.setAutoGenerateSchema(autoGenerateSchema);
936 return source;
937 }
938 return null;
939 }
940
941
942
943
944
945
946 public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
947 if (this.name == null || this.name.trim().length() == 0) {
948 throw new RepositorySourceException(JpaConnectorI18n.repositorySourceMustHaveName.text());
949 }
950 assert rootNodeUuid != null;
951 assert rootUuid != null;
952 if (entityManagers == null) {
953
954 Ejb3Configuration configurator = new Ejb3Configuration();
955
956
957 configurator.addAnnotatedClass(StoreOptionEntity.class);
958
959
960 configure(configurator);
961
962
963 if (this.dataSource == null && this.dataSourceJndiName != null) {
964
965 try {
966 Context context = new InitialContext();
967 dataSource = (DataSource)context.lookup(this.dataSourceJndiName);
968 } catch (Throwable t) {
969 Logger.getLogger(getClass())
970 .error(t, JpaConnectorI18n.errorFindingDataSourceInJndi, name, dataSourceJndiName);
971 }
972 }
973
974 if (this.dataSource != null) {
975
976 configurator.setDataSource(this.dataSource);
977 } else {
978
979 if (this.repositoryContext != null && this.driverClassloaderName != null) {
980 try {
981 ExecutionContext context = this.repositoryContext.getExecutionContext();
982 ClassLoader loader = context.getClassLoader(this.driverClassloaderName);
983 if (loader != null) {
984 Thread.currentThread().setContextClassLoader(loader);
985 }
986 } catch (Throwable t) {
987 I18n msg = JpaConnectorI18n.errorSettingContextClassLoader;
988 Logger.getLogger(getClass()).error(t, msg, name, driverClassloaderName);
989 }
990 }
991
992 setProperty(configurator, "hibernate.dialect", this.dialect);
993 setProperty(configurator, "hibernate.connection.driver_class", this.driverClassName);
994 setProperty(configurator, "hibernate.connection.username", this.username);
995 setProperty(configurator, "hibernate.connection.password", this.password);
996 setProperty(configurator, "hibernate.connection.url", this.url);
997 setProperty(configurator, "hibernate.connection.max_fetch_depth", DEFAULT_MAXIMUM_FETCH_DEPTH);
998 setProperty(configurator, "hibernate.connection.pool_size", 0);
999 setProperty(configurator, "hibernate.show_sql", String.valueOf(this.showSql));
1000 }
1001
1002 Logger logger = getLogger();
1003 if (logger.isDebugEnabled()) {
1004 logger.debug("Properties for Hibernate configuration used for ModeShape JPA Source {0}:", getName());
1005 Properties props = configurator.getProperties();
1006 for (Map.Entry<Object, Object> entry : props.entrySet()) {
1007 String propName = entry.getKey().toString();
1008 if (propName.startsWith("hibernate")) {
1009 logger.debug(" {0} = {1}", propName, entry.getValue());
1010 }
1011 }
1012 }
1013
1014 EntityManagerFactory entityManagerFactory = configurator.buildEntityManagerFactory();
1015 try {
1016
1017 EntityManager entityManager = entityManagerFactory.createEntityManager();
1018 try {
1019
1020
1021 StoreOptions options = new StoreOptions(entityManager);
1022 UUID actualUuid = options.getRootNodeUuid();
1023 if (actualUuid != null) {
1024 this.setRootNodeUuid(actualUuid.toString());
1025 } else {
1026 options.setRootNodeUuid(this.rootUuid);
1027 }
1028
1029
1030 String actualModelName = options.getModelName();
1031 if (actualModelName == null) {
1032
1033 if (model == null) setModel(Models.DEFAULT.getName());
1034 assert model != null;
1035 options.setModelName(model);
1036 } else {
1037
1038 try {
1039 setModel(actualModelName);
1040 } catch (Throwable e) {
1041
1042 String msg = JpaConnectorI18n.existingStoreSpecifiesUnknownModel.text(name, actualModelName);
1043 throw new RepositorySourceException(msg);
1044 }
1045 }
1046 } finally {
1047 entityManager.close();
1048 }
1049 } finally {
1050 entityManagerFactory.close();
1051 }
1052
1053
1054 model.configure(configurator);
1055
1056
1057 entityManagers = new EntityManagers(configurator);
1058 }
1059
1060 return model.createConnection(this);
1061 }
1062
1063
1064
1065
1066
1067
1068 public synchronized void close() {
1069 if (entityManagers != null) {
1070 try {
1071
1072
1073 entityManagers.close();
1074 } finally {
1075 entityManagers = null;
1076 }
1077 }
1078 }
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 protected void configure( Ejb3Configuration configuration ) {
1091
1092 setProperty(configuration, "hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
1093 setProperty(configuration, "hibernate.c3p0.max_size", this.maximumConnectionsInPool);
1094 setProperty(configuration, "hibernate.c3p0.min_size", this.minimumConnectionsInPool);
1095 setProperty(configuration, "hibernate.c3p0.timeout", this.maximumConnectionIdleTimeInSeconds);
1096 setProperty(configuration, "hibernate.c3p0.max_statements", this.maximumSizeOfStatementCache);
1097 setProperty(configuration, "hibernate.c3p0.idle_test_period", this.idleTimeInSecondsBeforeTestingConnections);
1098 setProperty(configuration, "hibernate.c3p0.acquire_increment", this.numberOfConnectionsToAcquireAsNeeded);
1099 setProperty(configuration, "hibernate.c3p0.validate", "false");
1100
1101
1102 setProperty(configuration, "hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider");
1103
1104
1105
1106 setProperty(configuration, "hibernate.format_sql", "true");
1107 setProperty(configuration, "hibernate.use_sql_comments", "true");
1108 setProperty(configuration, "hibernate.hbm2ddl.auto", this.autoGenerateSchema);
1109 }
1110
1111 protected void setProperty( Ejb3Configuration configurator,
1112 String propertyName,
1113 String propertyValue ) {
1114 assert configurator != null;
1115 assert propertyName != null;
1116 assert propertyName.trim().length() != 0;
1117 if (propertyValue != null) {
1118 configurator.setProperty(propertyName, propertyValue.trim());
1119 }
1120 }
1121
1122 protected void setProperty( Ejb3Configuration configurator,
1123 String propertyName,
1124 int propertyValue ) {
1125 assert configurator != null;
1126 assert propertyName != null;
1127 assert propertyName.trim().length() != 0;
1128 configurator.setProperty(propertyName, Integer.toString(propertyValue));
1129 }
1130
1131 @Immutable
1132
1133 private static final long serialVersionUID = 1L;
1134 private final int ttl;
1135
1136
1137 this.ttl = ttl;
1138 }
1139
1140 public long getTimeToLive() {
1141 return ttl;
1142 }
1143
1144 }
1145
1146 }