1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.tools.pamanager;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.security.Permission;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.jetspeed.cluster.NodeManager;
30 import org.apache.jetspeed.components.portletentity.PortletEntityAccessComponent;
31 import org.apache.jetspeed.components.portletentity.PortletEntityNotDeletedException;
32 import org.apache.jetspeed.components.portletregistry.PortletRegistry;
33 import org.apache.jetspeed.components.portletregistry.RegistryException;
34 import org.apache.jetspeed.container.window.PortletWindowAccessor;
35 import org.apache.jetspeed.factory.PortletFactory;
36 import org.apache.jetspeed.om.common.portlet.MutablePortletApplication;
37 import org.apache.jetspeed.om.common.servlet.MutableWebApplication;
38 import org.apache.jetspeed.search.SearchEngine;
39 import org.apache.jetspeed.security.PermissionManager;
40 import org.apache.jetspeed.security.PortletPermission;
41 import org.apache.jetspeed.security.Role;
42 import org.apache.jetspeed.security.RoleManager;
43 import org.apache.jetspeed.security.SecurityException;
44 import org.apache.jetspeed.util.DirectoryHelper;
45 import org.apache.jetspeed.util.FileSystemHelper;
46 import org.apache.jetspeed.util.MultiFileChecksumHelper;
47 import org.apache.jetspeed.util.descriptor.PortletApplicationWar;
48 import org.apache.pluto.om.common.SecurityRole;
49 import org.apache.pluto.om.entity.PortletEntity;
50 import org.apache.pluto.om.entity.PortletEntityCtrl;
51 import org.apache.pluto.om.portlet.PortletDefinition;
52
53 /***
54 * PortletApplicationManager
55 *
56 * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
57 * @version $Id: PortletApplicationManager.java,v 1.21 2005/04/09 00:24:44 shinsuke Exp $
58 */
59 public class PortletApplicationManager implements PortletApplicationManagement
60 {
61 private static int DEFAULT_DESCRIPTOR_CHANGE_MONITOR_INTERVAL = 10*1000;
62 private static final Log log = LogFactory.getLog("deployment");
63
64 protected PortletEntityAccessComponent entityAccess;
65 protected PortletFactory portletFactory;
66 protected PortletRegistry registry;
67 protected PortletWindowAccessor windowAccess;
68 protected SearchEngine searchEngine;
69 protected RoleManager roleManager;
70 protected PermissionManager permissionManager;
71 protected boolean autoCreateRoles;
72 protected List permissionRoles;
73 protected int descriptorChangeMonitorInterval = DEFAULT_DESCRIPTOR_CHANGE_MONITOR_INTERVAL;
74 protected DescriptorChangeMonitor monitor;
75 protected boolean started;
76 protected String appRoot;
77 protected NodeManager nodeManager;
78
79 /***
80 * Creates a new PortletApplicationManager object.
81 */
82 public PortletApplicationManager(PortletFactory portletFactory, PortletRegistry registry,
83 PortletEntityAccessComponent entityAccess, PortletWindowAccessor windowAccess,
84 PermissionManager permissionManager, SearchEngine searchEngine,
85 RoleManager roleManager, List permissionRoles, NodeManager nodeManager, String appRoot)
86 {
87 this.portletFactory = portletFactory;
88 this.registry = registry;
89 this.entityAccess = entityAccess;
90 this.windowAccess = windowAccess;
91 this.permissionManager = permissionManager;
92 this.searchEngine = searchEngine;
93 this.roleManager = roleManager;
94 this.permissionRoles = permissionRoles;
95 this.nodeManager = nodeManager;
96 this.appRoot = appRoot;
97 }
98
99 public void start()
100 {
101 if ( descriptorChangeMonitorInterval > 0 )
102 {
103 try
104 {
105 monitor = new DescriptorChangeMonitor(Thread.currentThread().getThreadGroup(),
106 "PortletApplicationManager Descriptor Change Monitor Thread", this, descriptorChangeMonitorInterval);
107
108 monitor.setContextClassLoader(getClass().getClassLoader());
109 monitor.start();
110 log.info("PortletApplicationManager Descriptor Change Monitor started!");
111 }
112 catch (Exception e)
113 {
114 log.warn("Unable to start PortletApplicationManager Descriptor Change Monitor: "+ e.toString(), e);
115 monitor.safeStop();
116 monitor = null;
117 }
118 }
119 started = true;
120 }
121
122 public void stop()
123 {
124 started = false;
125 if (monitor != null)
126 {
127 monitor.safeStop();
128 monitor = null;
129 }
130 }
131
132 public boolean isStarted()
133 {
134 return started;
135 }
136
137 public void setRoleManager(RoleManager roleManager)
138 {
139 this.roleManager = roleManager;
140 }
141
142 public void setAutoCreateRoles(boolean autoCreateRoles)
143 {
144 this.autoCreateRoles = autoCreateRoles;
145 }
146
147 public void setSearchEngine(SearchEngine searchEngine)
148 {
149 this.searchEngine = searchEngine;
150 }
151
152 private void checkStarted()
153 {
154 if (!started)
155 {
156 throw new IllegalStateException("Not started yet");
157 }
158 }
159
160 public void startLocalPortletApplication(String contextName, FileSystemHelper warStruct,
161 ClassLoader paClassLoader)
162 throws RegistryException
163 {
164 checkStarted();
165 startPA(contextName, warStruct, paClassLoader, MutablePortletApplication.LOCAL);
166 }
167
168 public void startInternalApplication(String contextName) throws RegistryException
169 {
170 checkStarted();
171 File webinf = new File (appRoot);
172 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
173 DirectoryHelper dir = new DirectoryHelper(webinf);
174 String appName = (contextName.startsWith("/")) ? contextName.substring(1) : contextName;
175 MutablePortletApplication app = registry.getPortletApplicationByIdentifier(appName);
176 if (app != null && app.getApplicationType() == MutablePortletApplication.LOCAL)
177 {
178 app.setApplicationType(MutablePortletApplication.INTERNAL);
179 registry.updatePortletApplication(app);
180 }
181 startPA(contextName, dir, contextClassLoader, MutablePortletApplication.INTERNAL);
182
183 }
184
185 public void startPortletApplication(String contextName, FileSystemHelper warStruct,
186 ClassLoader paClassLoader)
187 throws RegistryException
188 {
189 checkStarted();
190 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
191 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
192 try
193 {
194 startPA(contextName, warStruct, paClassLoader, MutablePortletApplication.WEBAPP);
195 }
196 finally
197 {
198 Thread.currentThread().setContextClassLoader(contextClassLoader);
199 }
200 }
201
202 public void stopLocalPortletApplication(String contextName)
203 throws RegistryException
204 {
205 stopPA(contextName, MutablePortletApplication.LOCAL);
206 }
207
208 public void stopPortletApplication(String contextName)
209 throws RegistryException
210 {
211 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
212 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
213 try
214 {
215 stopPA(contextName, MutablePortletApplication.WEBAPP);
216 }
217 finally
218 {
219 Thread.currentThread().setContextClassLoader(contextClassLoader);
220 }
221 }
222
223 public void unregisterPortletApplication(String paName)
224 throws RegistryException
225 {
226 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
227 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
228 try
229 {
230 MutablePortletApplication pa = null;
231
232 try
233 {
234 pa = registry.getPortletApplication(paName);
235 }
236 catch (Exception e)
237 {
238
239 }
240
241
242 if (pa != null)
243 {
244 if (portletFactory.isPortletApplicationRegistered(pa))
245 {
246 throw new RegistryException("Portlet Application " + paName + " still running");
247 }
248
249 unregisterPortletApplication(pa, true);
250 try
251 {
252 nodeManager.removeNode(paName);
253 }
254 catch (Exception ee)
255 {
256
257 }
258 }
259 }
260 finally
261 {
262 Thread.currentThread().setContextClassLoader(contextClassLoader);
263 }
264 }
265
266 protected void checkValidContextName(String contextName, boolean local)
267 throws RegistryException
268 {
269 int prefixLength = LOCAL_PA_PREFIX.length();
270
271 if ((contextName.length() >= prefixLength)
272 && contextName.substring(0, prefixLength).equalsIgnoreCase(LOCAL_PA_PREFIX))
273 {
274 if (!local)
275 {
276 throw new RegistryException("Prefix \"" + LOCAL_PA_PREFIX
277 + "\" is reserved for Local Portlet Applications only.");
278 }
279 }
280 else if (local)
281 {
282 throw new RegistryException("Prefix \"" + LOCAL_PA_PREFIX
283 + "\" is required for Local Portlet Applications.");
284 }
285 }
286
287 protected MutablePortletApplication registerPortletApplication(PortletApplicationWar paWar,
288 MutablePortletApplication oldPA, int paType, ClassLoader paClassLoader)
289 throws RegistryException
290 {
291 if (oldPA != null)
292 {
293 unregisterPortletApplication(oldPA, false);
294 oldPA = null;
295 }
296
297 MutablePortletApplication pa = null;
298 boolean registered = false;
299 String paName = paWar.getPortletApplicationName();
300
301 try
302 {
303 log.info("Loading portlet.xml...." + paName);
304 pa = paWar.createPortletApp(paClassLoader);
305 pa.setApplicationType(paType);
306
307
308 log.info("Loading web.xml...." + paName);
309 MutableWebApplication wa = paWar.createWebApp();
310 paWar.validate();
311
312 if (paType == MutablePortletApplication.LOCAL)
313 {
314 wa.setContextRoot("<portal>");
315 }
316 else if (paType == MutablePortletApplication.INTERNAL)
317 {
318
319 wa.setContextRoot("/" + paName);
320 }
321
322 pa.setWebApplicationDefinition(wa);
323
324
325
326 Collection portletDefs = pa.getPortletDefinitions();
327 if(portletDefs != null && portletDefs.size() > 0)
328 {
329 Iterator pdItr = portletDefs.iterator();
330 while(pdItr.hasNext())
331 {
332 PortletDefinition pd = (PortletDefinition) pdItr.next();
333 Collection portletEntites = entityAccess.getPortletEntities(pd);
334 if(portletEntites != null && portletEntites.size() > 0)
335 {
336 Iterator peItr = portletEntites.iterator();
337 while(peItr.hasNext())
338 {
339 PortletEntityCtrl portletEntity = (PortletEntityCtrl) peItr.next();
340 portletEntity.setPortletDefinition(pd);
341 }
342 }
343 }
344 }
345 }
346 catch (Exception e)
347 {
348 String msg = "Failed to load portlet application for "
349 + paWar.getPortletApplicationName();
350 log.error(msg, e);
351 throw new RegistryException(msg);
352 }
353
354
355 try
356 {
357 registry.registerPortletApplication(pa);
358 registered = true;
359 log.info("Registered the portlet application " + paName);
360
361
362 this.updateSearchEngine(false, pa);
363
364
365 nodeManager.addNode(new Long(pa.getId().toString()), pa.getName());
366
367
368 grantDefaultPermissions(paName);
369
370 if ( autoCreateRoles && roleManager != null && pa.getWebApplicationDefinition().getSecurityRoles() != null )
371 {
372 try
373 {
374 Iterator rolesIter = pa.getWebApplicationDefinition().getSecurityRoles().iterator();
375 SecurityRole sr;
376 while ( rolesIter.hasNext() )
377 {
378 sr = (SecurityRole)rolesIter.next();
379 if ( !roleManager.roleExists(sr.getRoleName()) )
380 {
381 roleManager.addRole(sr.getRoleName());
382 log.info("AutoCreated role: "+sr.getRoleName()+" from portlet application "+paName+" its web definition");
383 }
384 }
385 }
386 catch (SecurityException sex)
387 {
388 log.warn("Failed to autoCreate roles for portlet application " + paName+": "+sex.getMessage(), sex);
389 }
390 }
391
392 return pa;
393 }
394 catch (Exception e)
395 {
396 String msg = "Failed to register portlet application, " + paName;
397 log.error(msg, e);
398
399 if (registered)
400 {
401 try
402 {
403 unregisterPortletApplication(pa, (paType == MutablePortletApplication.LOCAL));
404 }
405 catch (Exception re)
406 {
407 log.error("Failed to rollback registration of portlet application" + paName, re);
408 }
409 }
410
411 throw new RegistryException(msg, e);
412 }
413 }
414
415 protected void startPA(String contextName, FileSystemHelper warStruct,
416 ClassLoader paClassLoader, int paType)
417 throws RegistryException
418 {
419 startPA(contextName, warStruct, paClassLoader, paType, 0);
420 }
421
422 protected void startPA(String contextName, FileSystemHelper warStruct,
423 ClassLoader paClassLoader, int paType, long checksum)
424 throws RegistryException
425 {
426 PortletApplicationWar paWar = null;
427 try
428 {
429 boolean register = true;
430 boolean monitored = checksum != 0;
431 paWar = new PortletApplicationWar(warStruct, contextName, "/" + contextName, checksum);
432 try
433 {
434 if (paClassLoader == null)
435 {
436 paClassLoader = paWar.createClassloader(getClass().getClassLoader());
437 }
438 checksum = paWar.getPortletApplicationChecksum();
439 }
440 catch (IOException e)
441 {
442 String msg = "Invalid PA WAR for " + contextName;
443 log.error(msg, e);
444 if ( paClassLoader == null )
445 {
446
447 throw new RegistryException(e);
448 }
449 register = false;
450 }
451
452 MutablePortletApplication pa = registry.getPortletApplication(contextName);
453
454 if (pa != null)
455 {
456 if ( pa.getApplicationType() != paType )
457 {
458 throw new RegistryException("Cannot start portlet application "+contextName+": as Application Types don't match: " + pa.getApplicationType() + " != " + paType);
459 }
460 DescriptorChangeMonitor changeMonitor = this.monitor;
461 if (!monitored && changeMonitor != null)
462 {
463 changeMonitor.remove(contextName);
464 }
465 portletFactory.unregisterPortletApplication(pa);
466 }
467
468 if (register)
469 {
470 if (pa == null)
471 {
472
473 try
474 {
475 pa = registerPortletApplication(paWar, pa, paType, paClassLoader);
476 }
477 catch (Exception e)
478 {
479
480 register = false;
481 }
482 }
483 else
484 {
485 int status = nodeManager.checkNode(new Long(pa.getId().toString()), pa.getName());
486 boolean reregister = false;
487 boolean deploy = false;
488 switch (status)
489 {
490 case NodeManager.NODE_NEW:
491 {
492
493
494
495 log.warn("The portlet application " + pa.getName() + " is registered in the database but not locally .... we will reregister");
496 reregister = true;
497 if (checksum != pa.getChecksum())
498 {
499 log.warn("The provided portlet application " + pa.getName() + " is a different version than in the database (db-checksum=" + pa.getChecksum() + ", local-checksum=: " + checksum + ") .... we will redeploy (also to the database)");
500 deploy = true;
501 }
502 break;
503 }
504 case NodeManager.NODE_SAVED:
505 {
506 if (checksum != pa.getChecksum())
507 {
508 log.warn("The provided portlet application " + pa.getName() + " is a different version than in the local node info and the database (db-checksum=" + pa.getChecksum() + ", local-checksum=: " + checksum + ") .... we will reregister AND redeploy (also to the database)");
509
510
511 reregister = true;
512 deploy = true;
513 }
514 break;
515 }
516 case NodeManager.NODE_OUTDATED:
517 {
518
519
520 if (checksum != pa.getChecksum())
521 log.error("The portlet application " + pa.getName() + " provided for the upgrade IS WRONG. The database checksum= " + pa.getChecksum() + ", but the local=" + checksum + "....THIS NEEDS TO BE CORRECTED");
522 reregister = true;
523 break;
524 }
525 }
526 if (deploy)
527 pa = registerPortletApplication(paWar, pa, paType, paClassLoader);
528 else
529 if (reregister)
530 {
531
532 this.updateSearchEngine(true, pa);
533 this.updateSearchEngine(false, pa);
534
535
536 try
537 {
538 nodeManager.addNode(new Long(pa.getId().toString()), pa.getName());
539 } catch (Exception e)
540 {
541 log.error("Adding node for portlet application " + pa.getName() + " caused exception" , e);
542 }
543 }
544
545
546 }
547 }
548 if (register)
549 {
550 portletFactory.registerPortletApplication(pa, paClassLoader);
551 }
552
553 DescriptorChangeMonitor changeMonitor = this.monitor;
554 if (!monitored && changeMonitor != null)
555 {
556 changeMonitor.monitor(contextName,paClassLoader, paType, warStruct.getRootDirectory(), checksum);
557 }
558 }
559 finally
560 {
561 if (paWar != null)
562 {
563 try
564 {
565 paWar.close();
566 }
567 catch (IOException e)
568 {
569 log.error("Failed to close PA WAR for " + contextName, e);
570 }
571 }
572 }
573 }
574
575 protected void stopPA(String contextName, int paType)
576 throws RegistryException
577 {
578 MutablePortletApplication pa = null;
579
580 try
581 {
582 pa = registry.getPortletApplication(contextName);
583 }
584 catch (Exception e)
585 {
586
587 }
588 if (pa != null && pa.getApplicationType() != paType)
589 {
590 throw new RegistryException("Cannot stop portlet application "+contextName+": as Application Types don't match: " + pa.getApplicationType() + " != " + paType);
591 }
592 DescriptorChangeMonitor monitor = this.monitor;
593 if ( monitor != null )
594 {
595 monitor.remove(contextName);
596 }
597 if (pa != null)
598 {
599 portletFactory.unregisterPortletApplication(pa);
600 }
601 }
602
603
604 protected void updateSearchEngine(boolean remove,MutablePortletApplication pa )
605 {
606 if (searchEngine != null)
607 {
608 if (remove)
609 {
610 searchEngine.remove(pa);
611 searchEngine.remove(pa.getPortletDefinitions());
612 log.info("Un-Registered the portlet application in the search engine... " + pa.getName());
613 }
614 else
615 {
616 searchEngine.add(pa);
617 searchEngine.add(pa.getPortletDefinitions());
618 log.info("Registered the portlet application in the search engine... " + pa.getName());
619 }
620 }
621
622 }
623 protected void unregisterPortletApplication(MutablePortletApplication pa,
624 boolean purgeEntityInfo)
625 throws RegistryException
626 {
627
628 updateSearchEngine(true,pa);
629 log.info("Remove all registry entries defined for portlet application " + pa.getName());
630
631 Iterator portlets = pa.getPortletDefinitions().iterator();
632
633 while (portlets.hasNext())
634 {
635 PortletDefinition portletDefinition = (PortletDefinition) portlets.next();
636 Iterator entities = entityAccess.getPortletEntities(portletDefinition)
637 .iterator();
638
639 while (entities.hasNext())
640 {
641 PortletEntity entity = (PortletEntity) entities.next();
642
643 if (purgeEntityInfo)
644 {
645 try
646 {
647 entityAccess.removePortletEntity(entity);
648 }
649 catch (PortletEntityNotDeletedException e)
650 {
651 String msg = "Failed to delete Portlet Entity " + entity.getId();
652 log.error(msg, e);
653 throw new RegistryException(msg, e);
654 }
655 }
656
657 entityAccess.removeFromCache(entity);
658 windowAccess.removeWindows(entity);
659 }
660 }
661
662
663 registry.removeApplication(pa);
664 revokeDefaultPermissions(pa.getName());
665 }
666
667 protected void grantDefaultPermissions(String paName)
668 {
669 try
670 {
671
672 Iterator roles = permissionRoles.iterator();
673 while (roles.hasNext())
674 {
675 String roleName = (String)roles.next();
676 Role userRole = roleManager.getRole(roleName);
677 if (userRole != null)
678 {
679 Permission permission = new PortletPermission(paName + "::*", "view, edit");
680 if (!permissionManager.permissionExists(permission))
681 {
682 permissionManager.addPermission(permission);
683 permissionManager.grantPermission(userRole.getPrincipal(), permission);
684 }
685 }
686 }
687 }
688 catch (SecurityException e)
689 {
690 log.error("Error granting default permissions for " + paName, e);
691 }
692 }
693
694 protected void revokeDefaultPermissions(String paName)
695 {
696 try
697 {
698 Iterator roles = permissionRoles.iterator();
699 while (roles.hasNext())
700 {
701 String roleName = (String)roles.next();
702 Role userRole = roleManager.getRole(roleName);
703 if (userRole != null)
704 {
705 Permission permission = new PortletPermission(paName + "::*", "view, edit");
706 if (permissionManager.permissionExists(permission))
707 {
708 permissionManager.removePermission(permission);
709 }
710
711 }
712 }
713 }
714 catch (SecurityException e)
715 {
716 log.error("Error revoking default permissions for " + paName, e);
717 }
718 }
719
720 public int getDescriptorChangeMonitorInterval()
721 {
722 return descriptorChangeMonitorInterval/1000;
723 }
724
725 public void setDescriptorChangeMonitorInterval(int descriptorChangeMonitorInterval)
726 {
727 this.descriptorChangeMonitorInterval = descriptorChangeMonitorInterval*1000;
728 }
729
730 private static class DescriptorChangeMonitor extends Thread
731 {
732 private static class DescriptorChangeMonitorInfo
733 {
734 private String contextName;
735 private ClassLoader paClassLoader;
736 private int paType;
737 private File paDir;
738 private File[] descriptors;
739 private long descriptorModificationTime;
740 private long extendedDescriptorModificationTime;
741 private long checksum;
742 private boolean obsolete;
743
744
745
746
747 public DescriptorChangeMonitorInfo(String contextName)
748 {
749 this.contextName = contextName;
750 }
751
752 public DescriptorChangeMonitorInfo(String contextName, ClassLoader paClassLoader, int paType, File paDir, long checksum)
753 {
754 this.contextName = contextName;
755 this.paClassLoader = paClassLoader;
756 this.paType = paType;
757 this.paDir = paDir.isAbsolute() ? paDir : paDir.getAbsoluteFile();
758 this.checksum = checksum;
759
760 this.descriptors = new File[] {
761 new File(paDir, PortletApplicationWar.WEB_XML_PATH),
762 new File(paDir, PortletApplicationWar.PORTLET_XML_PATH),
763 new File(paDir, PortletApplicationWar.EXTENDED_PORTLET_XML_PATH) };
764
765 descriptorModificationTime = descriptors[1].lastModified();
766 extendedDescriptorModificationTime = descriptors[2].lastModified();
767 }
768
769 public String getContextName()
770 {
771 return contextName;
772 }
773
774 public ClassLoader getPAClassLoader()
775 {
776 return paClassLoader;
777 }
778
779 public int getPortletApplicationType()
780 {
781 return paType;
782 }
783
784 public File getPADir()
785 {
786 return paDir;
787 }
788
789 public long getChecksum()
790 {
791 return checksum;
792 }
793
794 public boolean isChanged()
795 {
796 if ( !obsolete)
797 {
798 long newDescriptorModificationTime = descriptors[1].lastModified();
799 long newExtendedDescriptorModificationTime = descriptors[2].lastModified();
800 if ( descriptorModificationTime != newDescriptorModificationTime ||
801 extendedDescriptorModificationTime != newExtendedDescriptorModificationTime )
802 {
803 descriptorModificationTime = newDescriptorModificationTime;
804 extendedDescriptorModificationTime = newExtendedDescriptorModificationTime;
805 long newChecksum = MultiFileChecksumHelper.getChecksum(descriptors);
806 if ( checksum != newChecksum )
807 {
808 checksum = newChecksum;
809 return true;
810 }
811 }
812 }
813 return false;
814 }
815
816 public void setObsolete()
817 {
818 obsolete = true;
819 }
820
821 public boolean isObsolete()
822 {
823 return obsolete;
824 }
825 }
826
827 private PortletApplicationManager pam;
828 private long interval;
829 private boolean started = true;
830 private ArrayList monitorInfos;
831
832 public DescriptorChangeMonitor(ThreadGroup group, String name, PortletApplicationManager pam, long interval)
833 {
834 super(group, name);
835 this.pam = pam;
836 this.interval = interval;
837 monitorInfos = new ArrayList();
838 setPriority(MIN_PRIORITY);
839 setDaemon(true);
840 }
841
842 public void run()
843 {
844 try
845 {
846 sleep(interval);
847 }
848 catch (InterruptedException e)
849 {
850 }
851 while (started)
852 {
853 checkDescriptorChanges();
854
855 try
856 {
857 sleep(interval);
858 }
859 catch (InterruptedException e)
860 {
861
862 }
863 }
864 }
865
866 /***
867 * notifies a switch variable that exits the watcher's montior loop started in the <code>run()</code> method.
868 */
869 public synchronized void safeStop()
870 {
871 started = false;
872 monitorInfos.clear();
873 }
874
875 public synchronized void monitor(String contextName, ClassLoader paClassLoader, int paType, File paDir, long checksum)
876 {
877 monitorInfos.add(new DescriptorChangeMonitorInfo(contextName, paClassLoader, paType, paDir, checksum));
878 }
879
880 public synchronized void remove(String contextName)
881 {
882 DescriptorChangeMonitorInfo monitorInfo;
883 for ( int i = monitorInfos.size()-1; i > -1; i-- )
884 {
885 monitorInfo = (DescriptorChangeMonitorInfo)monitorInfos.get(i);
886 if (contextName.equals(monitorInfo.getContextName()))
887 {
888
889 monitorInfo.setObsolete();
890 break;
891 }
892 }
893 }
894
895 private void checkDescriptorChanges()
896 {
897 int size;
898 synchronized (this)
899 {
900 size = monitorInfos.size();
901 }
902 for (int i = size-1; i > -1; i--)
903 {
904 DescriptorChangeMonitorInfo monitorInfo;
905 synchronized (this)
906 {
907 if ( started )
908 {
909 monitorInfo = (DescriptorChangeMonitorInfo)monitorInfos.get(i);
910 if (monitorInfo.isObsolete())
911 {
912 monitorInfos.remove(i);
913 }
914 else
915 {
916 try
917 {
918 if (monitorInfo.isChanged())
919 {
920 try
921 {
922 pam.startPA(monitorInfo.getContextName(), new DirectoryHelper(monitorInfo.getPADir()),
923 monitorInfo.getPAClassLoader(), monitorInfo.getPortletApplicationType(), monitorInfo.getChecksum());
924 }
925 catch (Exception e)
926 {
927 log.error("Failed to restart PortletApplication "+monitorInfo.getContextName(),e);
928 }
929 }
930 }
931 catch (Exception e)
932 {
933
934 log.error("Descriptor Change check failure for PortletApplication "+monitorInfo.getContextName(),e);
935 }
936 }
937 }
938 }
939 }
940 }
941 }
942 }