Coverage report

  %line %branch
org.apache.jetspeed.tools.pamanager.PortletApplicationManager$DescriptorChangeMonitor$DescriptorChangeMonitorInfo
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 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; // 10 seconds
 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  
         // startInternal(contextName, warStruct, paClassLoader, true);        
 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  
                 // ignore errors during portal shutdown
 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  
                 	// we actually do not care about an exception in the remove operation...
 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  
 			// load the web.xml
 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  
                 // TODO: this is screwing up the PSML as its set all over the place to "jetspeed-layouts", not good
 319  
                 wa.setContextRoot("/" + paName);                
 320  
             }
 321  
 
 322  
 			pa.setWebApplicationDefinition(wa);
 323  
             
 324  
             // Make sure existing entities are refreshed with the most
 325  
             // recent PortletDefintion.
 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  
 		// register the portlet application
 355  
 		try
 356  
 		{
 357  
 			registry.registerPortletApplication(pa);
 358  
 			registered = true;
 359  
 			log.info("Registered the portlet application " + paName);
 360  
 
 361  
 			// add to search engine result
 362  
 			this.updateSearchEngine(false, pa);
 363  
 			
 364  
 			// and add to the current node info
 365  
 			nodeManager.addNode(new Long(pa.getId().toString()), pa.getName());
 366  
             
 367  
             // grant default permissions to portlet application
 368  
 			grantDefaultPermissions(paName);
 369  
             
 370  
             if ( autoCreateRoles && roleManager != null && pa.getWebApplicationDefinition().getSecurityRoles() != class="keyword">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  
                     // nothing to be done about it anymore: this pa is beyond repair :(
 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  
 //            if (register && (pa == null || checksum != pa.getChecksum()))
 468  
             if (register)
 469  
             {
 470  
             	if (pa == null)
 471  
             	{ 
 472  
             		// new
 473  
 	                try
 474  
 	                {
 475  
 	                    pa = registerPortletApplication(paWar, pa, paType, paClassLoader);
 476  
 	                }
 477  
 	                catch (Exception e)
 478  
 	                {
 479  
 	                    // don't register the pa
 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  
             				//only reason is that the file got somehow corrupted 
 493  
             				// so we really do not know what is going on here...
 494  
             				// the best chance at this point is to reregister (which might be the absolute wrong choice)
 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  
         						//database and local node info are in synch, so we assume that this is a brand new
 510  
         						// war .... let's deploy
 511  
         						reregister = true;
 512  
         						deploy = true;
 513  
                     		}
 514  
         					break;
 515  
         				}
 516  
         				case  NodeManager.NODE_OUTDATED:
 517  
         				{
 518  
             				//database version is older (determined by id) than the database 
 519  
         					//let's deploy and reregister
 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  
         					// add to search engine result
 532  
         					this.updateSearchEngine(true, pa);
 533  
         					this.updateSearchEngine(false, pa);
 534  
         					
 535  
         					// and add to the current node info
 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  
             // ignore errors during portal shutdown
 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  
 		// todo keep (User)Prefs?
 663  
 		registry.removeApplication(pa);
 664  
         revokeDefaultPermissions(pa.getName());
 665  
 	}
 666  
     
 667  
     protected void grantDefaultPermissions(String paName)
 668  
     {
 669  
         try
 670  
         {
 671  
             // create a default permission for this portlet app, granting configured roles to the portlet application 
 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  
              * Constructor only used for looking up the matching registered one in monitorsInfo
 746  
              */
 747  
             public DescriptorChangeMonitorInfo(String contextName)
 748  0
             {
 749  0
                 this.contextName = contextName;
 750  0
             }
 751  
             
 752  
             public DescriptorChangeMonitorInfo(String contextName, ClassLoader paClassLoader, int paType, File paDir, long checksum)
 753  0
             {
 754  0
                 this.contextName = contextName;
 755  0
                 this.paClassLoader = paClassLoader;
 756  0
                 this.paType = paType;
 757  0
                 this.paDir = paDir.isAbsolute() ? paDir : paDir.getAbsoluteFile();
 758  0
                 this.checksum = checksum;
 759  
                 
 760  0
                 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  0
                 descriptorModificationTime = descriptors[1].lastModified();
 766  0
                 extendedDescriptorModificationTime = descriptors[2].lastModified();
 767  0
             }
 768  
             
 769  
             public String getContextName()
 770  
             {
 771  0
                 return contextName;
 772  
             }
 773  
             
 774  
             public ClassLoader getPAClassLoader()
 775  
             {
 776  0
                 return paClassLoader;
 777  
             }
 778  
             
 779  
             public int getPortletApplicationType()
 780  
             {
 781  0
                 return paType;
 782  
             }
 783  
             
 784  
             public File getPADir()
 785  
             {
 786  0
                 return paDir;
 787  
             }
 788  
 
 789  
             public long getChecksum()
 790  
             {
 791  0
                 return checksum;
 792  
             }
 793  
             
 794  
             public boolean isChanged()
 795  
             {
 796  0
                 if ( !obsolete)
 797  
                 {
 798  0
                     long newDescriptorModificationTime = descriptors[1].lastModified();
 799  0
                     long newExtendedDescriptorModificationTime = descriptors[2].lastModified();
 800  0
                     if ( descriptorModclass="keyword">ificationTime != newDescriptorModclass="keyword">ificationTime ||
 801  
                             extendedDescriptorModificationTime != newExtendedDescriptorModificationTime )
 802  
                     {
 803  0
                         descriptorModificationTime = newDescriptorModificationTime;
 804  0
                         extendedDescriptorModificationTime = newExtendedDescriptorModificationTime;
 805  0
                         long newChecksum = MultiFileChecksumHelper.getChecksum(descriptors);
 806  0
                         if ( checksum != newChecksum )
 807  
                         {
 808  0
                             checksum = newChecksum;
 809  0
                             return true;
 810  
                         }
 811  
                     }
 812  
                 }
 813  0
                 return false;
 814  
             }
 815  
             
 816  
             public void setObsolete()
 817  
             {
 818  0
                 obsolete = true;
 819  0
             }
 820  
             
 821  
             public boolean isObsolete()
 822  
             {
 823  0
                 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  
                     // will be removed by checkDescriptorChanges on next iteration
 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  
                                 // ignore filesystem and/or descriptor errors, maybe next time round they'll be fixed again
 934  
                                 log.error("Descriptor Change check failure for PortletApplication "+monitorInfo.getContextName(),e);
 935  
                             }
 936  
                         }
 937  
                     }
 938  
                 }
 939  
             }
 940  
         }        
 941  
     }    
 942  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.