<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg DL { border : 1px #006 solid; background-color : #369; padding : 6px; color : #fff; } #msg DT { float : left; width : 6em; font-weight : bold; } #msg DL, #msg DT, #msg UL, #msg LI { font-family : arial,helvetica,sans-serif; font-size : 10pt; } h3 { font-family : arial,helvetica,sans-serif; font-size : 10pt; font-weight : bold; } #msg PRE { overflow : auto; white-space : normal; background-color : #ffc; border : 1px #fc0 solid; padding : 6px; } #msg UL, PRE, .diff { overflow : auto; } #patch h4 { font-family : arial,helvetica,sans-serif; font-size : 10pt; } #patch h4 { padding: 8px; background : #369; color : #fff; margin : 0; } #patch .propset h4, #patch .binary h4 {margin: 0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {background:#eeeeee;padding: 0 0 10px 0;} #patch .propset .diff, #patch .binary .diff {padding: 10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch .add {background:#ddffdd;} #patch .rem {background:#ffdddd;} #patch .lines, .info {color:#888888;background:#ffffff;} .diff { width : 100%; } #msg DL { border : 1px #006 solid; background-color : #369; padding : 6px; color : #fff; } #msg DT { float : left; width : 6em; font-weight : bold; } #msg DL, #msg DT, #msg UL, #msg LI { font-family : arial,helvetica,sans-serif; font-size : 10pt; } h3 { font-family : arial,helvetica,sans-serif; font-size : 10pt; font-weight : bold; } #msg PRE { overflow : auto; white-space : normal; background-color : #ffc; border : 1px #fc0 solid; padding : 6px; } #msg UL, PRE, .diff { overflow : auto; } #patch h4 { font-family : arial,helvetica,sans-serif; font-size : 10pt; } #patch h4 { padding: 8px; background : #369; color : #fff; margin : 0; } #patch .propset h4, #patch .binary h4 {margin: 0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {background:#eeeeee;padding: 0 0 10px 0;} #patch .propset .diff, #patch .binary .diff {padding: 10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch .add {background:#ddffdd;} #patch .rem {background:#ffdddd;} #patch .lines, .info {color:#888888;background:#ffffff;} .diff { width : 100%; } --></style> <title>[rhq-project.org rhq] [4002] pluginClassLoader field in ResourceContainer is now transient and is re-hydrated by PC after loading inventory.dat (http://jira.rhq-project.org/browse/RHQ-2121)</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>4002</dd> <dt>Author</dt> <dd>ispringer</dd> <dt>Date</dt> <dd>2009-05-28 08:56:00 -0500 (Thu, 28 May 2009)</dd> </dl> <h3>Log Message</h3> <pre>pluginClassLoader field in ResourceContainer is now transient and is re-hydrated by PC after loading inventory.dat (http://jira.rhq-project.org/browse/RHQ-2121)</pre> <h3>Modified Paths</h3> <ul> <li><a href="#rhqtrunkmodulescoreplugincontainersrcmainjavaorgrhqcorepcinventoryInventoryFilejava">rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryFile.java</a></li> <li><a href="#rhqtrunkmodulescoreplugincontainersrcmainjavaorgrhqcorepcinventoryInventoryManagerjava">rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java</a></li> <li><a href="#rhqtrunkmodulescoreplugincontainersrcmainjavaorgrhqcorepcinventoryResourceContainerjava">rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java</a></li> <li><a href="#rhqtrunkmodulescoreplugincontainersrctestjavaorgrhqcorepcinventoryResourceContainerTestjava">rhq/trunk/modules/core/plugin-container/src/test/java/org/rhq/core/pc/inventory/ResourceContainerTest.java</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="rhqtrunkmodulescoreplugincontainersrcmainjavaorgrhqcorepcinventoryInventoryFilejava"></a> <div class="modfile"><h4>Modified: rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryFile.java (4001 => 4002)</h4> <pre class="diff"> <span class="info">--- rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryFile.java 2009-05-28 13:39:36 UTC (rev 4001) +++ rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryFile.java 2009-05-28 13:56:00 UTC (rev 4002) </span><span class="lines">@@ -108,8 +108,9 @@ </span><span class="cx"> this.platform = (Resource) ois.readObject(); connectTypes(this.platform); this.resourceContainers = (Map<String, ResourceContainer>) ois.readObject(); </span><span class="rem">- for (ResourceContainer resourceContainer : this.resourceContainers.values()) </span><span class="add">+ for (ResourceContainer resourceContainer : this.resourceContainers.values()) { </span><span class="cx"> connectTypes(resourceContainer.getResource()); </span><span class="add">+ } </span><span class="cx"> } catch (Exception e) { throw new PluginContainerException("Cannot load inventory file: " + inventoryFile, e); } </span></pre></div> <a id="rhqtrunkmodulescoreplugincontainersrcmainjavaorgrhqcorepcinventoryInventoryManagerjava"></a> <div class="modfile"><h4>Modified: rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java (4001 => 4002)</h4> <pre class="diff"> <span class="info">--- rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java 2009-05-28 13:39:36 UTC (rev 4001) +++ rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java 2009-05-28 13:56:00 UTC (rev 4002) </span><span class="lines">@@ -84,6 +84,7 @@ </span><span class="cx"> import org.rhq.core.pc.plugin.BlacklistedException; import org.rhq.core.pc.plugin.PluginComponentFactory; import org.rhq.core.pc.plugin.PluginManager; </span><span class="add">+import org.rhq.core.pc.plugin.PluginEnvironment; </span><span class="cx"> import org.rhq.core.pc.util.DiscoveryComponentProxyFactory; import org.rhq.core.pc.util.FacetLockType; import org.rhq.core.pc.util.LoggingThreadFactory; </span><span class="lines">@@ -1030,7 +1031,8 @@ </span><span class="cx"> private ResourceContainer initResourceContainer(Resource resource) { ResourceContainer resourceContainer = getResourceContainer(resource); if (resourceContainer == null) { </span><span class="rem">- resourceContainer = new ResourceContainer(resource); </span><span class="add">+ ClassLoader pluginClassLoader = getPluginClassLoader(resource); + resourceContainer = new ResourceContainer(resource, pluginClassLoader); </span><span class="cx"> if (!this.configuration.isInsideAgent()) { // Auto-sync if the PC is running within the embedded JBossAS console. resourceContainer.setSynchronizationState(ResourceContainer.SynchronizationState.SYNCHRONIZED); </span><span class="lines">@@ -1047,6 +1049,16 @@ </span><span class="cx"> return resourceContainer; } </span><span class="add">+ private ClassLoader getPluginClassLoader(Resource resource) { + if (resource.getResourceType().equals(PluginMetadataManager.TEST_PLATFORM_TYPE)) { + return Thread.currentThread().getContextClassLoader(); + } else { + String pluginName = resource.getResourceType().getPlugin(); + PluginEnvironment pluginEnv = this.pluginManager.getPlugin(pluginName); + return pluginEnv.getPluginClassLoader(); + } + } + </span><span class="cx"> /** * This will start the resource's plugin component, creating it first if it has not yet been created. If the * component is already created and started, this method is a no-op. </span><span class="lines">@@ -1315,23 +1327,29 @@ </span><span class="cx"> File file = new File(this.configuration.getDataDirectory(), "inventory.dat"); if (file.exists()) { long start = System.currentTimeMillis(); </span><span class="rem">- log.info("Loading inventory from persistent data file"); </span><span class="add">+ log.info("Loading inventory from data file " + file + "..."); </span><span class="cx"> InventoryFile inventoryFile = new InventoryFile(file); inventoryFile.loadInventory(); this.platform = inventoryFile.getPlatform(); this.resourceContainers.clear(); </span><span class="rem">- this.resourceContainers.putAll(inventoryFile.getResourceContainers()); </span><span class="add">+ for (String uuid : inventoryFile.getResourceContainers().keySet()) { + ResourceContainer resourceContainer = inventoryFile.getResourceContainers().get(uuid); + this.resourceContainers.put(uuid, resourceContainer); + // Make sure to set the plugin class loader, which is transient and so not saved to inventory.dat. + ClassLoader pluginClassLoader = getPluginClassLoader(resourceContainer.getResource()); + resourceContainer.setPluginClassLoader(pluginClassLoader); + } </span><span class="cx"> initResourceContainer(this.platform); activateFromDisk(this.platform); </span><span class="rem">- log.info("Inventory size [" + this.resourceContainers.size() + "] initialized from disk in [" </span><span class="add">+ log.info("Inventory with size [" + this.resourceContainers.size() + "] initialized from data file in [" </span><span class="cx"> + (System.currentTimeMillis() - start) + "ms]"); } } catch (Exception e) { </span><span class="rem">- log.error("Could not load inventory data from disk", e); </span><span class="add">+ log.error("Could not load inventory from data file.", e); </span><span class="cx"> } finally { this.inventoryLock.writeLock().unlock(); } </span></pre></div> <a id="rhqtrunkmodulescoreplugincontainersrcmainjavaorgrhqcorepcinventoryResourceContainerjava"></a> <div class="modfile"><h4>Modified: rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java (4001 => 4002)</h4> <pre class="diff"> <span class="info">--- rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java 2009-05-28 13:39:36 UTC (rev 4001) +++ rhq/trunk/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java 2009-05-28 13:56:00 UTC (rev 4002) </span><span class="lines">@@ -53,8 +53,6 @@ </span><span class="cx"> import org.rhq.core.domain.resource.Resource; import org.rhq.core.pc.util.FacetLockType; import org.rhq.core.pc.util.LoggingThreadFactory; </span><span class="rem">-import org.rhq.core.pc.PluginContainer; -import org.rhq.core.pc.plugin.PluginEnvironment; </span><span class="cx"> import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.jetbrains.annotations.Nullable; </span><span class="lines">@@ -78,26 +76,27 @@ </span><span class="cx"> STARTED, STOPPED } </span><span class="rem">- private final Log log = LogFactory.getLog(this.getClass()); </span><span class="add">+ // thread pools used to invoke methods on container's components + private static final String DAEMON_THREAD_POOL_NAME = "ResourceContainer.invoker.daemon"; + private static final String NON_DAEMON_THREAD_POOL_NAME = "ResourceContainer.invoker.nonDaemon"; + private static ExecutorService DAEMON_THREAD_POOL; + private static ExecutorService NON_DAEMON_THREAD_POOL; </span><span class="cx"> </span><span class="add">+ // non-transient fields + private final Resource resource; + private Availability availability; + private SynchronizationState synchronizationState = SynchronizationState.NEW; + private Set<MeasurementScheduleRequest> measurementSchedule = new HashSet<MeasurementScheduleRequest>(); + private Set<ResourcePackageDetails> installedPackages = new HashSet<ResourcePackageDetails>(); + + // transient fields </span><span class="cx"> private transient ResourceComponent resourceComponent; private transient ResourceContext resourceContext; private transient ResourceComponentState resourceComponentState = ResourceComponentState.STOPPED; private transient ReentrantReadWriteLock facetAccessLock = new ReentrantReadWriteLock(); </span><span class="rem">- private final Resource resource; - private Availability availability; - private Set<ResourcePackageDetails> installedPackages = new HashSet<ResourcePackageDetails>(); - private Set<MeasurementScheduleRequest> measurementSchedule = new HashSet<MeasurementScheduleRequest>(); - private SynchronizationState synchronizationState = SynchronizationState.NEW; </span><span class="cx"> private transient Map<Integer, Object> proxyCache = new HashMap<Integer, Object>(); </span><span class="rem">- private ClassLoader pluginClassLoader; </span><span class="add">+ private transient ClassLoader pluginClassLoader; </span><span class="cx"> </span><span class="rem">- // thread pools used to invoke methods on container's components - private static final String DAEMON_THREAD_POOL_NAME = "ResourceContainer.invoker.daemon"; - private static final String NON_DAEMON_THREAD_POOL_NAME = "ResourceContainer.invoker.nonDaemon"; - private static ExecutorService DAEMON_THREAD_POOL; - private static ExecutorService NON_DAEMON_THREAD_POOL; - </span><span class="cx"> /** * Initialize the ResourceContainer's internals, such as its thread pools. */ </span><span class="lines">@@ -116,15 +115,9 @@ </span><span class="cx"> NON_DAEMON_THREAD_POOL.shutdown(); } </span><span class="rem">- public ResourceContainer(Resource resource) { </span><span class="add">+ public ResourceContainer(Resource resource, ClassLoader pluginClassLoader) { </span><span class="cx"> this.resource = resource; </span><span class="rem">- String pluginName = this.resource.getResourceType().getPlugin(); - PluginEnvironment pluginEnv = PluginContainer.getInstance().getPluginManager().getPlugin(pluginName); - if (pluginEnv == null) { - log.warn("No plugin environment found for plugin '" + pluginName + "'."); - } - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - this.pluginClassLoader = (pluginEnv != null) ? pluginEnv.getPluginClassLoader() : contextClassLoader; </span><span class="add">+ this.pluginClassLoader = pluginClassLoader; </span><span class="cx"> } public Availability updateAvailability(AvailabilityType availabilityType) { </span><span class="lines">@@ -277,6 +270,10 @@ </span><span class="cx"> return this.pluginClassLoader; } </span><span class="add">+ public void setPluginClassLoader(ClassLoader pluginClassLoader) { + this.pluginClassLoader = pluginClassLoader; + } + </span><span class="cx"> @Override public String toString() { return this.getClass().getSimpleName() + "[resource=" + this.resource + "]"; </span><span class="lines">@@ -322,12 +319,12 @@ </span><span class="cx"> + "] interface: " + this); } </span><span class="rem">- // if no locking is required and there is no timeout, there is no need for a proxy - return the actual component </span><span class="add">+ // If no locking is required and there is no timeout, there is no need for a proxy - return the actual component. </span><span class="cx"> if (lockType == FacetLockType.NONE && timeout == 0) { return (T) resourceComponent; } </span><span class="rem">- // Check for a cached proxy </span><span class="add">+ // Check for a cached proxy. </span><span class="cx"> int key; key = facetInterface.hashCode(); key = 31 * key + lockType.hashCode(); </span><span class="lines">@@ -368,7 +365,7 @@ </span><span class="cx"> return str.toString(); } </span><span class="rem">- // Recreate the facet lock on deserialization </span><span class="add">+ // Recreate the facet lock on deserialization. </span><span class="cx"> private Object readResolve() throws java.io.ObjectStreamException { this.facetAccessLock = new ReentrantReadWriteLock(); return this; </span><span class="lines">@@ -391,14 +388,13 @@ </span><span class="cx"> private final boolean daemonThread; private final Class facetInterface; </span><span class="rem">- </span><span class="cx"> /** * * @param container the resource container managing the resource component upon which the method will be invoked; * caller must ensure the container's component is never null * @param lockType the type of facet lock to acquire for the invocation; must not be null * @param timeout if the method invocation thread has not completed after this many milliseconds, interrupt it; </span><span class="rem">- * value must be positive </span><span class="add">+ * value must be positive </span><span class="cx"> * @param daemonThread whether or not the thread used for the invocation should be a daemon thread * @param facetInterface the interface that the component implements that is being exposed by this proxy */ </span><span class="lines">@@ -421,7 +417,12 @@ </span><span class="cx"> public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader(); try { </span><span class="rem">- Thread.currentThread().setContextClassLoader(this.container.getPluginClassLoader()); </span><span class="add">+ + ClassLoader pluginClassLoader = this.container.getPluginClassLoader(); + if (pluginClassLoader == null) { + throw new IllegalStateException("No plugin classloader was specified for " + this + "."); + } + Thread.currentThread().setContextClassLoader(pluginClassLoader); </span><span class="cx"> if (method.getDeclaringClass().equals(this.facetInterface)) { return invokeInNewThreadWithLock(method, args); } else { </span><span class="lines">@@ -503,6 +504,7 @@ </span><span class="cx"> try { // This is the actual call into the resource component's facet interface. </span><span class="add">+ @SuppressWarnings({"UnnecessaryLocalVariable"}) </span><span class="cx"> Object results = this.method.invoke(resourceComponent, this.args); return results; } catch (InvocationTargetException e) { </span><span class="lines">@@ -513,7 +515,8 @@ </span><span class="cx"> } catch (Exception e) { throw new RuntimeException(e); } finally { </span><span class="rem">- if (this.lock != null) { </span><span class="add">+ if (this.lock != null) + { </span><span class="cx"> this.lock.unlock(); } } </span></pre></div> <a id="rhqtrunkmodulescoreplugincontainersrctestjavaorgrhqcorepcinventoryResourceContainerTestjava"></a> <div class="modfile"><h4>Modified: rhq/trunk/modules/core/plugin-container/src/test/java/org/rhq/core/pc/inventory/ResourceContainerTest.java (4001 => 4002)</h4> <pre class="diff"> <span class="info">--- rhq/trunk/modules/core/plugin-container/src/test/java/org/rhq/core/pc/inventory/ResourceContainerTest.java 2009-05-28 13:39:36 UTC (rev 4001) +++ rhq/trunk/modules/core/plugin-container/src/test/java/org/rhq/core/pc/inventory/ResourceContainerTest.java 2009-05-28 13:56:00 UTC (rev 4002) </span><span class="lines">@@ -28,12 +28,11 @@ </span><span class="cx"> import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.resource.Resource; </span><span class="rem">-import org.rhq.core.domain.resource.ResourceType; -import org.rhq.core.domain.resource.ResourceCategory; </span><span class="cx"> import org.rhq.core.pc.util.FacetLockType; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.core.pluginapi.inventory.ResourceContext; </span><span class="add">+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager; </span><span class="cx"> /** * Unit test for {@link ResourceContainer}. </span><span class="lines">@@ -56,9 +55,9 @@ </span><span class="cx"> } public void testCreateResourceComponentProxy() throws Exception { </span><span class="rem">- ResourceType resourceType = new ResourceType("name", "plugin", ResourceCategory.PLATFORM, null); - Resource resource = new Resource("key", "name", resourceType); - ResourceContainer resourceContainer = new ResourceContainer(resource); </span><span class="add">+ Resource resource = new Resource("TestPlatformKey", "MyTestPlatform", PluginMetadataManager.TEST_PLATFORM_TYPE); + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + ResourceContainer resourceContainer = new ResourceContainer(resource, contextClassLoader); </span><span class="cx"> ResourceComponent resourceComponent = new MockResourceComponent(false); resourceContainer.setResourceComponent(resourceComponent); System.out.println("Testing proxy call that should timeout..."); </span> </pre> </div> </div> </body> </html> |