View Javadoc

1   package org.sourceforge.vlibrary.user.dao;
2   
3   import org.apache.log4j.Logger;
4   
5   import java.sql.Types;
6   
7   import java.util.List;
8   import java.util.Iterator;
9   import java.util.Map;
10  import java.util.Locale;
11  import java.util.ArrayList;
12  
13  import org.springframework.context.support.ResourceBundleMessageSource;
14  import org.springframework.jdbc.core.JdbcTemplate;
15  
16  import org.apache.commons.lang.StringUtils;
17  
18  import org.sourceforge.vlibrary.Constants;
19  import org.sourceforge.vlibrary.exceptions.LibraryException;
20  import org.sourceforge.vlibrary.user.exceptions.DuplicateReaderException;
21  import org.sourceforge.vlibrary.user.domain.Reader;
22  import org.sourceforge.vlibrary.util.Crypto;
23  import org.sourceforge.vlibrary.util.Utils;
24  
25  
26  /**
27   *
28   * @version $Revision$ $Date$
29   */
30  
31  public class ReaderDAOSpringJDBCImpl implements ReaderDAO {
32      /** log4j Logger */
33      private static Logger logger =
34       Logger.getLogger(ReaderDAOSpringJDBCImpl.class.getName());
35      
36      private ResourceBundleMessageSource resourceBundleMessageSource;
37      private JdbcTemplate jdbcTemplate;
38      private String insertUserRoleSQL;
39      private String selectReaderIdByUidSQL;
40      private String selectReaderByDeskPhoneSQL;
41      private String selectReaderByIdSQL;
42      private String updateReaderSQL;
43      private String insertReaderSQL;
44      private String selectAllReadersSQL;
45      private String selectReaderByFirstLastNameSQL;
46      private String updateReaderPasswordSQL;
47      private String deleteReaderAdminRoleSQL;
48      private String insertReaderAdminRoleSQL;
49      private String selectReaderAdminRoleSQL;
50      private Crypto crypto;
51      
52      /**
53       * Used for Spring Dependency Injection
54       * @param jdbcTemplate The jdbcTemplate to set.
55       */
56      public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
57          this.jdbcTemplate = jdbcTemplate;
58      }
59      
60      /**
61       * Used for Spring Dependency Injection
62       */
63      public void setResourceBundleMessageSource(
64       ResourceBundleMessageSource resourceBundleMessageSource) {
65          this.resourceBundleMessageSource = resourceBundleMessageSource;
66      }
67      
68      /**
69       * Used for Spring Dependency Injection
70       */
71      public void setUpdateReaderPasswordSQL( String updateReaderPasswordSQL) {
72          this.updateReaderPasswordSQL = updateReaderPasswordSQL;
73      }
74      
75      /**
76       * Used for Spring Dependency Injection
77       */
78      public void setSelectReaderByFirstLastNameSQL(
79              String selectReaderByFirstLastNameSQL) {
80          this.selectReaderByFirstLastNameSQL = selectReaderByFirstLastNameSQL;
81      }
82      
83      /**
84       * Used for Spring Dependency Injection
85       */
86      public void setSelectAllReadersSQL( String selectAllReadersSQL) {
87          this.selectAllReadersSQL = selectAllReadersSQL;
88      }
89      
90      /**
91       * Used for Spring Dependency Injection
92       */
93      public void setInsertReaderSQL( String insertReaderSQL) {
94          this.insertReaderSQL = insertReaderSQL;
95      }
96      
97      /**
98       * Used for Spring Dependency Injection
99       */
100     public void setInsertUserRoleSQL(String insertUserRoleSQL) {
101         this.insertUserRoleSQL = insertUserRoleSQL;
102     }
103     
104     /**
105      * Used for Spring Dependency Injection
106      */
107     public void setSelectReaderIdByUidSQL(String selectReaderIdByUidSQL) {
108         this.selectReaderIdByUidSQL = selectReaderIdByUidSQL;
109     }
110     
111     /**
112      * Used for Spring Dependency Injection
113      */
114     public void setSelectReaderByIdSQL( String selectReaderByIdSQL) {
115         this.selectReaderByIdSQL = selectReaderByIdSQL;
116     }
117     
118     /**
119      * Used for Spring Dependency Injection
120      */
121     public void setSelectReaderByDeskPhoneSQL( String selectReaderByDeskPhoneSQL) {
122         this.selectReaderByDeskPhoneSQL = selectReaderByDeskPhoneSQL;
123     }
124     
125     /**
126      * Used for Spring Dependency Injection
127      */
128     public void setUpdateReaderSQL( String updateReaderSQL) {
129         this.updateReaderSQL = updateReaderSQL;
130     }
131     
132     /**
133      * Used for Spring Dependency Injection
134      */
135     public void setDeleteReaderAdminRoleSQL( String deleteReaderAdminRoleSQL) {
136         this.deleteReaderAdminRoleSQL = deleteReaderAdminRoleSQL;
137     }
138     
139     /**
140      * Used for Spring Dependency Injection
141      */
142     public void setInsertReaderAdminRoleSQL( String insertReaderAdminRoleSQL) {
143         this.insertReaderAdminRoleSQL = insertReaderAdminRoleSQL;
144     }
145     
146     /**
147      * Used for Spring Dependency Injection
148      */
149     public void setSelectReaderAdminRoleSQL( String selectReaderAdminRoleSQL) {
150         this.selectReaderAdminRoleSQL = selectReaderAdminRoleSQL;
151     }
152     
153     /**
154      * Used for Spring Dependency Injection
155      */
156     public void setCrypto( Crypto crypto) {
157         this.crypto = crypto;
158     }
159     
160     /**
161      * Inserts Reader into the database. Has the side effect of
162      * setting Reader object's id to the sequentially generated id of the new record.
163      * Also adds "reader" role for this reader to the user_x_role table.
164      *
165      * @throws LibraryException
166      */
167     public void insert(Reader reader) throws LibraryException {
168         if (reader == null ||
169          reader.getFirstName() == null ||
170          reader.getEmail() == null ||
171          reader.getLastName() == null ||
172          reader.getUid() == null) {
173             String message = resourceBundleMessageSource.getMessage(
174                "error.reader.insert.missing.data",
175                new Object[] { reader==null?"":reader.toString() },
176                Locale.US);
177             logger.error(message);
178             throw new LibraryException(message);
179         }
180         
181         if (logger.isDebugEnabled()) {
182             logger.debug( resourceBundleMessageSource.getMessage(
183                "inserting.reader",
184                new Object[] {reader}, Locale.US));
185         }
186         
187         try {
188             jdbcTemplate.update(insertReaderSQL,
189              new Object [] {
190                 StringUtils.replace
191                  (reader.getFirstName(),Constants.APOSTROPHE,
192                  Constants.ESCAPED_APOSTROPHE),
193                 StringUtils.replace
194                  (reader.getLastName(),Constants.APOSTROPHE,
195                  Constants.ESCAPED_APOSTROPHE),
196                 StringUtils.replace
197                  (reader.getEmail(),Constants.APOSTROPHE,
198                  Constants.ESCAPED_APOSTROPHE),
199                 reader.normalizePhone(reader.getDeskPhone()),
200                 reader.normalizePhone(reader.getMobilePhone()),
201                 StringUtils.replace
202                  (reader.getPager(),Constants.APOSTROPHE,
203                  Constants.ESCAPED_APOSTROPHE),
204                 StringUtils.replace
205                  (reader.getScreenName(), Constants.APOSTROPHE,
206                  Constants.ESCAPED_APOSTROPHE),
207                 StringUtils.replace
208                  (reader.getUid(),Constants.APOSTROPHE,
209                  Constants.ESCAPED_APOSTROPHE),
210                 StringUtils.replace
211                  (crypto.encrypt(reader.getPwd()),Constants.APOSTROPHE,
212                  Constants.ESCAPED_APOSTROPHE),
213                 StringUtils.replace
214                  (reader.getImService(),Constants.APOSTROPHE,
215                  Constants.ESCAPED_APOSTROPHE)
216             },
217              new int[] {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
218                     Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
219                     Types.VARCHAR, Types.VARCHAR, Types.VARCHAR}
220             );
221         } catch (org.springframework.dao.DataIntegrityViolationException se) {
222             String errString = resourceBundleMessageSource.getMessage(
223                "dataintegrity.error.reader.insert.sql",
224                new Object[] { reader.toString()}, Locale.US);
225             logger.error(errString,se);
226             throw new DuplicateReaderException(errString,se);
227         } catch (Exception se) {
228             String errString = resourceBundleMessageSource.getMessage(
229                "error.reader.insert.sql",
230                new Object[] { reader.toString()}, Locale.US);
231             logger.error(errString,se);
232             throw new LibraryException(errString,se);
233         }
234         
235         try {
236             // add reader role to this uid
237             jdbcTemplate.update(insertUserRoleSQL,
238                new Object [] {reader.getUid()}, 
239                new int[] {Types.VARCHAR}
240             );
241         } catch (Exception se) {
242             String errString = resourceBundleMessageSource.getMessage(
243                "error.new.reader.insert.role.sql",
244                new Object[] {reader.toString()}, Locale.US);
245             logger.error(errString,se);
246             throw new LibraryException(errString,se);
247         }
248         
249         try {
250             // Get the new ID and update this.id  
251             List rows;
252             rows = jdbcTemplate.queryForList(selectReaderIdByUidSQL,
253                new Object[] {reader.getUid()});
254             
255             Iterator it = rows.iterator();
256             if (it.hasNext()) {
257                 Map record = (Map) it.next();
258                 reader.setId(
259                    new Long(((Integer) Utils.getIgnoreCase(
260                    record, "ID")).longValue()));
261             }
262         } catch (Exception se) {
263             String errString = resourceBundleMessageSource.getMessage(
264                 "error.reader.new.insert.read.sql",
265                 new Object[] { reader.toString()}, Locale.US);
266             logger.error(errString,se);
267             throw new LibraryException(errString,se);
268         }
269         
270         if (logger.isDebugEnabled()) {
271             logger.debug(resourceBundleMessageSource.getMessage(
272                "reader.insert.successful",
273                new Object[] {reader.toString() }, Locale.US));
274         }
275     }
276     
277     /**
278      * Update Reader in the database, using the UID of the Reader to
279      * locate the database record.
280      *
281      * @throws LibraryException if reader is null or contains insufficient data
282      */
283     public void update(Reader reader) throws LibraryException {
284         if (reader == null ||
285          reader.getFirstName() == null ||
286          reader.getEmail() == null ||
287          reader.getLastName() == null ||
288          reader.getUid() == null) {
289             String message = resourceBundleMessageSource.getMessage(
290                     "error.reader.update.missing.data",
291              new Object[] { (reader==null?"":reader.toString()) },
292              Locale.US);
293             logger.error(message);
294             throw new LibraryException(message);
295         }
296         
297         if (logger.isDebugEnabled()) {
298             logger.debug( resourceBundleMessageSource.getMessage(
299                "updating.reader",
300                new Object[] { reader.toString() }, Locale.US));
301         }
302         
303         try {
304             jdbcTemplate.update(updateReaderSQL,
305              new Object [] {
306                 StringUtils.replace
307                  (reader.getLastName(),Constants.APOSTROPHE,
308                  Constants.ESCAPED_APOSTROPHE),
309                 StringUtils.replace
310                  (reader.getFirstName(),Constants.APOSTROPHE,
311                  Constants.ESCAPED_APOSTROPHE),
312                 StringUtils.replace
313                  (reader.getEmail(),Constants.APOSTROPHE,
314                  Constants.ESCAPED_APOSTROPHE),
315                 reader.normalizePhone(reader.getDeskPhone()),
316                 reader.normalizePhone(reader.getMobilePhone()),
317                 StringUtils.replace
318                  (reader.getPager(),Constants.APOSTROPHE,
319                  Constants.ESCAPED_APOSTROPHE),
320                 StringUtils.replace
321                  (reader.getScreenName(), Constants.APOSTROPHE,
322                  Constants.ESCAPED_APOSTROPHE),
323                 StringUtils.replace
324                  (reader.getImService(),Constants.APOSTROPHE,
325                  Constants.ESCAPED_APOSTROPHE),
326                 StringUtils.replace
327                  (reader.getUid(),Constants.APOSTROPHE,
328                  Constants.ESCAPED_APOSTROPHE)
329             },
330             new int[] {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
331                     Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
332                     Types.VARCHAR, Types.VARCHAR, Types.VARCHAR}
333             );
334             
335             // synch admin status in the database
336             persistAdminStatus(reader);
337         } catch (Exception se) {
338             String errString = resourceBundleMessageSource.getMessage(
339                "error.reader.update",
340                new Object[] { reader.toString() }, Locale.US);
341             logger.error(errString,se);
342             throw new LibraryException(errString,se);
343         }
344         
345         if (logger.isDebugEnabled()) {
346             logger.debug(resourceBundleMessageSource.getMessage(
347                "reader.update.successful",
348                new Object[] {reader.toString() }, Locale.US));
349         }
350     }
351     
352     /**
353      * Retrieve Reader from the database
354      * @return Reader - Fully populated Reader object, or NULL if a record
355      * matching criteria could not be located in the DB
356      *
357      * @throws LibraryException
358      */
359     public Reader retrieve(Reader rd) throws LibraryException {
360         if (rd == null) {
361             String message = resourceBundleMessageSource.getMessage(
362                "error.reader.retrieve", null, Locale.US);
363             logger.error(message);
364             throw new LibraryException( message );
365         }
366         return retrieveById(rd.getId());
367     }
368     
369     /**
370      * Retrieve Reader by id from the database
371      * @return Reader - Fully populated Reader object, or NULL if a record
372      * matching criteria could not be located in the DB
373      *
374      * @throws LibraryException
375      */
376     public Reader retrieveById( long id ) throws LibraryException {
377         return retrieveByGenericCriteria(selectReaderByIdSQL,
378                 new Object[] { new Long(id) } );
379     }
380     
381     
382     /**
383      * Retrieve Reader by uid from the database
384      * @return Reader - Fully populated Reader object, or NULL if a record
385      * matching criteria could not be located in the DB
386      *
387      * @throws LibraryException
388      */
389     public Reader retrieveByUid(String uid) throws LibraryException {
390         return retrieveByGenericCriteria(selectReaderIdByUidSQL,
391                 new Object[] { uid } );
392     }
393     
394     /**
395      * Retrieve Reader by deskphone from the database
396      * @return Reader - Fully populated Reader object, or NULL if a record
397      * matching criteria could not be located in the DB
398      *
399      * @throws LibraryException
400      */
401     public Reader retrieveByPhone(String deskphone) throws LibraryException {
402         return retrieveByGenericCriteria(
403                 selectReaderByDeskPhoneSQL, new Object[] {deskphone});
404     }
405     
406     /**
407      * Retrieve Reader by first and last name from the database
408      * @return Reader - Fully populated Reader object, or NULL if a record
409      * matching criteria could not be located in the DB
410      *
411      * @throws LibraryException
412      */
413     public Reader retrieveByFirstLastName(String firstName, String lastName)
414     throws LibraryException {
415         return retrieveByGenericCriteria(selectReaderByFirstLastNameSQL,
416          new Object[] {firstName, lastName});
417     }
418     
419     /**
420      * Retrieve Reader using a parameterized query.
421      *
422      * @param sqlString - Parameterized SQL query
423      * @param criteria - Query parameters
424      * @return Reader - Fully populated Reader object, or NULL if a record
425      * matching criteria could not be located in the DB
426      * @throws LibraryException if an error occurs retrieving the reader
427      */
428     public Reader retrieveByGenericCriteria(String sqlString, 
429             Object[] criteria) throws LibraryException {
430         if (logger.isDebugEnabled()) {
431             logger.debug(resourceBundleMessageSource.getMessage(
432                "retrieving.reader", criteria, Locale.US));
433         }
434         
435         Reader reader = null;
436         try {
437             List rows = jdbcTemplate.queryForList(sqlString, criteria);
438             reader = loadReaderProperties(rows);
439         } catch (Exception se) {
440             String errString = resourceBundleMessageSource.getMessage(
441                "error.reader.retrieve", criteria, Locale.US);
442             logger.error(errString,se);
443             throw new LibraryException(errString,se);
444         }
445         
446         if (logger.isDebugEnabled()) {
447             logger.debug(resourceBundleMessageSource.getMessage(
448                "reader.retrieve.successful",
449                new Object[] {reader==null?null:reader.toString()},Locale.US));
450         }
451         
452         return reader;
453     }
454     
455     /**
456      * Populates Reader from DB record.  Input List is assumed to consist of
457      * Map instances, each representing a record in the database. The first
458      * element of the list is used to populate the Reader.  Returns null if
459      * the input list is emppty (but not null).
460      *
461      * @param List List containing DB records (each record is a Map)
462      * @return Reader Populated Reader object or null if list is empty
463      * @throws LibraryException - if the input list is null
464      */
465     private Reader loadReaderProperties(List rs)
466     throws LibraryException {
467         if (rs == null) {
468             String errString = resourceBundleMessageSource.getMessage(
469                "error.reader.retrieve", new Object[] {rs}, Locale.US);
470             logger.error(errString);
471             throw new LibraryException(errString);
472         }
473         Reader reader = null;
474         Iterator it = rs.iterator();
475         if (it.hasNext()) {
476             Map record = (Map)it.next();
477             reader = loadReaderPropertiesfromRecord(record);
478         }
479         return reader;
480     }
481     
482     /**
483      * Populates a List of Readers from a resultset.  The resultset is
484      * represented by a List of Map instances, each representing a Reader
485      * in the database.
486      *
487      * @param List List containing DB records (each record is a Map)
488      * @return List of Readers - Populated Reader instances
489      * @throws NullPointerException if rs is null
490      */
491     private List loadAllReadersProperties(List rs)
492     throws LibraryException {
493         Reader reader = null;
494         Iterator it = rs.iterator();
495         List list = new ArrayList();
496         while(it.hasNext()) {
497             reader = new Reader();
498             Map record = (Map) it.next();
499             reader = loadReaderPropertiesfromRecord(record);
500             list.add(reader);
501         }
502         return list;
503     }
504     
505     /**
506      * Populates Reader from a Map with keys <-> field names
507      * and values <-> field values.
508      *
509      * @param record Map whose keys are field names and values are field values
510      * @return Reader Populated Reader object
511      * @throws NullPointerException if record is null
512      */
513     private Reader loadReaderPropertiesfromRecord( Map record )
514     throws LibraryException {
515         Reader reader = new Reader();
516         
517         reader.setId((Integer) Utils.getIgnoreCase(record,"ID"));
518         reader.setLastName((String) Utils.getIgnoreCase(record,"LASTNAME"));
519         reader.setFirstName((String) Utils.getIgnoreCase(record,"FIRSTNAME"));
520         reader.setEmail((String) Utils.getIgnoreCase(record,"EMAIL"));
521         reader.setDeskPhone((String) Utils.getIgnoreCase(record,"DESK_PHONE"));
522         reader.setMobilePhone((String) Utils.getIgnoreCase(record,"MOBILE_PHONE"));
523         reader.setPager((String) Utils.getIgnoreCase(record,"PAGER"));
524         reader.setScreenName((String) Utils.getIgnoreCase(record,"SCREEN_NAME"));
525         reader.setUid((String) Utils.getIgnoreCase(record,"UID"));
526         reader.setImService((String) Utils.getIgnoreCase(record,"IM_SERVICE"));
527         String adminStatus = (String) Utils.getIgnoreCase(record,"ROLE");
528         
529         if (adminStatus != null &&
530          adminStatus.compareToIgnoreCase("administrator") == 0) {
531             reader.setAdministrator( true );
532         }
533         
534         return reader;
535     }
536     
537     /**
538      * Persists admin status in reader instance to database, using UID as key.
539      */
540     private void persistAdminStatus(Reader reader) throws LibraryException {
541         if (logger.isDebugEnabled()) {
542             logger.debug( resourceBundleMessageSource.getMessage(
543                "updating.reader.role",
544                new Object[] { reader.toString() }, Locale.US));
545         }
546         
547         try {
548             boolean durableStatus = false;
549             List rows;
550             rows = jdbcTemplate.queryForList(selectReaderAdminRoleSQL,
551              new Object[] {
552                 StringUtils.replace(reader.getUid(),
553                  Constants.APOSTROPHE,
554                  Constants.ESCAPED_APOSTROPHE)});
555             
556             Iterator it = rows.iterator();
557             if (it.hasNext()) {
558                 durableStatus = true;
559             }
560             
561             if (reader.isAdministrator() != durableStatus) {
562                 String sql = "";
563                 if (durableStatus) {
564                     // demote
565                     sql = deleteReaderAdminRoleSQL;
566                 } else {
567                     // promote
568                     sql = insertReaderAdminRoleSQL;
569                 }
570                 
571                 jdbcTemplate.update(sql,
572                     new Object [] {
573                       StringUtils.replace(reader.getUid(),
574                       Constants.APOSTROPHE,
575                       Constants.ESCAPED_APOSTROPHE)},
576                     new int[] {Types.VARCHAR});
577             }
578         } catch(Exception se) {
579             String errString = resourceBundleMessageSource.getMessage(
580               "error.reader.role.update",
581               new Object[] {reader.toString()}, Locale.US);
582             logger.error(errString,se);
583             throw new LibraryException(errString,se);
584         }
585         
586         if (logger.isDebugEnabled()) {
587             logger.debug(resourceBundleMessageSource.getMessage(
588                "reader.role.update.successful",
589                new Object[] {reader.toString()}, Locale.US));
590         }
591     }
592     
593     /**
594      * Checks to see if a Reader uid exists in the database
595      *
596      * @param uid = uid to look for
597      * @exception LibraryException
598      */
599     public boolean uidExists(String uid)
600     throws LibraryException {
601         if (retrieveByUid( uid ) != null) {
602             return true;
603         } else {
604             return false;
605         }
606     }
607     
608     /**
609      * Checks to see if a Reader id exists in the database
610      *
611      * @param id = id to look for
612      * @exception LibraryException
613      */
614     public boolean readerExists(long id)
615     throws LibraryException {
616         if (retrieveById( id ) != null) {
617             return true;
618         } else {
619             return false;
620         }
621     }
622     
623     /**
624      * Checks to see if a Reader with a specified deskphone exists in the database
625      *
626      * @param deskphone = deskphone to look for
627      * @exception LibraryException
628      */
629     public boolean readerExists(String deskphone)
630     throws LibraryException {
631         if (retrieveByPhone( deskphone ) != null) {
632             return true;
633         } else {
634             return false;
635         }
636     }
637     
638     /**
639      * Checks to see if a Reader with a specified deskphone exists in the database
640      *
641      * @param deskphone = deskphone to look for
642      * @exception LibraryException
643      */
644     public boolean deskPhoneExists(String deskphone)
645     throws LibraryException {
646         return readerExists(deskphone);
647     }
648     
649     /**
650      * Checks to see if a reader with the given first and last name is
651      * registered in the database.
652      *
653      * @param firstName = reader's first name
654      * @param lastName = reader's last name
655      * @exception LibraryException
656      */
657     public boolean readerExists(String firstName, String lastName)
658     throws LibraryException {
659         if (retrieveByFirstLastName( firstName, lastName ) != null) {
660             return true;
661         } else {
662             return false;
663         }
664     }
665     
666     /**
667      * Retrive all Readers from the database
668      *
669      * @return ArrayList of Readers - Fully populated Reader objects, or empty
670      * if no readers could be located in the DB
671      * @throws LibraryException
672      */
673     public ArrayList getReaders()
674     throws LibraryException {
675         if (logger.isDebugEnabled()) {
676             logger.debug( resourceBundleMessageSource.getMessage(
677               "retrieving.readers", null, Locale.US));
678         }
679         
680         ArrayList list = new ArrayList();
681         try {
682             List rows = jdbcTemplate.queryForList(selectAllReadersSQL,
683                     new Object[] { } );
684             list = (ArrayList) loadAllReadersProperties(rows);
685         } catch (Exception se) {
686             String errString = resourceBundleMessageSource.getMessage(
687                "error.readers.retrieve", null, Locale.US);
688             logger.error(errString,se);
689             throw new LibraryException(errString,se);
690         }
691         
692         if (logger.isDebugEnabled()) {
693             logger.debug(resourceBundleMessageSource.getMessage(
694               "readers.retrieve.successful",
695               new Object[] { list }, Locale.US));
696         }
697         
698         return list;
699     }
700     
701     /**
702      * Looks up the ID of a reader from first and last name.
703      * Does not check for uniqueness -- returns the first one
704      * @param firstName = first name of the reader
705      * @param lastName = last name of the reader
706      * @throws LibraryException if there is no such reader
707      */
708     public long getReaderID(String firstName,String lastName)
709     throws LibraryException {
710         Reader reader = retrieveByFirstLastName( firstName, lastName );
711         if ( reader != null ) {
712             return reader.getId();
713         } else {
714             String errString = resourceBundleMessageSource.getMessage(
715               "error.reader.retrieve",
716                new Object[] { "firstname=" + firstName + "," +
717                "lastname=" + lastName }, Locale.US);
718             logger.error( errString );
719             throw new LibraryException(errString);
720         }
721     }
722     
723     /**
724      * Resets user's password
725      * @param user = uid
726      * @param newPwd = new password
727      * @exception LibraryException - mostly for DB access, HOWEVER it will not
728      * throw any error if the user does not exist in the DB!
729      */
730     public void resetPassword(String user, String newPwd)
731     throws LibraryException {
732         if (user == null || newPwd == null ) {
733             String message = resourceBundleMessageSource.getMessage(
734               "error.reader.update.missing.data",
735                new Object[] { user==null?"":user.toString() }, Locale.US);
736             logger.error(message);
737             throw new LibraryException( message );
738         }
739         
740         if (logger.isDebugEnabled()) {
741             logger.debug( resourceBundleMessageSource.getMessage(
742                "updating.reader",
743                 new Object[] { user + ", " + newPwd }, Locale.US));
744         }
745         
746         try {
747             jdbcTemplate.update(updateReaderPasswordSQL,
748              new Object [] {
749                 StringUtils.replace
750                  (crypto.encrypt(newPwd),Constants.APOSTROPHE,
751                  Constants.ESCAPED_APOSTROPHE),
752                 StringUtils.replace
753                  (user,Constants.APOSTROPHE,
754                  Constants.ESCAPED_APOSTROPHE)
755             },
756              new int[] {Types.VARCHAR, Types.VARCHAR}
757             );
758         } catch (Exception se) {
759             String errString = resourceBundleMessageSource.getMessage(
760               "error.reader.update",
761                new Object[] { user + ", " + newPwd },Locale.US);
762             logger.error(errString,se);
763             throw new LibraryException(errString,se);
764         }
765         
766         if (logger.isDebugEnabled()) {
767             logger.debug(resourceBundleMessageSource.getMessage(
768               "reader.update.successful",
769               new Object[] {user + ", " + newPwd }, Locale.US));
770         }
771             
772     }
773     
774     public ReaderDAOSpringJDBCImpl() {
775     }
776 }