1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.dataConnector;
19
20 import java.io.Serializable;
21 import java.sql.Connection;
22 import java.sql.PreparedStatement;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.sql.Timestamp;
26 import java.sql.Types;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import javax.sql.DataSource;
31
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35
36
37
38
39
40
41
42
43 public class StoredIDStore {
44
45
46 private final Logger log = LoggerFactory.getLogger(StoredIDStore.class);
47
48
49 private DataSource dataSource;
50
51
52 private int queryTimeout;
53
54
55 private final String table = "shibpid";
56
57
58 private final String localEntityColumn = "localEntity";
59
60
61 private final String peerEntityColumn = "peerEntity";
62
63
64 private final String principalNameColumn = "principalName";
65
66
67 private final String localIdColumn = "localId";
68
69
70 private final String persistentIdColumn = "persistentId";
71
72
73 private final String peerProvidedIdColumn = "peerProvidedId";
74
75
76 private final String createTimeColumn = "creationDate";
77
78
79 private final String deactivationTimeColumn = "deactivationDate";
80
81
82 private final String idEntrySelectSQL = "SELECT * FROM " + table + " WHERE ";
83
84
85 private final String deactivateIdSQL = "UPDATE " + table + " SET " + deactivationTimeColumn + "= ? WHERE "
86 + persistentIdColumn + "= ?";
87
88
89
90
91
92
93
94 public StoredIDStore(DataSource source, int timeout) {
95 dataSource = source;
96 queryTimeout = timeout;
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110 public int getNumberOfPersistentIdEntries(String localEntity, String peerEntity, String localId)
111 throws SQLException {
112 StringBuilder sqlBuilder = new StringBuilder();
113 sqlBuilder.append("SELECT");
114 sqlBuilder.append(" count(").append(persistentIdColumn).append(")");
115 sqlBuilder.append(" FROM ").append(table).append(" WHERE ");
116 sqlBuilder.append(localEntityColumn).append(" = ?");
117 sqlBuilder.append(" AND ");
118 sqlBuilder.append(peerEntityColumn).append(" = ?");
119 sqlBuilder.append(" AND ");
120 sqlBuilder.append(localIdColumn).append(" = ?");
121
122 String sql = sqlBuilder.toString();
123 Connection dbConn = dataSource.getConnection();
124 try {
125 log.debug("Selecting number of persistent ID entries based on prepared sql statement: {}", sql);
126 PreparedStatement statement = dbConn.prepareStatement(sql);
127 statement.setQueryTimeout(queryTimeout);
128
129 log.debug("Setting prepared statement parameter {}: {}", 1, localEntity);
130 statement.setString(1, localEntity);
131 log.debug("Setting prepared statement parameter {}: {}", 2, peerEntity);
132 statement.setString(2, peerEntity);
133 log.debug("Setting prepared statement parameter {}: {}", 3, localId);
134 statement.setString(3, localId);
135
136 ResultSet rs = statement.executeQuery();
137 rs.next();
138 return rs.getInt(1);
139 } finally {
140 try {
141 if (dbConn != null && !dbConn.isClosed()) {
142 dbConn.close();
143 }
144 } catch (SQLException e) {
145 log.error("Error closing database connection", e);
146 }
147 }
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161 public List<PersistentIdEntry> getPersistentIdEntries(String localEntity, String peerEntity, String localId)
162 throws SQLException {
163 StringBuilder sqlBuilder = new StringBuilder(idEntrySelectSQL);
164 sqlBuilder.append(localEntityColumn).append(" = ?");
165 sqlBuilder.append(" AND ").append(peerEntityColumn).append(" = ?");
166 sqlBuilder.append(" AND ").append(localIdColumn).append(" = ?");
167 String sql = sqlBuilder.toString();
168
169 log.debug("Selecting all persistent ID entries based on prepared sql statement: {}", sql);
170
171 Connection dbConn = dataSource.getConnection();
172 try {
173 PreparedStatement statement = dbConn.prepareStatement(sql);
174 statement.setQueryTimeout(queryTimeout);
175
176 log.debug("Setting prepared statement parameter {}: {}", 1, localEntity);
177 statement.setString(1, localEntity);
178 log.debug("Setting prepared statement parameter {}: {}", 2, peerEntity);
179 statement.setString(2, peerEntity);
180 log.debug("Setting prepared statement parameter {}: {}", 3, localId);
181 statement.setString(3, localId);
182
183 return buildIdentifierEntries(statement.executeQuery());
184 } finally {
185 try {
186 if (dbConn != null && !dbConn.isClosed()) {
187 dbConn.close();
188 }
189 } catch (SQLException e) {
190 log.error("Error closing database connection", e);
191 }
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204 public PersistentIdEntry getActivePersistentIdEntry(String persistentId) throws SQLException {
205 return getPersistentIdEntry(persistentId, true);
206 }
207
208
209
210
211
212
213
214
215
216
217
218 public PersistentIdEntry getPersistentIdEntry(String persistentId, boolean onlyActiveId) throws SQLException {
219 StringBuilder sqlBuilder = new StringBuilder(idEntrySelectSQL);
220 sqlBuilder.append(persistentIdColumn).append(" = ?");
221 if (onlyActiveId) {
222 sqlBuilder.append(" AND ").append(deactivationTimeColumn).append(" IS NULL");
223 }
224 String sql = sqlBuilder.toString();
225
226 log.debug("Selecting persistent ID entry based on prepared sql statement: {}", sql);
227
228 Connection dbConn = dataSource.getConnection();
229 try {
230 PreparedStatement statement = dbConn.prepareStatement(sql);
231 statement.setQueryTimeout(queryTimeout);
232
233 log.debug("Setting prepared statement parameter {}: {}", 1, persistentId);
234 statement.setString(1, persistentId);
235
236 List<PersistentIdEntry> entries = buildIdentifierEntries(statement.executeQuery());
237
238 if (entries == null || entries.size() == 0) {
239 return null;
240 }
241
242 if (entries.size() > 1) {
243 log.warn("More than one identifier found, only the first will be used");
244 }
245
246 return entries.get(0);
247 } finally {
248 try {
249 if (dbConn != null && !dbConn.isClosed()) {
250 dbConn.close();
251 }
252 } catch (SQLException e) {
253 log.error("Error closing database connection", e);
254 }
255 }
256 }
257
258 public PersistentIdEntry getActivePersistentIdEntry(String localEntity, String peerEntity, String localId,
259 boolean isActive) throws SQLException {
260 StringBuilder sqlBuilder = new StringBuilder(idEntrySelectSQL);
261 sqlBuilder.append(localEntityColumn).append(" = ?");
262 sqlBuilder.append(" AND ").append(peerEntityColumn).append(" = ?");
263 sqlBuilder.append(" AND ").append(localIdColumn).append(" = ?");
264 if(isActive){
265 sqlBuilder.append(" AND ").append(deactivationTimeColumn).append(" IS NULL");
266 }else{
267 sqlBuilder.append(" AND ").append(deactivationTimeColumn).append(" IS NOT NULL");
268 }
269 String sql = sqlBuilder.toString();
270
271 log.debug("Selecting persistent ID entry based on prepared sql statement: {}", sql);
272 Connection dbConn = dataSource.getConnection();
273 try {
274 PreparedStatement statement = dbConn.prepareStatement(sql);
275 statement.setQueryTimeout(queryTimeout);
276
277 log.debug("Setting prepared statement parameter {}: {}", 1, localEntity);
278 statement.setString(1, localEntity);
279 log.debug("Setting prepared statement parameter {}: {}", 2, peerEntity);
280 statement.setString(2, peerEntity);
281 log.debug("Setting prepared statement parameter {}: {}", 3, localId);
282 statement.setString(3, localId);
283
284 log.debug("Getting active persistent Id entries.");
285 List<PersistentIdEntry> entries = buildIdentifierEntries(statement.executeQuery());
286
287 if (entries == null || entries.size() == 0) {
288 return null;
289 }
290
291 if (entries.size() > 1) {
292 log.warn("More than one active identifier, only the first will be used");
293 }
294
295 return entries.get(0);
296 } finally {
297 try {
298 if (dbConn != null && !dbConn.isClosed()) {
299 dbConn.close();
300 }
301 } catch (SQLException e) {
302 log.error("Error closing database connection", e);
303 }
304 }
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318 public PersistentIdEntry getActivePersistentIdEntry(String localEntity, String peerEntity, String localId)
319 throws SQLException {
320 StringBuilder sqlBuilder = new StringBuilder(idEntrySelectSQL);
321 sqlBuilder.append(localEntityColumn).append(" = ?");
322 sqlBuilder.append(" AND ").append(peerEntityColumn).append(" = ?");
323 sqlBuilder.append(" AND ").append(localIdColumn).append(" = ?");
324 sqlBuilder.append(" AND ").append(deactivationTimeColumn).append(" IS NULL");
325 String sql = sqlBuilder.toString();
326
327 log.debug("Selecting active persistent ID entry based on prepared sql statement: {}", sql);
328 Connection dbConn = dataSource.getConnection();
329 try {
330 PreparedStatement statement = dbConn.prepareStatement(sql);
331 statement.setQueryTimeout(queryTimeout);
332
333 log.debug("Setting prepared statement parameter {}: {}", 1, localEntity);
334 statement.setString(1, localEntity);
335 log.debug("Setting prepared statement parameter {}: {}", 2, peerEntity);
336 statement.setString(2, peerEntity);
337 log.debug("Setting prepared statement parameter {}: {}", 3, localId);
338 statement.setString(3, localId);
339
340 log.debug("Getting active persistent Id entries.");
341 List<PersistentIdEntry> entries = buildIdentifierEntries(statement.executeQuery());
342
343 if (entries == null || entries.size() == 0) {
344 return null;
345 }
346
347 if (entries.size() > 1) {
348 log.warn("More than one active identifier, only the first will be used");
349 }
350
351 return entries.get(0);
352 } finally {
353 try {
354 if (dbConn != null && !dbConn.isClosed()) {
355 dbConn.close();
356 }
357 } catch (SQLException e) {
358 log.error("Error closing database connection", e);
359 }
360 }
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374 public List<PersistentIdEntry> getDeactivatedPersistentIdEntries(String localEntity, String peerEntity,
375 String localId) throws SQLException {
376 StringBuilder sqlBuilder = new StringBuilder(idEntrySelectSQL);
377 sqlBuilder.append(localEntityColumn).append(" = ?");
378 sqlBuilder.append(" AND ").append(peerEntityColumn).append(" = ?");
379 sqlBuilder.append(" AND ").append(localIdColumn).append(" = ?");
380 sqlBuilder.append(" AND ").append(deactivationTimeColumn).append(" IS NOT NULL");
381 String sql = sqlBuilder.toString();
382
383 log.debug("Selecting deactivated persistent ID entries based on prepared sql statement: {}", sql);
384 Connection dbConn = dataSource.getConnection();
385 try {
386 PreparedStatement statement = dbConn.prepareStatement(sql);
387 statement.setQueryTimeout(queryTimeout);
388
389 log.debug("Setting prepared statement parameter {}: {}", 1, localEntity);
390 statement.setString(1, localEntity);
391 log.debug("Setting prepared statement parameter {}: {}", 2, peerEntity);
392 statement.setString(2, peerEntity);
393 log.debug("Setting prepared statement parameter {}: {}", 3, localId);
394 statement.setString(3, localId);
395
396 log.debug("Getting deactivated persistent Id entries");
397 List<PersistentIdEntry> entries = buildIdentifierEntries(statement.executeQuery());
398
399 if (entries == null || entries.size() == 0) {
400 return null;
401 }
402
403 return entries;
404 } finally {
405 try {
406 if (dbConn != null && !dbConn.isClosed()) {
407 dbConn.close();
408 }
409 } catch (SQLException e) {
410 log.error("Error closing database connection", e);
411 }
412 }
413 }
414
415
416
417
418
419
420
421
422 public void storePersistentIdEntry(PersistentIdEntry entry) throws SQLException {
423
424 StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");
425 sqlBuilder.append(table).append(" (");
426 sqlBuilder.append(localEntityColumn).append(", ");
427 sqlBuilder.append(peerEntityColumn).append(", ");
428 sqlBuilder.append(principalNameColumn).append(", ");
429 sqlBuilder.append(localIdColumn).append(", ");
430 sqlBuilder.append(persistentIdColumn).append(", ");
431 sqlBuilder.append(peerProvidedIdColumn).append(", ");
432 sqlBuilder.append(createTimeColumn);
433 sqlBuilder.append(") VALUES (?, ?, ?, ?, ?, ?, ?)");
434
435 String sql = sqlBuilder.toString();
436
437 Connection dbConn = dataSource.getConnection();
438 try {
439 log.debug("Storing persistent ID entry based on prepared sql statement: {}", sql);
440 PreparedStatement statement = dbConn.prepareStatement(sql);
441 statement.setQueryTimeout(queryTimeout);
442
443 log.debug("Setting prepared statement parameter {}: {}", 1, entry.getLocalEntityId());
444 statement.setString(1, entry.getLocalEntityId());
445 log.debug("Setting prepared statement parameter {}: {}", 2, entry.getPeerEntityId());
446 statement.setString(2, entry.getPeerEntityId());
447 log.debug("Setting prepared statement parameter {}: {}", 3, entry.getPrincipalName());
448 statement.setString(3, entry.getPrincipalName());
449 log.debug("Setting prepared statement parameter {}: {}", 4, entry.getLocalId());
450 statement.setString(4, entry.getLocalId());
451 log.debug("Setting prepared statement parameter {}: {}", 5, entry.getPersistentId());
452 statement.setString(5, entry.getPersistentId());
453
454 if (entry.getPeerProvidedId() == null) {
455 log.debug("Setting prepared statement parameter {}: {}", 6, Types.VARCHAR);
456 statement.setNull(6, Types.VARCHAR);
457 } else {
458 log.debug("Setting prepared statement parameter {}: {}", 6, entry.getPeerProvidedId());
459 statement.setString(6, entry.getPeerProvidedId());
460 }
461 Timestamp timestamp = new Timestamp(System.currentTimeMillis());
462 log.debug("Setting prepared statement parameter {}: {}", 7, timestamp.toString());
463 statement.setTimestamp(7, timestamp);
464
465 statement.executeUpdate();
466 } finally {
467 try {
468 if (dbConn != null && !dbConn.isClosed()) {
469 dbConn.close();
470 }
471 } catch (SQLException e) {
472 log.error("Error closing database connection", e);
473 }
474 }
475 }
476
477
478
479
480
481
482
483
484
485 public void deactivatePersistentId(String persistentId, Timestamp deactivation) throws SQLException {
486 Timestamp deactivationTime = deactivation;
487 if (deactivationTime == null) {
488 deactivationTime = new Timestamp(System.currentTimeMillis());
489 }
490
491 Connection dbConn = dataSource.getConnection();
492 try {
493 log.debug("Deactivating persistent id {} as of {}", persistentId, deactivationTime.toString());
494 PreparedStatement statement = dbConn.prepareStatement(deactivateIdSQL);
495 statement.setQueryTimeout(queryTimeout);
496 statement.setTimestamp(1, deactivationTime);
497 statement.setString(2, persistentId);
498 statement.executeUpdate();
499 } finally {
500 try {
501 if (dbConn != null && !dbConn.isClosed()) {
502 dbConn.close();
503 }
504 } catch (SQLException e) {
505 log.error("Error closing database connection", e);
506 }
507 }
508 }
509
510
511
512
513
514
515
516
517
518
519 protected List<PersistentIdEntry> buildIdentifierEntries(ResultSet resultSet) throws SQLException {
520 ArrayList<PersistentIdEntry> entries = new ArrayList<PersistentIdEntry>();
521
522 PersistentIdEntry entry;
523 while (resultSet.next()) {
524 entry = new PersistentIdEntry();
525 entry.setLocalEntityId(resultSet.getString(localEntityColumn));
526 entry.setPeerEntityId(resultSet.getString(peerEntityColumn));
527 entry.setPrincipalName(resultSet.getString(principalNameColumn));
528 entry.setPersistentId(resultSet.getString(persistentIdColumn));
529 entry.setLocalId(resultSet.getString(localIdColumn));
530 entry.setPeerProvidedId(resultSet.getString(peerProvidedIdColumn));
531 entry.setCreationTime(resultSet.getTimestamp(createTimeColumn));
532 entry.setDeactivationTime(resultSet.getTimestamp(deactivationTimeColumn));
533 entries.add(entry);
534
535 log.trace("");
536 }
537
538 return entries;
539 }
540
541
542 public class PersistentIdEntry implements Serializable {
543
544
545 private static final long serialVersionUID = -8711779466442306767L;
546
547
548 private String localEntityId;
549
550
551 private String peerEntityId;
552
553
554 private String principalName;
555
556
557 private String localId;
558
559
560 private String persistentId;
561
562
563 private String peerProvidedId;
564
565
566 private Timestamp creationTime;
567
568
569 private Timestamp deactivationTime;
570
571
572 public PersistentIdEntry() {
573 }
574
575
576
577
578
579
580 public String getLocalEntityId() {
581 return localEntityId;
582 }
583
584
585
586
587
588
589 public void setLocalEntityId(String id) {
590 localEntityId = id;
591 }
592
593
594
595
596
597
598 public String getPeerEntityId() {
599 return peerEntityId;
600 }
601
602
603
604
605
606
607 public void setPeerEntityId(String id) {
608 peerEntityId = id;
609 }
610
611
612
613
614
615
616 public String getPrincipalName() {
617 return principalName;
618 }
619
620
621
622
623
624
625 public void setPrincipalName(String name) {
626 principalName = name;
627 }
628
629
630
631
632
633
634 public String getLocalId() {
635 return localId;
636 }
637
638
639
640
641
642
643 public void setLocalId(String id) {
644 localId = id;
645 }
646
647
648
649
650
651
652 public String getPersistentId() {
653 return persistentId;
654 }
655
656
657
658
659
660
661 public void setPersistentId(String id) {
662 persistentId = id;
663 }
664
665
666
667
668
669
670 public String getPeerProvidedId() {
671 return peerProvidedId;
672 }
673
674
675
676
677
678
679 public void setPeerProvidedId(String id) {
680 peerProvidedId = id;
681 }
682
683
684
685
686
687
688 public Timestamp getCreationTime() {
689 return creationTime;
690 }
691
692
693
694
695
696
697 public void setCreationTime(Timestamp time) {
698 creationTime = time;
699 }
700
701
702
703
704
705
706 public Timestamp getDeactivationTime() {
707 return deactivationTime;
708 }
709
710
711
712
713
714
715 public void setDeactivationTime(Timestamp time) {
716 this.deactivationTime = time;
717 }
718
719
720 public String toString() {
721 StringBuilder stringForm = new StringBuilder("PersistentIdEntry{");
722 stringForm.append("persistentId:").append(persistentId).append(", ");
723 stringForm.append("localEntityId:").append(localEntityId).append(", ");
724 stringForm.append("peerEntityId:").append(peerEntityId).append(", ");
725 stringForm.append("localId:").append(localId).append(", ");
726 stringForm.append("principalName:").append(principalName).append(", ");
727 stringForm.append("peerProvidedId:").append(peerProvidedId).append(", ");
728 stringForm.append("creationTime:").append(creationTime).append(", ");
729 stringForm.append("deactivationTime:").append(deactivationTime).append(", ");
730 stringForm.append("}");
731 return stringForm.toString();
732 }
733 }
734 }