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.meta.jdbc;
25
26 import java.sql.Connection;
27 import java.sql.DatabaseMetaData;
28 import java.sql.SQLException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.UUID;
39 import net.jcip.annotations.ThreadSafe;
40 import org.modeshape.common.util.Logger;
41 import org.modeshape.graph.ModeShapeLexicon;
42 import org.modeshape.graph.ExecutionContext;
43 import org.modeshape.graph.JcrLexicon;
44 import org.modeshape.graph.JcrNtLexicon;
45 import org.modeshape.graph.connector.LockFailedException;
46 import org.modeshape.graph.connector.RepositorySourceException;
47 import org.modeshape.graph.connector.path.DefaultPathNode;
48 import org.modeshape.graph.connector.path.PathNode;
49 import org.modeshape.graph.connector.path.PathRepository;
50 import org.modeshape.graph.connector.path.PathWorkspace;
51 import org.modeshape.graph.connector.path.cache.WorkspaceCache;
52 import org.modeshape.graph.property.Name;
53 import org.modeshape.graph.property.NameFactory;
54 import org.modeshape.graph.property.Path;
55 import org.modeshape.graph.property.PathFactory;
56 import org.modeshape.graph.property.PathNotFoundException;
57 import org.modeshape.graph.property.Property;
58 import org.modeshape.graph.property.PropertyFactory;
59 import org.modeshape.graph.property.Path.Segment;
60 import org.modeshape.graph.query.QueryResults;
61 import org.modeshape.graph.request.AccessQueryRequest;
62 import org.modeshape.graph.request.LockBranchRequest.LockScope;
63
64 @ThreadSafe
65 public class JdbcMetadataRepository extends PathRepository {
66
67 public final static String TABLES_SEGMENT_NAME = "tables";
68 public final static String PROCEDURES_SEGMENT_NAME = "procedures";
69
70 private static final Logger LOGGER = Logger.getLogger(JdbcMetadataRepository.class);
71 private final JdbcMetadataSource source;
72 private Map<Name, Property> rootNodeProperties;
73 private String databaseProductName;
74 private String databaseProductVersion;
75 private int databaseMajorVersion;
76 private int databaseMinorVersion;
77
78 public JdbcMetadataRepository( JdbcMetadataSource source ) {
79 super(source);
80 this.source = source;
81 initialize();
82 }
83
84 @Override
85 protected synchronized void initialize() {
86 if (!this.workspaces.isEmpty()) return;
87
88 String defaultWorkspaceName = getDefaultWorkspaceName();
89 this.workspaces.put(defaultWorkspaceName, new JdbcMetadataWorkspace(defaultWorkspaceName));
90
91 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
92 PropertyFactory propFactory = context.getPropertyFactory();
93 this.rootNodeProperties = new HashMap<Name, Property>();
94
95 Connection conn = getConnection();
96 try {
97 Name propName;
98 DatabaseMetaData dmd = conn.getMetaData();
99
100 databaseProductName = dmd.getDatabaseProductName();
101 databaseProductVersion = dmd.getDatabaseProductVersion();
102 databaseMajorVersion = dmd.getDatabaseMajorVersion();
103 databaseMinorVersion = dmd.getDatabaseMinorVersion();
104
105 propName = JdbcMetadataLexicon.DATABASE_PRODUCT_NAME;
106 rootNodeProperties.put(propName, propFactory.create(propName, databaseProductName));
107 propName = JdbcMetadataLexicon.DATABASE_PRODUCT_VERSION;
108 rootNodeProperties.put(propName, propFactory.create(propName, databaseProductVersion));
109 propName = JdbcMetadataLexicon.DATABASE_MAJOR_VERSION;
110 rootNodeProperties.put(propName, propFactory.create(propName, databaseMajorVersion));
111 propName = JdbcMetadataLexicon.DATABASE_MINOR_VERSION;
112 rootNodeProperties.put(propName, propFactory.create(propName, databaseMinorVersion));
113
114 rootNodeProperties.put(JcrLexicon.PRIMARY_TYPE, propFactory.create(JcrLexicon.PRIMARY_TYPE, ModeShapeLexicon.ROOT));
115 rootNodeProperties.put(JcrLexicon.MIXIN_TYPES, propFactory.create(JcrLexicon.MIXIN_TYPES,
116 JdbcMetadataLexicon.DATABASE_ROOT));
117
118 rootNodeProperties = Collections.unmodifiableMap(rootNodeProperties);
119 } catch (SQLException se) {
120 throw new IllegalStateException(JdbcMetadataI18n.couldNotGetDatabaseMetadata.text(), se);
121 } finally {
122 closeConnection(conn);
123 }
124 }
125
126 public WorkspaceCache getCache( String workspaceName ) {
127 return source.getPathRepositoryCache().getCache(workspaceName);
128 }
129
130 Connection getConnection() {
131 try {
132 return source.getDataSource().getConnection();
133 } catch (SQLException se) {
134 throw new IllegalStateException(JdbcMetadataI18n.errorObtainingConnection.text(), se);
135 }
136 }
137
138 void closeConnection( Connection connection ) {
139 assert connection != null;
140 try {
141 connection.close();
142 } catch (SQLException se) {
143 LOGGER.error(se, JdbcMetadataI18n.errorClosingConnection);
144 }
145 }
146
147 @ThreadSafe
148 @SuppressWarnings( "synthetic-access" )
149 private class JdbcMetadataWorkspace implements PathWorkspace {
150
151 private final String name;
152 private final WorkspaceCache cache;
153
154 JdbcMetadataWorkspace( String name ) {
155 this.name = name;
156 cache = getCache(name);
157 }
158
159 public Path getLowestExistingPath( Path path ) {
160 PathFactory pathFactory = source.getRepositoryContext().getExecutionContext().getValueFactories().getPathFactory();
161
162 Path lastWorkingPath = pathFactory.createRootPath();
163
164 for (Segment segment : path.getSegmentsList()) {
165 Path newPathToTry = pathFactory.create(lastWorkingPath, segment);
166
167 try {
168 getNode(newPathToTry);
169 lastWorkingPath = newPathToTry;
170 } catch (PathNotFoundException pnfe) {
171 return lastWorkingPath;
172 }
173 }
174
175
176 return path;
177 }
178
179 public String getName() {
180 return this.name;
181 }
182
183 public PathNode getNode( Path path ) {
184 assert path != null;
185
186 PathNode node = cache.get(path);
187 if (node != null) return node;
188
189 List<Segment> segments = path.getSegmentsList();
190 switch (segments.size()) {
191 case 0:
192 node = getRoot();
193 break;
194 case 1:
195 node = catalogNodeFor(segments);
196 break;
197 case 2:
198 node = schemaNodeFor(segments);
199 break;
200 case 3:
201 if (TABLES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName())) {
202 node = tablesNodeFor(segments);
203 } else if (PROCEDURES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName())) {
204 node = proceduresNodeFor(segments);
205 }
206 break;
207 case 4:
208 if (TABLES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName())) {
209 node = tableNodeFor(segments);
210 } else if (PROCEDURES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName())) {
211 node = procedureNodeFor(segments);
212 }
213 break;
214 case 5:
215 if (TABLES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName())) {
216 node = columnNodeFor(segments);
217 }
218 break;
219 default:
220 return null;
221 }
222
223 if (node != null) cache.set(node);
224 return node;
225 }
226
227 private PathNode catalogNodeFor( List<Segment> segments ) throws RepositorySourceException {
228 assert segments != null;
229 assert segments.size() == 1;
230
231 List<Segment> schemaNames = new LinkedList<Segment>();
232 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
233 PathFactory pathFactory = context.getValueFactories().getPathFactory();
234 PropertyFactory propFactory = context.getPropertyFactory();
235
236 Path nodePath = pathFactory.createAbsolutePath(segments);
237
238 Connection conn = getConnection();
239 String catalogName = segments.get(0).getName().getLocalName();
240
241 try {
242 MetadataCollector meta = source.getMetadataCollector();
243 if (catalogName.equals(source.getDefaultCatalogName())) catalogName = null;
244
245
246 List<String> catalogNames = meta.getCatalogNames(conn);
247
248
249
250
251
252
253
254
255
256 boolean catalogMatchesDefaultName = catalogNames.isEmpty() || catalogNames.contains("");
257
258 if ((catalogName != null && !catalogNames.contains(catalogName))
259 || (catalogName == null && !catalogMatchesDefaultName)) {
260 return null;
261 }
262
263 List<String> schemaNamesFromMeta = new ArrayList<String>(meta.getSchemaNames(conn, catalogName));
264
265 for (String schemaName : schemaNamesFromMeta) {
266 if (schemaName.length() > 0) {
267 schemaNames.add(pathFactory.createSegment(schemaName));
268 }
269 }
270
271 if (schemaNames.isEmpty()) {
272 schemaNames.add(pathFactory.createSegment(source.getDefaultSchemaName()));
273 }
274
275 Map<Name, Property> properties = new HashMap<Name, Property>();
276 properties.put(JcrLexicon.PRIMARY_TYPE, propFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.UNSTRUCTURED));
277 properties.put(JcrLexicon.MIXIN_TYPES, propFactory.create(JcrLexicon.MIXIN_TYPES, JdbcMetadataLexicon.CATALOG));
278
279 return new DefaultPathNode(nodePath, null, properties, schemaNames);
280 } catch (JdbcMetadataException se) {
281 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetSchemaNames.text(catalogName), se);
282 } finally {
283 closeConnection(conn);
284 }
285 }
286
287 private PathNode schemaNodeFor( List<Segment> segments ) throws RepositorySourceException {
288 assert segments != null;
289 assert segments.size() == 2;
290
291 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
292 PathFactory pathFactory = context.getValueFactories().getPathFactory();
293 PropertyFactory propFactory = context.getPropertyFactory();
294
295 Path nodePath = pathFactory.createAbsolutePath(segments);
296
297 Connection conn = getConnection();
298 String catalogName = segments.get(0).getName().getLocalName();
299 if (catalogName.equals(source.getDefaultCatalogName())) catalogName = null;
300
301 String schemaName = segments.get(1).getName().getLocalName();
302 if (schemaName.equals(source.getDefaultSchemaName())) schemaName = null;
303
304 try {
305 MetadataCollector meta = source.getMetadataCollector();
306
307
308 List<String> schemaNames = meta.getSchemaNames(conn, catalogName);
309
310
311
312
313
314
315 if ((schemaName != null && !schemaNames.contains(schemaName)) || (schemaName == null && !schemaNames.isEmpty())) {
316 return null;
317 }
318
319 Map<Name, Property> properties = new HashMap<Name, Property>();
320 properties.put(JcrLexicon.PRIMARY_TYPE, propFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.UNSTRUCTURED));
321 properties.put(JcrLexicon.MIXIN_TYPES, propFactory.create(JcrLexicon.MIXIN_TYPES, JdbcMetadataLexicon.SCHEMA));
322
323 Segment[] children = new Segment[] {pathFactory.createSegment(TABLES_SEGMENT_NAME),
324 pathFactory.createSegment(PROCEDURES_SEGMENT_NAME)};
325
326 return new DefaultPathNode(nodePath, null, properties, Arrays.asList(children));
327 } catch (JdbcMetadataException se) {
328 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetSchemaNames.text(catalogName), se);
329 } finally {
330 closeConnection(conn);
331 }
332 }
333
334 private PathNode tablesNodeFor( List<Segment> segments ) throws RepositorySourceException {
335 assert segments != null;
336 assert segments.size() == 3;
337 assert TABLES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName());
338
339 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
340 PathFactory pathFactory = context.getValueFactories().getPathFactory();
341 PropertyFactory propFactory = context.getPropertyFactory();
342
343 Path nodePath = pathFactory.createAbsolutePath(segments);
344
345 Connection conn = getConnection();
346 String catalogName = segments.get(0).getName().getLocalName();
347 if (catalogName.equals(source.getDefaultCatalogName())) catalogName = null;
348
349 String schemaName = segments.get(1).getName().getLocalName();
350 if (schemaName.equals(source.getDefaultSchemaName())) schemaName = null;
351
352 try {
353 MetadataCollector meta = source.getMetadataCollector();
354
355
356 List<String> schemaNames = meta.getSchemaNames(conn, catalogName);
357
358
359
360
361
362
363 if ((schemaName != null && !schemaNames.contains(schemaName)) || (schemaName == null && !schemaNames.isEmpty())) {
364 return null;
365 }
366
367 Map<Name, Property> properties = new HashMap<Name, Property>();
368 properties.put(JcrLexicon.PRIMARY_TYPE, propFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.UNSTRUCTURED));
369 properties.put(JcrLexicon.MIXIN_TYPES, propFactory.create(JcrLexicon.MIXIN_TYPES, JdbcMetadataLexicon.TABLES));
370
371 List<TableMetadata> tables = meta.getTables(conn, catalogName, schemaName, null);
372 List<Segment> children = new ArrayList<Segment>(tables.size());
373
374 for (TableMetadata table : tables) {
375 children.add(pathFactory.createSegment(table.getName()));
376 }
377
378 return new DefaultPathNode(nodePath, null, properties, children);
379 } catch (JdbcMetadataException se) {
380 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetTableNames.text(catalogName, schemaName), se);
381 } finally {
382 closeConnection(conn);
383 }
384 }
385
386 private PathNode tableNodeFor( List<Segment> segments ) throws RepositorySourceException {
387 assert segments != null;
388 assert segments.size() == 4;
389 assert TABLES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName());
390
391 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
392 PathFactory pathFactory = context.getValueFactories().getPathFactory();
393 PropertyFactory propFactory = context.getPropertyFactory();
394
395 Path nodePath = pathFactory.createAbsolutePath(segments);
396
397 Connection conn = getConnection();
398 String catalogName = segments.get(0).getName().getLocalName();
399 if (catalogName.equals(source.getDefaultCatalogName())) catalogName = null;
400
401 String schemaName = segments.get(1).getName().getLocalName();
402 if (schemaName.equals(source.getDefaultSchemaName())) schemaName = null;
403
404 String tableName = segments.get(3).getName().getLocalName();
405
406 try {
407 MetadataCollector meta = source.getMetadataCollector();
408
409 List<TableMetadata> tables = meta.getTables(conn, catalogName, schemaName, tableName);
410
411
412 if (tables.isEmpty()) {
413 return null;
414 }
415 assert tables.size() == 1;
416 TableMetadata table = tables.get(0);
417
418 Map<Name, Property> properties = new HashMap<Name, Property>();
419 Name propName;
420 propName = JcrLexicon.PRIMARY_TYPE;
421 properties.put(propName, propFactory.create(propName, JcrNtLexicon.UNSTRUCTURED));
422 propName = JcrLexicon.MIXIN_TYPES;
423 properties.put(propName, propFactory.create(propName, JdbcMetadataLexicon.TABLE));
424
425 if (table.getType() != null) {
426 propName = JdbcMetadataLexicon.TABLE_TYPE;
427 properties.put(propName, propFactory.create(propName, table.getType()));
428 }
429 if (table.getDescription() != null) {
430 propName = JdbcMetadataLexicon.DESCRIPTION;
431 properties.put(propName, propFactory.create(propName, table.getDescription()));
432 }
433 if (table.getTypeCatalogName() != null) {
434 propName = JdbcMetadataLexicon.TYPE_CATALOG_NAME;
435 properties.put(propName, propFactory.create(propName, table.getTypeCatalogName()));
436 }
437 if (table.getTypeSchemaName() != null) {
438 propName = JdbcMetadataLexicon.TYPE_SCHEMA_NAME;
439 properties.put(propName, propFactory.create(propName, table.getTypeSchemaName()));
440 }
441 if (table.getTypeName() != null) {
442 propName = JdbcMetadataLexicon.TYPE_NAME;
443 properties.put(propName, propFactory.create(propName, table.getTypeName()));
444 }
445 if (table.getSelfReferencingColumnName() != null) {
446 propName = JdbcMetadataLexicon.SELF_REFERENCING_COLUMN_NAME;
447 properties.put(propName, propFactory.create(propName, table.getSelfReferencingColumnName()));
448 }
449 if (table.getReferenceGenerationStrategyName() != null) {
450 propName = JdbcMetadataLexicon.REFERENCE_GENERATION_STRATEGY_NAME;
451 properties.put(propName, propFactory.create(propName, table.getReferenceGenerationStrategyName()));
452 }
453
454 List<ColumnMetadata> columns = meta.getColumns(conn, catalogName, schemaName, tableName, null);
455 List<Segment> children = new ArrayList<Segment>(columns.size());
456
457 for (ColumnMetadata column : columns) {
458 children.add(pathFactory.createSegment(column.getName()));
459 }
460
461 return new DefaultPathNode(nodePath, null, properties, children);
462 } catch (JdbcMetadataException se) {
463 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetTable.text(catalogName, schemaName, tableName),
464 se);
465 } finally {
466 closeConnection(conn);
467 }
468 }
469
470 private PathNode proceduresNodeFor( List<Segment> segments ) throws RepositorySourceException {
471 assert segments != null;
472 assert segments.size() == 3;
473 assert PROCEDURES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName());
474
475 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
476 PathFactory pathFactory = context.getValueFactories().getPathFactory();
477 PropertyFactory propFactory = context.getPropertyFactory();
478
479 Path nodePath = pathFactory.createAbsolutePath(segments);
480
481 Connection conn = getConnection();
482 String catalogName = segments.get(0).getName().getLocalName();
483 if (catalogName.equals(source.getDefaultCatalogName())) catalogName = null;
484
485 String schemaName = segments.get(1).getName().getLocalName();
486 if (schemaName.equals(source.getDefaultSchemaName())) schemaName = null;
487
488 try {
489 MetadataCollector meta = source.getMetadataCollector();
490
491
492 List<String> schemaNames = meta.getSchemaNames(conn, catalogName);
493
494
495
496
497
498
499 if ((schemaName != null && !schemaNames.contains(schemaName)) || (schemaName == null && !schemaNames.isEmpty())) {
500 return null;
501 }
502
503 Map<Name, Property> properties = new HashMap<Name, Property>();
504 properties.put(JcrLexicon.PRIMARY_TYPE, propFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.UNSTRUCTURED));
505 properties.put(JcrLexicon.MIXIN_TYPES, propFactory.create(JcrLexicon.MIXIN_TYPES, JdbcMetadataLexicon.PROCEDURES));
506
507 List<ProcedureMetadata> procedures = meta.getProcedures(conn, catalogName, schemaName, null);
508 List<Segment> children = new ArrayList<Segment>(procedures.size());
509
510 for (ProcedureMetadata procedure : procedures) {
511 children.add(pathFactory.createSegment(procedure.getName()));
512 }
513
514 return new DefaultPathNode(nodePath, null, properties, children);
515 } catch (JdbcMetadataException se) {
516 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetProcedureNames.text(catalogName, schemaName), se);
517 } finally {
518 closeConnection(conn);
519 }
520 }
521
522 private PathNode procedureNodeFor( List<Segment> segments ) throws RepositorySourceException {
523 assert segments != null;
524 assert segments.size() == 4;
525 assert PROCEDURES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName());
526
527 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
528 PathFactory pathFactory = context.getValueFactories().getPathFactory();
529 PropertyFactory propFactory = context.getPropertyFactory();
530
531 Path nodePath = pathFactory.createAbsolutePath(segments);
532
533 Connection conn = getConnection();
534 String catalogName = segments.get(0).getName().getLocalName();
535 if (catalogName.equals(source.getDefaultCatalogName())) catalogName = null;
536
537 String schemaName = segments.get(1).getName().getLocalName();
538 if (schemaName.equals(source.getDefaultSchemaName())) schemaName = null;
539
540 String procedureName = segments.get(3).getName().getLocalName();
541
542 try {
543 MetadataCollector meta = source.getMetadataCollector();
544
545 List<ProcedureMetadata> procedures = meta.getProcedures(conn, catalogName, schemaName, procedureName);
546
547
548 if (procedures.isEmpty()) {
549 return null;
550 }
551
552
553
554
555
556
557
558
559
560
561 if (segments.get(3).getIndex() > procedures.size()) {
562 return null;
563 }
564
565 ProcedureMetadata procedure = procedures.get(segments.get(3).getIndex() - 1);
566
567 Map<Name, Property> properties = new HashMap<Name, Property>();
568 Name propName;
569 propName = JcrLexicon.PRIMARY_TYPE;
570 properties.put(propName, propFactory.create(propName, JcrNtLexicon.UNSTRUCTURED));
571 propName = JcrLexicon.MIXIN_TYPES;
572 properties.put(propName, propFactory.create(propName, JdbcMetadataLexicon.PROCEDURE));
573
574 if (procedure.getDescription() != null) {
575 propName = JdbcMetadataLexicon.DESCRIPTION;
576 properties.put(propName, propFactory.create(propName, procedure.getDescription()));
577 }
578 propName = JdbcMetadataLexicon.PROCEDURE_RETURN_TYPE;
579 properties.put(propName, propFactory.create(propName, procedure.getType()));
580
581 return new DefaultPathNode(nodePath, null, properties, Collections.<Segment>emptyList());
582 } catch (JdbcMetadataException se) {
583 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetProcedure.text(catalogName,
584 schemaName,
585 procedureName), se);
586 } finally {
587 closeConnection(conn);
588 }
589 }
590
591 private PathNode columnNodeFor( List<Segment> segments ) throws RepositorySourceException {
592 assert segments != null;
593 assert segments.size() == 5;
594 assert TABLES_SEGMENT_NAME.equals(segments.get(2).getName().getLocalName());
595
596 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
597 PathFactory pathFactory = context.getValueFactories().getPathFactory();
598 PropertyFactory propFactory = context.getPropertyFactory();
599
600 Path nodePath = pathFactory.createAbsolutePath(segments);
601
602 Connection conn = getConnection();
603 String catalogName = segments.get(0).getName().getLocalName();
604 if (catalogName.equals(source.getDefaultCatalogName())) catalogName = null;
605
606 String schemaName = segments.get(1).getName().getLocalName();
607 if (schemaName.equals(source.getDefaultSchemaName())) schemaName = null;
608
609 String tableName = segments.get(3).getName().getLocalName();
610 String columnName = segments.get(4).getName().getLocalName();
611
612 try {
613 MetadataCollector meta = source.getMetadataCollector();
614
615 List<ColumnMetadata> columns = meta.getColumns(conn, catalogName, schemaName, tableName, columnName);
616
617
618 if (columns.isEmpty()) {
619 return null;
620 }
621
622 assert columns.size() == 1 : "Duplicate column named " + columnName;
623 ColumnMetadata column = columns.get(0);
624
625 Map<Name, Property> properties = new HashMap<Name, Property>();
626 Name propName;
627 propName = JcrLexicon.PRIMARY_TYPE;
628 properties.put(propName, propFactory.create(propName, JcrNtLexicon.UNSTRUCTURED));
629 propName = JcrLexicon.MIXIN_TYPES;
630 properties.put(propName, propFactory.create(propName, JdbcMetadataLexicon.COLUMN));
631
632 propName = JdbcMetadataLexicon.JDBC_DATA_TYPE;
633 properties.put(propName, propFactory.create(propName, column.getJdbcDataType()));
634 propName = JdbcMetadataLexicon.TYPE_NAME;
635 properties.put(propName, propFactory.create(propName, column.getTypeName()));
636 propName = JdbcMetadataLexicon.COLUMN_SIZE;
637 properties.put(propName, propFactory.create(propName, column.getColumnSize()));
638 propName = JdbcMetadataLexicon.DECIMAL_DIGITS;
639 properties.put(propName, propFactory.create(propName, column.getDecimalDigits()));
640 propName = JdbcMetadataLexicon.RADIX;
641 properties.put(propName, propFactory.create(propName, column.getRadix()));
642 if (column.getNullable() != null) {
643 propName = JdbcMetadataLexicon.NULLABLE;
644 properties.put(propName, propFactory.create(propName, column.getNullable()));
645 }
646 if (column.getDescription() != null) {
647 propName = JdbcMetadataLexicon.DESCRIPTION;
648 properties.put(propName, propFactory.create(propName, column.getDescription()));
649 }
650 if (column.getDefaultValue() != null) {
651 propName = JdbcMetadataLexicon.DEFAULT_VALUE;
652 properties.put(propName, propFactory.create(propName, column.getDefaultValue()));
653 }
654 propName = JdbcMetadataLexicon.LENGTH;
655 properties.put(propName, propFactory.create(propName, column.getLength()));
656 propName = JdbcMetadataLexicon.ORDINAL_POSITION;
657 properties.put(propName, propFactory.create(propName, column.getOrdinalPosition()));
658 if (column.getScopeCatalogName() != null) {
659 propName = JdbcMetadataLexicon.SCOPE_CATALOG_NAME;
660
661 properties.put(propName, propFactory.create(propName, column.getScopeCatalogName()));
662 }
663 if (column.getScopeSchemaName() != null) {
664 propName = JdbcMetadataLexicon.SCOPE_SCHEMA_NAME;
665 properties.put(propName, propFactory.create(propName, column.getScopeSchemaName()));
666 }
667 if (column.getScopeTableName() != null) {
668 propName = JdbcMetadataLexicon.SCOPE_TABLE_NAME;
669 properties.put(propName, propFactory.create(propName, column.getScopeTableName()));
670 }
671 if (column.getSourceJdbcDataType() != null) {
672 propName = JdbcMetadataLexicon.SOURCE_JDBC_DATA_TYPE;
673 properties.put(propName, propFactory.create(propName, column.getSourceJdbcDataType()));
674 }
675 return new DefaultPathNode(nodePath, null, properties, Collections.<Segment>emptyList());
676 } catch (JdbcMetadataException se) {
677 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetColumn.text(catalogName,
678 schemaName,
679 tableName,
680 columnName), se);
681 } finally {
682 closeConnection(conn);
683 }
684 }
685
686 public PathNode getRoot() throws RepositorySourceException {
687 List<Segment> catalogNames = new LinkedList<Segment>();
688 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
689 PathFactory pathFactory = context.getValueFactories().getPathFactory();
690
691 Connection conn = getConnection();
692 try {
693 MetadataCollector meta = source.getMetadataCollector();
694
695 for (String catalogName : meta.getCatalogNames(conn)) {
696 if (catalogName.length() > 0) {
697 catalogNames.add(pathFactory.createSegment(catalogName));
698 }
699 }
700
701 if (catalogNames.isEmpty()) {
702
703 catalogNames.add(pathFactory.createSegment(source.getDefaultCatalogName()));
704 }
705
706 return new RootNode(catalogNames);
707 } catch (JdbcMetadataException se) {
708 throw new RepositorySourceException(JdbcMetadataI18n.couldNotGetCatalogNames.text(), se);
709 } finally {
710 closeConnection(conn);
711 }
712 }
713
714
715
716
717
718
719
720
721
722 public void lockNode( PathNode node,
723 LockScope lockScope,
724 long lockTimeoutInMillis ) throws LockFailedException {
725
726 }
727
728
729
730
731
732
733 public void unlockNode( PathNode node ) {
734
735 }
736
737
738
739
740
741
742
743 public QueryResults query( ExecutionContext context,
744 AccessQueryRequest accessQuery ) {
745 throw new UnsupportedOperationException();
746 }
747
748
749
750
751
752
753 public QueryResults search( ExecutionContext context,
754 String fullTextSearchExpression ) {
755 return null;
756 }
757 }
758
759 @SuppressWarnings( "synthetic-access" )
760 private class RootNode implements PathNode {
761 private final List<Segment> catalogNames;
762
763 private RootNode( List<Segment> catalogNames ) {
764 this.catalogNames = catalogNames;
765 }
766
767 public List<Segment> getChildSegments() {
768 return catalogNames;
769 }
770
771 public Path getPath() {
772 ExecutionContext context = source.getRepositoryContext().getExecutionContext();
773 return context.getValueFactories().getPathFactory().createRootPath();
774 }
775
776 public UUID getUuid() {
777 return source.getRootNodeUuid();
778 }
779
780 public Map<Name, Property> getProperties() {
781 return rootNodeProperties;
782 }
783
784 public Property getProperty( ExecutionContext context,
785 String name ) {
786 NameFactory nameFactory = context.getValueFactories().getNameFactory();
787 return rootNodeProperties.get(nameFactory.create(name));
788 }
789
790 public Property getProperty( Name name ) {
791 return rootNodeProperties.get(name);
792 }
793
794 public Set<Name> getUniqueChildNames() {
795 Set<Name> childNames = new HashSet<Name>(catalogNames.size());
796
797 for (Segment catalogName : catalogNames) {
798 childNames.add(catalogName.getName());
799 }
800 return childNames;
801 }
802 }
803
804 }