1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.psmlmanager.db;
18
19 import java.sql.Connection;
20
21
22 import org.apache.jetspeed.services.psmlmanager.PsmlManagerService;
23
24
25
26 import org.apache.jetspeed.services.JetspeedSecurity;
27
28
29 import org.apache.jetspeed.om.profile.Profile;
30 import org.apache.jetspeed.om.profile.ProfileLocator;
31 import org.apache.jetspeed.om.profile.QueryLocator;
32 import org.apache.jetspeed.services.Profiler;
33 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
34 import org.apache.jetspeed.services.logging.JetspeedLogger;
35
36
37 import org.apache.jetspeed.om.profile.Portlets;
38 import org.apache.jetspeed.om.profile.PSMLDocument;
39 import org.apache.jetspeed.om.profile.BasePSMLDocument;
40
41
42 import org.apache.turbine.services.TurbineBaseService;
43 import org.apache.turbine.services.InitializationException;
44 import org.apache.turbine.services.TurbineServices;
45 import org.apache.turbine.services.resources.ResourceService;
46 import org.apache.turbine.services.servlet.TurbineServlet;
47 import org.apache.turbine.services.servlet.ServletService;
48
49
50 import org.apache.torque.Torque;
51
52
53 import org.apache.jetspeed.om.security.JetspeedUser;
54 import org.apache.jetspeed.om.security.JetspeedUserFactory;
55 import org.apache.jetspeed.om.security.Role;
56 import org.apache.jetspeed.om.security.JetspeedRoleFactory;
57 import org.apache.jetspeed.om.security.Group;
58 import org.apache.jetspeed.om.security.JetspeedGroupFactory;
59 import org.apache.jetspeed.services.security.JetspeedSecurityException;
60
61
62 import javax.servlet.ServletConfig;
63
64
65 import org.apache.jetspeed.om.dbpsml.JetspeedUserProfile;
66 import org.apache.jetspeed.om.dbpsml.JetspeedUserProfilePeer;
67 import org.apache.jetspeed.om.dbpsml.JetspeedRoleProfile;
68 import org.apache.jetspeed.om.dbpsml.JetspeedRoleProfilePeer;
69 import org.apache.jetspeed.om.dbpsml.JetspeedGroupProfile;
70 import org.apache.jetspeed.om.dbpsml.JetspeedGroupProfilePeer;
71
72
73 import java.lang.Thread;
74 import java.util.List;
75 import java.util.Iterator;
76 import java.util.StringTokenizer;
77 import java.util.ArrayList;
78 import java.util.Map;
79 import java.util.HashMap;
80 import java.io.FileReader;
81 import java.io.File;
82
83 import org.exolab.castor.mapping.Mapping;
84 import org.xml.sax.InputSource;
85
86
87 /***
88 * This service is responsible for loading and saving PSML documents. It uses
89 * database to persist the PSML documents.
90 *
91 * @author <a href="mailto:adambalk@cisco.com">Atul Dambalkar</a>
92 * @author <a href="mailto:mvaidya@cisco.com">Medha Vaidya</a>
93 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
94 * @version $Id: DatabasePsmlManagerService.java,v 1.35 2004/02/23 03:32:19 jford Exp $
95 */
96 public class DatabasePsmlManagerService extends TurbineBaseService
97 implements DatabasePsmlManager
98 {
99 /***
100 * Static initialization of the logger for this class
101 */
102 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(DatabasePsmlManagerService.class.getName());
103
104 private Map psmlCache = new HashMap();
105
106 /*** The watcher for the document locations */
107 private CacheRefresher refresher = null;
108
109 /*** the base refresh rate for documents */
110 private long refreshRate;
111
112 private final static String REFRESH_RATE = "refresh-rate";
113 private final static long DEFAULT_REFRESH_RATE = 60 * 60 * 8 * 1000;
114
115 /*** whether caching is allowed */
116 private boolean cachingOn;
117
118 private final static String CACHING_ON = "caching-on";
119 private final static boolean DEFAULT_CACHING_ON = false;
120
121 private final static String POOL_NAME = "database";
122
123 /*** the import/export consumer service **/
124 private PsmlManagerService consumer = null;
125
126
127 public static final String DEFAULT_MAPPING = "${webappRoot}/WEB-INF/conf/psml-mapping.xml";
128 String mapFile = null;
129 /*** the Castor mapping file name */
130 private Mapping mapping = null;
131
132 /*** The pool name to use for database requests. */
133 private String poolName = null;
134
135 /***
136 * This is the early initialization method called by the
137 * Turbine <code>Service</code> framework
138 */
139 public void init(ServletConfig conf) throws InitializationException
140 {
141 if (getInit())
142 {
143 return;
144 }
145
146 logger.info("Initializing DatabasePsmlManagerService...");
147 initConfiguration(conf);
148
149 logger.info("Done initializing DatabasePsmlManagerService.");
150
151 }
152
153 /***
154 * Loads the configuration parameters for this service from the
155 * JetspeedResources.properties file.
156 *
157 * @exception throws a <code>InitializationException</code> if the service
158 * fails to initialize
159 */
160 private void initConfiguration(ServletConfig conf)
161 throws InitializationException
162 {
163
164
165 TurbineServices.getInstance().initService(ServletService.SERVICE_NAME, conf);
166
167 ResourceService serviceConf =
168 ((TurbineServices)TurbineServices.getInstance())
169 .getResources(PsmlManagerService.SERVICE_NAME);
170 try
171 {
172
173
174
175 String value = serviceConf.getString(REFRESH_RATE);
176 refreshRate = DEFAULT_REFRESH_RATE;
177 try
178 {
179 refreshRate = Long.parseLong(value);
180 }
181 catch (Exception e)
182 {
183 logger.warn("DatabasePsmlManagerService: error in refresh-rate configuration: using default");
184 }
185
186
187 poolName = serviceConf.getString(POOL_NAME);
188
189
190 value = serviceConf.getString(CACHING_ON);
191 cachingOn = DEFAULT_CACHING_ON;
192 try
193 {
194 cachingOn = value.equals("true");
195 }
196 catch (Exception e)
197 {
198 logger.warn("DatabasePsmlManagerService: error in caching-on configuration: using default");
199 }
200
201
202 mapFile = serviceConf.getString("mapping",DEFAULT_MAPPING);
203 mapFile = TurbineServlet.getRealPath( mapFile );
204 loadMapping();
205 }
206 catch (Throwable t)
207 {
208 logger.error(this + ".init:" , t);
209 throw new InitializationException("Exception initializing DatabasePsmlManagerService" + t);
210 }
211
212 if (cachingOn)
213 {
214 this.refresher = new CacheRefresher();
215 refresher.start();
216 }
217 }
218
219 /*** Late init method from Turbine Service model */
220 public void init() throws InitializationException
221 {
222
223 setInit(true);
224
225
226
227
228
229
230
231
232
233
234
235 }
236
237 protected void loadMapping()
238 throws InitializationException
239 {
240
241
242 if (mapFile != null)
243 {
244 File map = new File(mapFile);
245 if (logger.isDebugEnabled())
246 logger.debug("Loading psml mapping file " + mapFile);
247 if (map.exists() && map.isFile() && map.canRead())
248 {
249 try
250 {
251 mapping = new Mapping();
252 InputSource is = new InputSource( new FileReader(map) );
253 is.setSystemId( mapFile );
254 mapping.loadMapping( is );
255 }
256 catch (Exception e)
257 {
258 logger.error("Error in psml mapping creation",e);
259 throw new InitializationException("Error in mapping",e);
260 }
261 }
262 else
263 {
264 throw new InitializationException("PSML Mapping not found or not a file or unreadable: "+mapFile);
265 }
266 }
267 }
268
269 /***
270 * This is the shutdown method called by the
271 * Turbine <code>Service</code> framework
272 */
273 public void shutdown()
274 {
275 if (this.refresher != null)
276 {
277 this.refresher.setDone(true);
278 }
279 }
280
281
282 /***
283 * A thread implementation of cache refreshing mechanism for database
284 * persisted PSMLs. We have to refresh the cache after specific intervals
285 * if someone manually updates the PSML database.
286 *
287 * @author <a href="mailto:adambalk@cisco.com">Atul Dambalkar</a>
288 */
289 class CacheRefresher extends Thread
290 {
291 private boolean done = false;
292
293 /***
294 * Constructor to to set the priority.
295 */
296 CacheRefresher()
297 {
298 setDaemon(true);
299 setPriority(Thread.MIN_PRIORITY+1);
300 }
301
302 /***
303 * We are all done, system is shutting down.
304 */
305 void setDone(boolean done)
306 {
307 this.done = done;
308 }
309
310 /***
311 * Method as needed for a Thread to run
312 */
313 public void run()
314 {
315 try
316 {
317 while (!done)
318 {
319 if (logger.isDebugEnabled())
320 logger.debug("Cache Refresher thread sleeping now!");
321 sleep (refreshRate);
322 if (logger.isDebugEnabled())
323 logger.debug("Cache Refresher thread working now!");
324
325 try
326 {
327 synchronized (this)
328 {
329 Iterator i = psmlCache.keySet().iterator();
330
331 while(i.hasNext())
332 {
333 String locator = (String)i.next();
334
335
336 PSMLDocument doc =
337 refresh(stringToLocator(locator));
338
339
340 psmlCache.put(locator, doc);
341 }
342 }
343 }
344 catch (Exception e)
345 {
346 logger.warn("DatabasePsmlManagerService.CacheRefresher: Error in cache refresher...", e);
347 }
348 }
349 }
350 catch (InterruptedException e)
351 {
352 if (logger.isDebugEnabled())
353 logger.debug("DatabasePsmlManagerService.CacheRefresher: recieved interruption, aborting.");
354 }
355 }
356 }
357
358 /***
359 * Return a unique string identifying this object.
360 */
361 private String locatorToString(ProfileLocator locator)
362 {
363 StringBuffer keybuf = new StringBuffer();
364
365 JetspeedUser user = locator.getUser();
366 Role role = locator.getRole();
367 Group group = locator.getGroup();
368 String name = locator.getName();
369 String mediaType = locator.getMediaType();
370 String country = locator.getCountry();
371 String language = locator.getLanguage();
372
373 synchronized (this)
374 {
375 if (user != null)
376 {
377 keybuf.append("User:").append(user.getUserName());
378 }
379 else if (group != null)
380 {
381 keybuf.append("Group:").append(group.getName());
382 }
383 else if (role != null)
384 {
385 keybuf.append("Role:").append(role.getName());
386 }
387
388 if (name != null)
389 {
390 keybuf.append('$').append("Page:").append(name);
391 }
392
393 if (mediaType != null)
394 {
395 keybuf.append('$').append("MediaType:").append(mediaType);
396 }
397 if (country != null && (! country.equals("-1")))
398 {
399 keybuf.append('$').append("Country:").append(country);
400 }
401 if (language != null && (! language.equals("-1")))
402 {
403 keybuf.append('$').append("Language:").append(language);
404 }
405 }
406 if (logger.isDebugEnabled())
407 logger.debug("DatabasePsmlManagerService: Returning locator string: " + keybuf.toString());
408
409 return keybuf.toString();
410 }
411
412 private ProfileLocator stringToLocator(String locstr) throws Exception
413 {
414 ProfileLocator locator = Profiler.createLocator();
415 String entity = null;
416
417 if (logger.isDebugEnabled())
418 logger.debug("DatabasePsmlManagerService: Creating locator for string: " + locstr);
419
420 StringTokenizer dollarTokens = new StringTokenizer(locstr, "$");
421 while (dollarTokens.hasMoreTokens())
422 {
423 String dollarToken = dollarTokens.nextToken().trim();
424
425 StringTokenizer colonTokens = new StringTokenizer(dollarToken, ":");
426 String colonToken = colonTokens.nextToken();
427 if (colonToken.equals("User"))
428 {
429 entity = colonTokens.nextToken().trim();
430 locator.setUser(JetspeedSecurity.getUser(entity));
431 }
432 else if (colonToken.equals("Group"))
433 {
434 entity = colonTokens.nextToken().trim();
435 locator.setGroup(JetspeedSecurity.getGroup(entity));
436 }
437 else if (colonToken.equals("Role"))
438 {
439 entity = colonTokens.nextToken().trim();
440 locator.setRole(JetspeedSecurity.getRole(entity));
441 }
442 else if (colonToken.equals("Page"))
443 {
444 entity = colonTokens.nextToken().trim();
445 locator.setName(entity);
446 }
447 else if (colonToken.equals("MediaType"))
448 {
449 entity = colonTokens.nextToken().trim();
450 locator.setMediaType(entity);
451 }
452 else if (colonToken.equals("Country"))
453 {
454 entity = colonTokens.nextToken().trim();
455 locator.setCountry(entity);
456 }
457 else if (colonToken.equals("Language"))
458 {
459 entity = colonTokens.nextToken().trim();
460 locator.setLanguage(entity);
461 }
462 }
463 if (logger.isDebugEnabled())
464 logger.debug("DatabasePsmlManagerService: Returning locator for string: " + locatorToString(locator));
465
466 return locator;
467
468 }
469
470 public PSMLDocument getDocument(String name)
471 {
472
473 logger.warn("*** NOT SUPPORTED: GETDOC FROM DATABASE PSML MANAGER!!!");
474 return null;
475 }
476
477 public boolean saveDocument(String fileOrUrl, PSMLDocument doc)
478 {
479
480 logger.warn("*** NOT SUPPORTED: SAVING DOC FROM DATABASE PSML MANAGER!!!");
481 return false;
482 }
483
484 public boolean saveDocument(PSMLDocument doc)
485 {
486
487 logger.warn("*** NOT SUPPORTED: SAVING DOC FROM DATABASE PSML MANAGER!!!");
488 return false;
489 }
490
491
492 /***
493 * Returns a PSML document for the given locator
494 *
495 * @param locator The locator descriptor(ProfileLocator object) of the
496 * document to be retrieved.
497 * @return psmldoc The PSMLDocument object
498 */
499 public PSMLDocument getDocument(ProfileLocator locator)
500 {
501
502
503
504 if (locator == null)
505 {
506 String message = "PSMLManager: Must specify a locator";
507 logger.warn("DatabasePsmlManagerService.getDocument: " + message);
508 throw new IllegalArgumentException(message);
509 }
510
511 PSMLDocument psmldoc = null;
512 String locStr = locatorToString(locator);
513 boolean inCache = false;
514
515 if (cachingOn)
516 {
517 synchronized (psmlCache)
518 {
519
520
521
522 inCache = psmlCache.containsKey(locStr);
523 if (inCache)
524 {
525 psmldoc = (PSMLDocument)psmlCache.get(locStr);
526 }
527 }
528
529
530
531
532
533 if (inCache)
534 {
535 return psmldoc;
536 }
537 }
538
539
540 try
541 {
542 return refresh(locator);
543 }
544 catch (Exception e)
545 {
546 logger.warn("DatabasePSMLManagerService.getDocument: exception:", e);
547 throw new RuntimeException("Could not get profile from DB");
548 }
549 }
550
551 /***
552 * Stores the PSML document in DB for the given profile
553 *
554 * @param profile The profile that holds the PSMLDocument.
555 * @return PSMLDocument The PSMLDocument that got created in DB.
556 */
557 public PSMLDocument createDocument(Profile profile)
558 {
559 return createOrSaveDocument(profile, INSERT);
560 }
561
562 /***
563 * Update the PSML document in DB for the given profile
564 *
565 * @param profile The profile that holds the PSMLDocument.
566 * @return PSMLDocument The PSMLDocument that got created in DB.
567 */
568 public boolean store(Profile profile)
569 {
570 return createOrSaveDocument(profile, UPDATE) != null;
571 }
572
573 private PSMLDocument createOrSaveDocument(Profile profile, int operation)
574 {
575
576
577
578 if (profile == null)
579 {
580 String message = "PSMLManager: Must specify a profile";
581 logger.warn("DatabasePsmlManagerService.createOrSaveDocument: " + message);
582 throw new IllegalArgumentException(message);
583 }
584
585 JetspeedUser user = profile.getUser();
586 Role role = profile.getRole();
587 Group group = profile.getGroup();
588 String tableName = null;
589
590 Connection dbCon = getDbConnection();
591
592 try
593 {
594 if (user != null)
595 {
596 tableName = "JETSPEED_USER_PROFILE";
597 if (operation == INSERT)
598 {
599 new JetspeedUserProfilePeer().insert(profile, dbCon);
600 }
601 else if (operation == UPDATE)
602 {
603 new JetspeedUserProfilePeer().update(profile, dbCon);
604 }
605 }
606 else if (role != null)
607 {
608 tableName = "JETSPEED_ROLE_PROFILE";
609 if (operation == INSERT)
610 {
611 new JetspeedRoleProfilePeer().insert(profile, dbCon);
612 }
613 else if (operation == UPDATE)
614 {
615 new JetspeedRoleProfilePeer().update(profile, dbCon);
616 }
617 }
618 else if (group != null)
619 {
620 tableName = "JETSPEED_GROUP_PROFILE";
621 if (operation == INSERT)
622 {
623 new JetspeedGroupProfilePeer().insert(profile, dbCon);
624 }
625 else if (operation == UPDATE)
626 {
627 new JetspeedGroupProfilePeer().update(profile, dbCon);
628 }
629 }
630
631 if (cachingOn)
632 {
633
634 synchronized (psmlCache)
635 {
636 if (logger.isDebugEnabled())
637 logger.debug("DatabasePsmlManagerService.createOrSaveDocument: caching document: profile: " + locatorToString(profile));
638 psmlCache.put(locatorToString(profile), profile.getDocument());
639 }
640 }
641
642 return profile.getDocument();
643 }
644 catch (Exception e)
645 {
646 logger.warn("DatabasePsmlManagerService.createOrSaveDocument: profile: "
647 + profile + " tableName: " + tableName, e);
648 throw new RuntimeException("Could not create new profile in DB");
649 }
650 finally
651 {
652
653 releaseDbConnection(dbCon);
654 }
655
656 }
657
658 /***
659 * Remove the PSMLDocument/profile for given locator object.
660 *
661 * @param locator The profile locator criteria for profile to be removed.
662 */
663 public void removeDocument(ProfileLocator locator)
664 {
665 if (locator == null)
666 {
667 String message = "PSMLManager: Must specify a locator";
668 logger.warn("DatabasePsmlManagerService.removeDocument: " + message);
669 throw new IllegalArgumentException(message);
670 }
671
672 JetspeedUser user = locator.getUser();
673 Role role = locator.getRole();
674 Group group = locator.getGroup();
675 String tableName = null;
676
677
678 Connection dbCon = getDbConnection();
679
680 try
681 {
682 if (user != null)
683 {
684 new JetspeedUserProfilePeer().delete(locator, dbCon);
685 tableName = "JETSPEED_USER_PROFILE";
686 }
687 else if (role != null)
688 {
689 new JetspeedRoleProfilePeer().delete(locator, dbCon);
690 tableName = "JETSPEED_ROLE_PROFILE";
691 }
692 else if (group != null)
693 {
694 new JetspeedGroupProfilePeer().delete(locator, dbCon);
695 tableName = "JETSPEED_GROUP_PROFILE";
696 }
697
698 if (cachingOn)
699 {
700
701 synchronized (psmlCache)
702 {
703 psmlCache.remove(locatorToString(locator));
704 }
705 }
706 }
707 catch (Exception e)
708 {
709 logger.warn("DatabasePsmlManagerService.removeDocument: profile: "
710 + locatorToString(locator) + " tableName: " + tableName, e);
711 throw new RuntimeException("Could not delete profile for given locator from DB");
712 }
713 finally
714 {
715
716 releaseDbConnection(dbCon);
717 }
718 }
719
720 /***
721 * Query for a collection of profiles given a profile locator criteria.
722 * Use SQL engine to get the required profiles.
723 *
724 * @param locator The profile locator criteria.
725 * @return Iterator object with the PSMLDocuments satisfying query
726 */
727 public Iterator query(QueryLocator locator)
728 {
729 if (locator == null)
730 {
731 String message = "PSMLManager: Must specify a locator";
732 logger.warn("DatabasePsmlManagerService.query: " + message);
733 throw new IllegalArgumentException(message);
734 }
735
736 Connection dbCon = getDbConnection();
737
738 try
739 {
740 List userData = null;
741 List groupData = null;
742 List roleData = null;
743
744 int queryMode = locator.getQueryMode();
745
746 List list = new ArrayList();
747
748 switch (queryMode)
749 {
750 case QueryLocator.QUERY_USER:
751 userData = new JetspeedUserProfilePeer().selectOrdered(locator, dbCon);
752 if (userData != null)
753 {
754 list = getProfiles(userData);
755 }
756 break;
757
758 case QueryLocator.QUERY_GROUP:
759 groupData = new JetspeedGroupProfilePeer().selectOrdered(locator, dbCon);
760 if (groupData != null)
761 {
762 list = getProfiles(groupData);
763 }
764 break;
765
766 case QueryLocator.QUERY_ROLE:
767 roleData = new JetspeedRoleProfilePeer().selectOrdered(locator, dbCon);
768 if (roleData != null)
769 {
770 list = getProfiles(roleData);
771 }
772 break;
773
774
775 default:
776 userData = new JetspeedUserProfilePeer().selectOrdered(locator, dbCon);
777 if (userData != null)
778 {
779 list.addAll(getProfiles(userData));
780 }
781
782 groupData = new JetspeedGroupProfilePeer().selectOrdered(locator, dbCon);
783 if (groupData != null)
784 {
785 list.addAll(getProfiles(groupData));
786 }
787
788 roleData = new JetspeedRoleProfilePeer().selectOrdered(locator, dbCon);
789 if (roleData != null)
790 {
791 list.addAll(getProfiles(roleData));
792 }
793
794 break;
795 }
796
797 return list.iterator();
798 }
799 catch (Exception e)
800 {
801 logger.warn("DatabasePsmlManagerService.query: exception" , e);
802 }
803 finally
804 {
805
806 releaseDbConnection(dbCon);
807 }
808
809 return new ArrayList().iterator();
810 }
811
812 /***
813 * Get profile iterator from given list of objects.
814 *
815 * @param data List of JetspeedUserProfile, JetspeedGroupProfile,
816 * JetspeedRoleProfile, objects
817 * @return List of profiles
818 */
819 private List getProfiles(List data)
820 {
821 List list = new ArrayList();
822
823 for (int i = 0; i < data.size(); i++)
824 {
825 Object obj = data.get(i);
826 Portlets portlets = null;
827
828 if (obj instanceof JetspeedUserProfile)
829 {
830 portlets = DBUtils.bytesToPortlets(((JetspeedUserProfile)obj).getProfile(), this.mapping);
831 list.add(createUserProfile((JetspeedUserProfile)obj, portlets));
832 }
833 else if (obj instanceof JetspeedGroupProfile)
834 {
835 portlets = DBUtils.bytesToPortlets(((JetspeedGroupProfile)obj).getProfile(), this.mapping);
836 list.add(createGroupProfile((JetspeedGroupProfile)obj, portlets));
837 }
838 else if (obj instanceof JetspeedRoleProfile)
839 {
840 portlets = DBUtils.bytesToPortlets(((JetspeedRoleProfile)obj).getProfile(), this.mapping);
841 list.add(createRoleProfile((JetspeedRoleProfile)obj, portlets));
842 }
843
844 }
845 return list;
846 }
847
848
849 /***
850 * Get PSMLDocument object for given pagename and portlets.
851 *
852 * @param portlets Portlets for the given page name
853 * @param page page name for this resource
854 * @return PSMLDocument object for given page and portlets
855 */
856 private PSMLDocument getPSMLDocument(String page, Portlets portlets)
857 {
858 PSMLDocument psmldoc = new BasePSMLDocument();
859 psmldoc.setName(page);
860 psmldoc.setPortlets(portlets);
861 return psmldoc;
862 }
863
864
865 /***
866 * Given ordered list of locators, find the first document matching
867 * a profile locator, starting from the beginning of the list and working
868 * to the end.
869 *
870 * @param locator The ordered list of profile locators.
871 * @return PSMLDocument object for the first document matching a locator
872 */
873 public PSMLDocument getDocument(List locators)
874 {
875 if (locators == null)
876 {
877 String message = "PSMLManager: Must specify a list of locators";
878 logger.warn("DatabasePsmlManagerService.getDocument: " + message);
879 throw new IllegalArgumentException(message);
880 }
881
882
883 for (int i = 0; i < locators.size(); i++)
884 {
885 PSMLDocument psmldoc = getDocument((ProfileLocator)locators.get(i));
886 if (psmldoc != null)
887 {
888 return psmldoc;
889 }
890 }
891 return null;
892 }
893
894 /***
895 * Returns a PSML document for the given locator, it is called by the cache
896 * refresher
897 *
898 * @param locator The locator descriptor(ProfileLocator object) of the
899 * document to be retrieved.
900 * @return psmldoc The PSMLDocument object
901 */
902 public PSMLDocument refresh(ProfileLocator locator)
903 {
904
905
906 if (locator == null)
907 {
908 String message = "PSMLManager: Must specify a locator";
909 logger.warn("DatabasePsmlManagerService.refresh: " + message);
910 throw new IllegalArgumentException(message);
911 }
912
913 JetspeedUser user = locator.getUser();
914 Role role = locator.getRole();
915 Group group = locator.getGroup();
916 String tableName = null;
917 List records = null;
918 Portlets portlets = null;
919 PSMLDocument psmldoc = null;
920 String page = null;
921
922 Connection dbCon = getDbConnection();
923
924 try
925 {
926 if (user != null)
927 {
928 tableName = "JETSPEED_USER_PROFILE";
929 records = new JetspeedUserProfilePeer().select(locator, dbCon);
930 Iterator iterator = records.iterator();
931 while (iterator.hasNext())
932 {
933 JetspeedUserProfile uprofile =
934 (JetspeedUserProfile)iterator.next();
935 page = uprofile.getPage();
936 portlets = DBUtils.bytesToPortlets(uprofile.getProfile(), this.mapping);
937 }
938 }
939 else if (role != null)
940 {
941 tableName = "JETSPEED_ROLE_PROFILE";
942 records = new JetspeedRoleProfilePeer().select(locator, dbCon);
943 Iterator iterator = records.iterator();
944 while (iterator.hasNext())
945 {
946 JetspeedRoleProfile rprofile =
947 (JetspeedRoleProfile)iterator.next();
948 page = rprofile.getPage();
949 portlets = DBUtils.bytesToPortlets(rprofile.getProfile(), this.mapping);
950 }
951 }
952 else if (group != null)
953 {
954 tableName = "JETSPEED_GROUP_PROFILE";
955 records = new JetspeedGroupProfilePeer().select(locator, dbCon);
956 Iterator iterator = records.iterator();
957 while (iterator.hasNext())
958 {
959 JetspeedGroupProfile gprofile =
960 (JetspeedGroupProfile)iterator.next();
961 page = gprofile.getPage();
962 portlets = DBUtils.bytesToPortlets(gprofile.getProfile(), this.mapping);
963 }
964 }
965
966 if (page != null && portlets != null)
967 {
968 psmldoc = getPSMLDocument(page, portlets);
969 if (cachingOn)
970 {
971 synchronized (psmlCache)
972 {
973 if (logger.isDebugEnabled())
974 logger.debug("DatabasePsmlManagerService.refresh: caching document: profile: " + locatorToString(locator));
975 psmlCache.put(locatorToString(locator), psmldoc);
976 }
977 }
978 return psmldoc;
979 }
980 else
981 {
982 if (cachingOn)
983 {
984
985 psmlCache.put(locatorToString(locator), null);
986 if (logger.isDebugEnabled())
987 logger.debug("DatabasePsmlManagerService.refresh: caching 'document not found': profile: " + locatorToString(locator));
988 }
989 }
990 }
991 catch (Exception e)
992 {
993 logger.warn("DatabasePsmlManagerService.refresh: profile: " + locatorToString(locator)
994 + " tableName: " + tableName, e);
995 throw new RuntimeException("Could not refresh profile from DB");
996 }
997 finally
998 {
999
1000 releaseDbConnection(dbCon);
1001 }
1002
1003 if (logger.isDebugEnabled())
1004 logger.debug("DatabasePsmlManagerService.refresh: no document found: profile: "
1005 + locatorToString(locator));
1006 return null;
1007 }
1008
1009 /*** Removes all documents for a given user.
1010 *
1011 * @param user The user object.
1012 */
1013 public void removeUserDocuments(JetspeedUser user)
1014 {
1015 Connection dbCon = getDbConnection();
1016
1017 try
1018 {
1019 if (user != null)
1020 {
1021 new JetspeedUserProfilePeer().delete(user, dbCon);
1022 }
1023 }
1024 catch (Exception e)
1025 {
1026 logger.warn("DatabasePsmlManagerService.removeUserDocuments: exception:", e);
1027 throw new RuntimeException("Could not delete documents for given user from DB");
1028 }
1029 finally
1030 {
1031
1032 releaseDbConnection(dbCon);
1033 }
1034
1035 }
1036
1037 /*** Removes all documents for a given role.
1038 *
1039 * @param role The role object.
1040 */
1041 public void removeRoleDocuments(Role role)
1042 {
1043 Connection dbCon = getDbConnection();
1044
1045 try
1046 {
1047 if (role != null)
1048 {
1049 new JetspeedRoleProfilePeer().delete(role, dbCon);
1050 }
1051 }
1052 catch (Exception e)
1053 {
1054 logger.warn("DatabasePsmlManagerService.removeRoleDocuments: exception:", e);
1055 throw new RuntimeException("Could not delete documents for given role from DB");
1056 }
1057 finally
1058 {
1059
1060 releaseDbConnection(dbCon);
1061 }
1062 }
1063
1064 /*** Removes all documents for a given group.
1065 *
1066 * @param group The group object.
1067 */
1068 public void removeGroupDocuments(Group group)
1069 {
1070 Connection dbCon = getDbConnection();
1071
1072 try
1073 {
1074 if (group != null)
1075 {
1076 new JetspeedGroupProfilePeer().delete(group, dbCon);
1077 }
1078 }
1079 catch (Exception e)
1080 {
1081 logger.warn("DatabasePsmlManagerService.removeGroupDocuments: exception:", e);
1082 throw new RuntimeException("Could not delete documents for given group from DB");
1083 }
1084 finally
1085 {
1086
1087 releaseDbConnection(dbCon);
1088 }
1089 }
1090
1091 /*** Query for a collection of profiles given a profile locator criteria.
1092 * This method should be used when importing or exporting profiles between services.
1093 *
1094 * @param locator The profile locator criteria.
1095 * @return The count of profiles exported.
1096 */
1097 public int export(PsmlManagerService consumer, QueryLocator locator)
1098 {
1099 Iterator profiles = null;
1100 int count = 0;
1101 try
1102 {
1103 this.consumer = consumer;
1104 profiles = query(locator);
1105
1106 while (profiles.hasNext() )
1107 {
1108 Profile profile = (Profile)profiles.next();
1109
1110 try
1111 {
1112 consumer.createDocument(profile);
1113 count++;
1114 }
1115 catch (Exception ex)
1116 {
1117 try
1118 {
1119 consumer.store(profile);
1120 count++;
1121 }
1122 catch (Exception e)
1123 {
1124 logger.warn("DatabasePsmlManagerService.export: profile: "
1125 + profile, ex);
1126 }
1127 }
1128 }
1129 }
1130 catch(Exception e)
1131 {
1132 logger.warn("DatabasePsmlManagerService.export: exception:", e);
1133
1134 }
1135 finally
1136 {
1137 }
1138 return count;
1139 }
1140
1141
1142 public Mapping getMapping()
1143 {
1144 return this.mapping;
1145 }
1146
1147 /***
1148 * Creates a user profile from a JetspeedUserProfile database object.
1149 *
1150 * @param entity The user profile entity in the database.
1151 * @param portlets The PSML blob.
1152 * @return A new profile object representing the locator and PSML blob.
1153 */
1154 public Profile createUserProfile(JetspeedUserProfile entity, Portlets portlets)
1155 {
1156 Profile profile = Profiler.createProfile();
1157 try
1158 {
1159 JetspeedUser user = JetspeedSecurity.getUser(entity.getUserName());
1160 if (null == user)
1161 {
1162 user = JetspeedUserFactory.getInstance();
1163 user.setUserName(entity.getUserName());
1164 }
1165 profile.setUser(user);
1166
1167 profile.setMediaType(entity.getMediaType());
1168 profile.setLanguage(entity.getLanguage());
1169 profile.setCountry(entity.getCountry());
1170 profile.setName(entity.getPage());
1171 profile.setDocument(getPSMLDocument(entity.getPage(), portlets));
1172 }
1173 catch (JetspeedSecurityException e)
1174 {
1175 }
1176 return profile;
1177 }
1178
1179 /***
1180 * Creates a group profile from a JetspeedGroupProfile database object.
1181 *
1182 * @param entity The group profile entity in the database.
1183 * @param portlets The PSML blob.
1184 * @return A new profile object representing the locator and PSML blob.
1185 */
1186 public Profile createGroupProfile(JetspeedGroupProfile entity, Portlets portlets)
1187 {
1188 Profile profile = Profiler.createProfile();
1189 try
1190 {
1191 Group group = JetspeedSecurity.getGroup(entity.getGroupName());
1192 if (null == group)
1193 {
1194 group = JetspeedGroupFactory.getInstance();
1195 group.setName(entity.getGroupName());
1196 }
1197 profile.setGroup(group);
1198 profile.setMediaType(entity.getMediaType());
1199 profile.setLanguage(entity.getLanguage());
1200 profile.setCountry(entity.getCountry());
1201 profile.setName(entity.getPage());
1202 profile.setDocument(getPSMLDocument(entity.getPage(), portlets));
1203 }
1204 catch (JetspeedSecurityException e)
1205 {
1206 }
1207 return profile;
1208 }
1209
1210 /***
1211 * Creates a role profile from a JetspeedRoleProfile database object.
1212 *
1213 * @param entity The group profile entity in the database.
1214 * @param portlets The PSML blob.
1215 * @return A new profile object representing the locator and PSML blob.
1216 */
1217 public Profile createRoleProfile(JetspeedRoleProfile entity, Portlets portlets)
1218 {
1219 Profile profile = Profiler.createProfile();
1220 try
1221 {
1222 Role role = JetspeedSecurity.getRole(entity.getRoleName());
1223 if (null == role)
1224 {
1225 role = JetspeedRoleFactory.getInstance();
1226 role.setName(entity.getRoleName());
1227 }
1228 profile.setRole(role);
1229 profile.setMediaType(entity.getMediaType());
1230 profile.setLanguage(entity.getLanguage());
1231 profile.setCountry(entity.getCountry());
1232 profile.setName(entity.getPage());
1233 profile.setDocument(getPSMLDocument(entity.getPage(), portlets));
1234 }
1235 catch (JetspeedSecurityException e)
1236 {
1237 }
1238 return profile;
1239 }
1240
1241
1242 /***
1243 * Get a database connection to the default or specifed torque database pool
1244 */
1245 private Connection getDbConnection()
1246 {
1247 try
1248 {
1249
1250 if (poolName == null)
1251 {
1252 return Torque.getConnection();
1253 }
1254
1255
1256 else
1257 {
1258 return Torque.getConnection(poolName);
1259 }
1260 }
1261 catch (Exception e)
1262 {
1263 logger.warn("DatabasePsmlManagerService.getDbConnection: exception: " + e);
1264 return null;
1265 }
1266 }
1267
1268 /***
1269 * Release a previously gotten database connection back to the torque pool
1270 */
1271 private void releaseDbConnection(Connection connection)
1272 {
1273 Torque.closeConnection(connection);
1274 }
1275 }
1276