1 16 package org.outerj.daisy.emailnotifier.serverimpl; 17 18 import org.outerj.daisy.emailnotifier.*; 19 import org.outerj.daisy.emailnotifier.commonimpl.*; 20 import org.outerj.daisy.repository.Repository; 21 import org.outerj.daisy.repository.RepositoryException; 22 import org.outerj.daisy.repository.LocaleHelper; 23 import org.outerj.daisy.repository.VariantKey; 24 import org.outerj.daisy.repository.user.User; 25 import org.outerj.daisy.repository.user.Role; 26 import org.outerj.daisy.jdbcutil.JdbcHelper; 27 28 import java.sql.*; 29 import java.util.ArrayList ; 30 import java.util.Locale ; 31 import java.util.List ; 32 33 public class LocalEmailSubscriptionManager implements EmailSubscriptionManager { 34 private Repository repository; 35 private LocalEmailSubscriptionManagerProvider.Context context; 36 private JdbcHelper jdbcHelper; 37 private SubscriptionStrategyImpl subscriptionStrategy = new SubscriptionStrategyImpl(); 38 39 protected LocalEmailSubscriptionManager(Repository repository, LocalEmailSubscriptionManagerProvider.Context context, 40 JdbcHelper jdbcHelper) { 41 this.repository = repository; 42 this.context = context; 43 this.jdbcHelper = jdbcHelper; 44 } 45 46 public Subscription getSubscription() throws RepositoryException { 47 return getSubscription(repository.getUserId()); 48 } 49 50 private void storeSubscription(SubscriptionImpl subscription) throws RepositoryException { 51 Connection conn = null; 52 PreparedStatement stmt = null; 53 try { 54 conn = context.getDataSource().getConnection(); 55 jdbcHelper.startTransaction(conn); 56 57 deleteSubscriptionInt(subscription.getUserId(), conn); 58 59 stmt = conn.prepareStatement("insert into emailntfy_subscriptions(user_id, document_events, schema_events, user_events, collection_events, acl_events, comment_events, locale) values (?,?,?,?,?,?,?,?)"); 60 stmt.setLong(1, subscription.getUserId()); 61 stmt.setBoolean(2, subscription.getReceiveDocumentEvents()); 62 stmt.setBoolean(3, subscription.getReceiveSchemaEvents()); 63 stmt.setBoolean(4, subscription.getReceiveUserEvents()); 64 stmt.setBoolean(5, subscription.getReceiveCollectionEvents()); 65 stmt.setBoolean(6, subscription.getReceiveAclEvents()); 66 stmt.setBoolean(7, subscription.getReceiveCommentEvents()); 67 stmt.setString(8, subscription.getLocale() != null ? LocaleHelper.getString(subscription.getLocale()) : null); 68 stmt.execute(); 69 stmt.close(); 70 71 73 VariantKey[] variantKeys = subscription.getSubscribedVariantKeys(); 74 if (variantKeys.length > 0) { 75 stmt = conn.prepareStatement("insert into document_subscriptions(user_id,doc_id,branch_id,lang_id) values(?,?,?,?)"); 76 stmt.setLong(1, subscription.getUserId()); 77 for (int i = 0; i < variantKeys.length; i++) { 78 VariantKey variantKey = variantKeys[i]; 79 stmt.setLong(2, variantKey.getDocumentId()); 80 stmt.setLong(3, variantKey.getBranchId()); 81 stmt.setLong(4, variantKey.getLanguageId()); 82 stmt.execute(); 83 } 84 stmt.close(); 85 } 86 87 89 CollectionSubscriptionKey[] collectionKeys = subscription.getSubscribedCollectionKeys(); 90 if (collectionKeys.length > 0) { 91 stmt = conn.prepareStatement("insert into collection_subscriptions(user_id,collection_id,branch_id,lang_id) values(?,?,?,?)"); 92 stmt.setLong(1, subscription.getUserId()); 93 for (int i = 0; i < collectionKeys.length; i++) { 94 CollectionSubscriptionKey collectionKey = collectionKeys[i]; 95 stmt.setLong(2, collectionKey.getCollectionId()); 96 stmt.setLong(3, collectionKey.getBranchId()); 97 stmt.setLong(4, collectionKey.getLanguageId()); 98 stmt.execute(); 99 } 100 stmt.close(); 101 } 102 103 104 conn.commit(); 105 } catch (Throwable e) { 106 jdbcHelper.rollback(conn); 107 throw new RepositoryException("An error occured storing subscription information for user " + repository.getUserId(), e); 108 } finally { 109 jdbcHelper.closeStatement(stmt); 110 jdbcHelper.closeConnection(conn); 111 } 112 } 113 114 private static final String SELECT_SUBSCRIPTION = "select user_id, document_events, schema_events, user_events, collection_events, acl_events, comment_events, locale from emailntfy_subscriptions"; 115 116 public Subscription getSubscription(long userId) throws RepositoryException { 117 if (userId != repository.getUserId() && !repository.isInRole(Role.ADMINISTRATOR)) 118 throw new RuntimeException ("Only users with role administrator can access the subscriptions of other users."); 119 120 Connection conn = null; 121 PreparedStatement stmt = null; 122 SubscriptionLoadContext subscriptionLoadContext = null; 123 try { 124 conn = context.getDataSource().getConnection(); 125 jdbcHelper.startTransaction(conn); 126 stmt = conn.prepareStatement(SELECT_SUBSCRIPTION + " where user_id = ?"); 127 stmt.setLong(1, userId); 128 ResultSet rs = stmt.executeQuery(); 129 if (rs.next()) { 130 subscriptionLoadContext = SubscriptionLoadContext.create(conn, jdbcHelper); 131 return instatiateSubscriptionFromResultSet(rs, subscriptionLoadContext); 132 } else { 133 User user = repository.getUserManager().getUser(userId, false); 134 return new SubscriptionImpl(subscriptionStrategy, user.getId()); 135 } 136 } catch (Throwable e) { 137 throw new RepositoryException("An error occured while retrieving subscription information for user " + repository.getUserId(), e); 138 } finally { 139 if (subscriptionLoadContext != null) 140 subscriptionLoadContext.cleanup(); 141 jdbcHelper.closeStatement(stmt); 142 jdbcHelper.closeConnection(conn); 143 } 144 } 145 146 149 static class SubscriptionLoadContext { 150 private PreparedStatement documentSubStmt; 151 private PreparedStatement collectionSubStmt; 152 private JdbcHelper jdbcHelper; 153 154 private SubscriptionLoadContext() { 155 } 156 157 static SubscriptionLoadContext create(Connection conn, JdbcHelper jdbcHelper) throws SQLException { 158 SubscriptionLoadContext context = new SubscriptionLoadContext(); 159 context.documentSubStmt = conn.prepareStatement("select doc_id, branch_id, lang_id from document_subscriptions where user_id = ?"); 160 context.collectionSubStmt = conn.prepareStatement("select collection_id, branch_id, lang_id from collection_subscriptions where user_id = ?"); 161 context.jdbcHelper = jdbcHelper; 162 return context; 163 } 164 165 public PreparedStatement getDocumentSubscriptionStmt() { 166 return documentSubStmt; 167 } 168 169 public PreparedStatement getCollectionSubscriptionStmt() { 170 return collectionSubStmt; 171 } 172 173 void cleanup() { 174 jdbcHelper.closeStatement(documentSubStmt); 175 jdbcHelper.closeStatement(collectionSubStmt); 176 } 177 } 178 179 private SubscriptionImpl instatiateSubscriptionFromResultSet(ResultSet rs, SubscriptionLoadContext slContext) throws SQLException { 180 long userId = rs.getLong("user_id"); 181 SubscriptionImpl subscription = new SubscriptionImpl(subscriptionStrategy, userId); 182 subscription.setReceiveDocumentEvents(rs.getBoolean("document_events")); 183 subscription.setReceiveSchemaEvents(rs.getBoolean("schema_events")); 184 subscription.setReceiveUserEvents(rs.getBoolean("user_events")); 185 subscription.setReceiveCollectionEvents(rs.getBoolean("collection_events")); 186 subscription.setReceiveAclEvents(rs.getBoolean("acl_events")); 187 subscription.setReceiveCommentEvents(rs.getBoolean("comment_events")); 188 String locale = rs.getString("locale"); 189 if (locale != null) 190 subscription.setLocale(LocaleHelper.parseLocale(locale)); 191 192 PreparedStatement stmt = slContext.getDocumentSubscriptionStmt(); 193 stmt.setLong(1, userId); 194 rs = stmt.executeQuery(); 195 List variantKeys = new ArrayList (); 196 while (rs.next()) { 197 variantKeys.add(new VariantKey(rs.getLong(1), rs.getLong(2), rs.getLong(3))); 198 } 199 subscription.setSubscribedVariantKeys((VariantKey[])variantKeys.toArray(new VariantKey[variantKeys.size()])); 200 201 stmt = slContext.getCollectionSubscriptionStmt(); 202 stmt.setLong(1, userId); 203 rs = stmt.executeQuery(); 204 List collectionKeys = new ArrayList (); 205 while (rs.next()) { 206 collectionKeys.add(new CollectionSubscriptionKey(rs.getLong(1), rs.getLong(2), rs.getLong(3))); 207 } 208 subscription.setSubscribedCollectionKeys((CollectionSubscriptionKey[])collectionKeys.toArray(new CollectionSubscriptionKey[collectionKeys.size()])); 209 210 return subscription; 211 } 212 213 public void deleteSubscription() throws RepositoryException { 214 deleteSubscription(repository.getUserId()); 215 } 216 217 public void deleteSubscription(long userId) throws RepositoryException { 218 if (userId != repository.getUserId() && !repository.isInRole(Role.ADMINISTRATOR)) 219 throw new RuntimeException ("Only users with role administrator can delete the subscriptions of other users."); 220 221 Connection conn = null; 222 PreparedStatement stmt = null; 223 try { 224 conn = context.getDataSource().getConnection(); 225 jdbcHelper.startTransaction(conn); 226 deleteSubscriptionInt(userId, conn); 227 conn.commit(); 228 } catch (Throwable e) { 229 jdbcHelper.rollback(conn); 230 throw new RepositoryException("An error occured while deleting subscription information for user " + repository.getUserId(), e); 231 } finally { 232 jdbcHelper.closeStatement(stmt); 233 jdbcHelper.closeConnection(conn); 234 } 235 } 236 237 public void deleteSubscriptionInt(long userId, Connection conn) throws SQLException { 238 PreparedStatement stmt = null; 239 try { 240 conn = context.getDataSource().getConnection(); 241 242 stmt = conn.prepareStatement("delete from document_subscriptions where user_id = ?"); 243 stmt.setLong(1, userId); 244 stmt.execute(); 245 stmt.close(); 246 247 stmt = conn.prepareStatement("delete from collection_subscriptions where user_id = ?"); 248 stmt.setLong(1, userId); 249 stmt.execute(); 250 stmt.close(); 251 252 stmt = conn.prepareStatement("delete from emailntfy_subscriptions where user_id = ?"); 253 stmt.setLong(1, userId); 254 stmt.execute(); 255 stmt.close(); 256 } finally { 257 jdbcHelper.closeStatement(stmt); 258 jdbcHelper.closeConnection(conn); 259 } 260 } 261 262 public Subscriptions getSubscriptions() throws RepositoryException { 263 if (!repository.isInRole(Role.ADMINISTRATOR)) 264 throw new RuntimeException ("Only users with role administrator can access the list of all subscriptions."); 265 266 Connection conn = null; 267 Statement stmt = null; 268 SubscriptionLoadContext subscriptionLoadContext = null; 269 try { 270 ArrayList subscriptions = new ArrayList (); 271 conn = context.getDataSource().getConnection(); 272 jdbcHelper.startTransaction(conn); 273 stmt = conn.createStatement(); 274 ResultSet rs = stmt.executeQuery(SELECT_SUBSCRIPTION); 275 subscriptionLoadContext = SubscriptionLoadContext.create(conn, jdbcHelper); 276 while (rs.next()) { 277 subscriptions.add(instatiateSubscriptionFromResultSet(rs, subscriptionLoadContext)); 278 } 279 return new SubscriptionsImpl((Subscription[])subscriptions.toArray(new Subscription[subscriptions.size()])); 280 } catch (Throwable e) { 281 throw new RepositoryException("An error occured while retrieving the subscriptions.", e); 282 } finally { 283 if (subscriptionLoadContext != null) 284 subscriptionLoadContext.cleanup(); 285 jdbcHelper.closeStatement(stmt); 286 jdbcHelper.closeConnection(conn); 287 } 288 } 289 290 293 private Subscribers getSubscribers(String query) throws RepositoryException { 294 if (!repository.isInRole(Role.ADMINISTRATOR)) 295 throw new RuntimeException ("Only users with role administrator can retrieve lists of subscribers."); 296 297 Connection conn = null; 298 PreparedStatement stmt = null; 299 try { 300 ArrayList subscribers = new ArrayList (); 301 conn = context.getDataSource().getConnection(); 302 stmt = conn.prepareStatement(query); 303 stmt.setBoolean(1, true); 304 ResultSet rs = stmt.executeQuery(); 305 while (rs.next()) { 306 long userId = rs.getLong(1); 307 String localeString = rs.getString("locale"); 308 Locale locale = localeString != null ? LocaleHelper.parseLocale(localeString) : null; 309 subscribers.add(new SubscriberImpl(userId, locale)); 310 } 311 return new SubscribersImpl((Subscriber[])subscribers.toArray(new Subscriber[subscribers.size()])); 312 } catch (Throwable e) { 313 throw new RepositoryException("An error occured while retrieving subscribers.", e); 314 } finally { 315 jdbcHelper.closeStatement(stmt); 316 jdbcHelper.closeConnection(conn); 317 } 318 } 319 320 public Subscribers getAllDocumentEventSubscribers(long documentId, long branchId, long languageId, long[] collections) throws RepositoryException { 321 return getAllEventSubscribersForDocumentOrCollections(documentId, branchId, languageId, collections, "document_events"); 322 } 323 324 private Subscribers getAllEventSubscribersForDocumentOrCollections(long documentId, long branchId, long languageId, long[] collections, String subscriptionColumn) throws RepositoryException { 325 StringBuffer query = new StringBuffer (); 326 query.append("select distinct(es.user_id), locale from emailntfy_subscriptions es"); 327 query.append(" left outer join document_subscriptions ds on (es.user_id = ds.user_id)"); 328 query.append(" left outer join collection_subscriptions cs on (es.user_id = cs.user_id)"); 329 query.append(" where es.").append(subscriptionColumn).append(" = ? and"); 330 query.append(" ("); 331 query.append(" ("); 332 query.append(" (ds.doc_id = ").append(documentId).append(" or ds.doc_id = -1)"); 333 query.append(" and (ds.branch_id = ").append(branchId).append(" or ds.branch_id = -1)"); 334 query.append(" and (ds.lang_id = ").append(languageId).append(" or ds.lang_id = -1)"); 335 query.append(" )"); 336 if (collections.length > 0) { 337 for (int i = 0; i < collections.length; i++) { 338 query.append(" or"); 339 query.append(" ("); 340 query.append(" (cs.collection_id = ").append(collections[i]).append(" or cs.collection_id = -1)"); 341 query.append(" and (cs.branch_id = ").append(branchId).append(" or cs.branch_id = -1)"); 342 query.append(" and (cs.lang_id = ").append(languageId).append(" or cs.lang_id = -1)"); 343 query.append(" )"); 344 } 345 } 346 query.append(" )"); 347 348 return getSubscribers(query.toString()); 349 } 350 351 public Subscribers getAllUserEventSubscribers() throws RepositoryException { 352 return getSubscribers("select user_id, locale from emailntfy_subscriptions where user_events = ?"); 353 } 354 355 public Subscribers getAllCollectionEventSubscribers() throws RepositoryException { 356 return getSubscribers("select user_id, locale from emailntfy_subscriptions where collection_events = ?"); 357 } 358 359 public Subscribers getAllSchemaEventSubscribers() throws RepositoryException { 360 return getSubscribers("select user_id, locale from emailntfy_subscriptions where schema_events = ?"); 361 } 362 363 public Subscribers getAllAclEventSubscribers() throws RepositoryException { 364 return getSubscribers("select user_id, locale from emailntfy_subscriptions where acl_events = ?"); 365 } 366 367 public Subscribers getAllCommentEventSubscribers(long documentId, long branchId, long languageId, long[] collections) throws RepositoryException { 368 return getAllEventSubscribersForDocumentOrCollections(documentId, branchId, languageId, collections, "comment_events"); 369 } 370 371 public void addDocumentSubscription(VariantKey variantKey) throws RepositoryException { 372 addDocumentSubscription(repository.getUserId(), variantKey); 373 } 374 375 public void addDocumentSubscription(long userId, VariantKey variantKey) throws RepositoryException { 376 if (userId != repository.getUserId() && !repository.isInRole(Role.ADMINISTRATOR)) 377 throw new RuntimeException ("Only users with role administrator can adjust the subscriptions of other users."); 378 379 Connection conn = null; 380 PreparedStatement stmt = null; 381 try { 382 conn = context.getDataSource().getConnection(); 383 jdbcHelper.startTransaction(conn); 384 385 stmt = conn.prepareStatement("select NULL from emailntfy_subscriptions where user_id = ?"); 387 stmt.setLong(1, userId); 388 ResultSet rs = stmt.executeQuery(); 389 if (!rs.next()) { 390 Subscription subscription = getSubscription(); 391 subscription.setReceiveDocumentEvents(true); 392 subscription.setSubscribedVariantKeys(new VariantKey[] {variantKey}); 393 subscription.save(); 394 return; 395 } 396 397 399 stmt = conn.prepareStatement("select NULL from document_subscriptions where user_id = ? and doc_id = ? and branch_id = ? and lang_id = ?"); 400 stmt.setLong(1, userId); 401 stmt.setLong(2, variantKey.getDocumentId()); 402 stmt.setLong(3, variantKey.getBranchId()); 403 stmt.setLong(4, variantKey.getLanguageId()); 404 rs = stmt.executeQuery(); 405 boolean needsInsert = !rs.next(); 406 stmt.close(); 407 408 if (needsInsert) { 409 stmt = conn.prepareStatement("insert into document_subscriptions(user_id, doc_id, branch_id, lang_id) values(?,?,?,?)"); 410 stmt.setLong(1, userId); 411 stmt.setLong(2, variantKey.getDocumentId()); 412 stmt.setLong(3, variantKey.getBranchId()); 413 stmt.setLong(4, variantKey.getLanguageId()); 414 stmt.execute(); 415 stmt.close(); 416 } 417 418 conn.commit(); 419 } catch (Throwable e) { 420 jdbcHelper.rollback(conn); 421 throw new RepositoryException("An error occured while adding the document subscription (user ID " + userId + ", " + variantKey.toString() + ").", e); 422 } finally { 423 jdbcHelper.closeStatement(stmt); 424 jdbcHelper.closeConnection(conn); 425 } 426 } 427 428 public boolean isSubsribed(VariantKey variantKey) throws RepositoryException { 429 return isSubsribed(repository.getUserId(), variantKey); 430 } 431 432 public boolean isSubsribed(long userId, VariantKey variantKey) throws RepositoryException { 433 if (userId != repository.getUserId() && !repository.isInRole(Role.ADMINISTRATOR)) 434 throw new RuntimeException ("Only users with role administrator can check the subscriptions of other users."); 435 436 Connection conn = null; 437 PreparedStatement stmt = null; 438 try { 439 conn = context.getDataSource().getConnection(); 440 stmt = conn.prepareStatement("select null from document_subscriptions where user_id = ? and doc_id = ? and branch_id = ? and lang_id = ?"); 441 stmt.setLong(1, userId); 442 stmt.setLong(2, variantKey.getDocumentId()); 443 stmt.setLong(3, variantKey.getBranchId()); 444 stmt.setLong(4, variantKey.getLanguageId()); 445 ResultSet rs = stmt.executeQuery(); 446 return rs.next(); 447 } catch (Throwable e) { 448 throw new RepositoryException("An error occured while checking document subscription (user ID " + userId + ", " + variantKey.toString() + ").", e); 449 } finally { 450 jdbcHelper.closeStatement(stmt); 451 jdbcHelper.closeConnection(conn); 452 } 453 } 454 455 public void deleteDocumentSubscription(VariantKey variantKey) throws RepositoryException { 456 deleteDocumentSubscription(repository.getUserId(), variantKey); 457 } 458 459 public void deleteDocumentSubscription(long userId, VariantKey variantKey) throws RepositoryException { 460 if (userId != repository.getUserId() && !repository.isInRole(Role.ADMINISTRATOR)) 461 throw new RuntimeException ("Only users with role administrator can adjust the subscriptions of other users."); 462 463 Connection conn = null; 464 PreparedStatement stmt = null; 465 try { 466 conn = context.getDataSource().getConnection(); 467 stmt = conn.prepareStatement("delete from document_subscriptions where user_id = ? and doc_id = ? and branch_id = ? and lang_id = ?"); 468 stmt.setLong(1, userId); 469 stmt.setLong(2, variantKey.getDocumentId()); 470 stmt.setLong(3, variantKey.getBranchId()); 471 stmt.setLong(4, variantKey.getLanguageId()); 472 stmt.execute(); 473 } catch (Throwable e) { 474 throw new RepositoryException("An error occured while removing document subscription (user ID " + userId + ", " + variantKey.toString() + ").", e); 475 } finally { 476 jdbcHelper.closeStatement(stmt); 477 jdbcHelper.closeConnection(conn); 478 } 479 } 480 481 public void deleteAllSubscriptionsForDocument(long documentId) throws RepositoryException { 482 if (!repository.isInRole(Role.ADMINISTRATOR)) 483 throw new RuntimeException ("Only users with role administrator can remove all subscriptions on a document."); 484 485 Connection conn = null; 486 PreparedStatement stmt = null; 487 try { 488 conn = context.getDataSource().getConnection(); 489 stmt = conn.prepareStatement("delete from document_subscriptions where doc_id = ?"); 490 stmt.setLong(1, documentId); 491 stmt.execute(); 492 } catch (Throwable e) { 493 throw new RepositoryException("An error occured while removing document subscriptions (document ID " + documentId + ").", e); 494 } finally { 495 jdbcHelper.closeStatement(stmt); 496 jdbcHelper.closeConnection(conn); 497 } 498 } 499 500 public void deleteAllSubscriptionsForDocumentVariant(VariantKey variantKey) throws RepositoryException { 501 if (!repository.isInRole(Role.ADMINISTRATOR)) 502 throw new RuntimeException ("Only users with role administrator can remove all subscriptions on a document variant."); 503 504 Connection conn = null; 505 PreparedStatement stmt = null; 506 try { 507 conn = context.getDataSource().getConnection(); 508 stmt = conn.prepareStatement("delete from document_subscriptions where doc_id = ? and branch_id = ? and lang_id = ?"); 509 stmt.setLong(1, variantKey.getDocumentId()); 510 stmt.setLong(2, variantKey.getBranchId()); 511 stmt.setLong(3, variantKey.getLanguageId()); 512 stmt.execute(); 513 } catch (Throwable e) { 514 throw new RepositoryException("An error occured while removing document variant subscriptions (" + variantKey.toString() + ").", e); 515 } finally { 516 jdbcHelper.closeStatement(stmt); 517 jdbcHelper.closeConnection(conn); 518 } 519 } 520 521 public void deleteAllSubscriptionsForCollection(long collectionId) throws RepositoryException { 522 if (!repository.isInRole(Role.ADMINISTRATOR)) 523 throw new RuntimeException ("Only users with role administrator can remove all subscriptions on a collection."); 524 525 Connection conn = null; 526 PreparedStatement stmt = null; 527 try { 528 conn = context.getDataSource().getConnection(); 529 stmt = conn.prepareStatement("delete from collection_subscriptions where collection_id = ?"); 530 stmt.setLong(1, collectionId); 531 stmt.execute(); 532 } catch (Throwable e) { 533 throw new RepositoryException("An error occured while removing collection subscriptions (collection ID " + collectionId + ").", e); 534 } finally { 535 jdbcHelper.closeStatement(stmt); 536 jdbcHelper.closeConnection(conn); 537 } 538 } 539 540 public class Context { 541 private Context() { 542 } 543 544 public Repository getRepository() { 545 return repository; 546 } 547 } 548 549 class SubscriptionStrategyImpl implements SubscriptionStrategy { 550 public void storeSubscription(SubscriptionImpl subscription) throws RepositoryException { 551 LocalEmailSubscriptionManager.this.storeSubscription(subscription); 552 } 553 } 554 555 } 556 | Popular Tags |