modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java | 50 +++++-
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java | 83 ++++------
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceTypeProcesses.java | 31 ++-
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java | 11 -
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java | 10 -
5 files changed, 117 insertions(+), 68 deletions(-)
New commits:
commit 5654b1e3373193b0b960590b990828d43f1350fc
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Dec 30 13:07:54 2013 +0100
Internally store timeout in seconds. Saves 8 bytes / instance (or on avg 20b / resource)
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java
index 8faa357..39e6f1a 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java
@@ -581,7 +581,7 @@ public class ResourceContainer implements Serializable {
private final ResourceContainer container;
private final Lock lock;
- private final long timeout;
+ private final int timeoutInSeconds;
private final boolean daemonThread;
private final Class facetInterface;
private final boolean transferInterrupt;
@@ -618,7 +618,7 @@ public class ResourceContainer implements Serializable {
if (timeout <= 0) {
throw new IllegalArgumentException("timeout value is not positive.");
}
- this.timeout = timeout;
+ this.timeoutInSeconds = (int) (timeout/1000);
this.daemonThread = daemonThread;
this.facetInterface = facetInterface;
this.transferInterrupt = transferInterrupt;
@@ -638,7 +638,7 @@ public class ResourceContainer implements Serializable {
ComponentInvocation componentInvocation = new ComponentInvocation(this.container, method, args, this.lock);
Future<?> future = threadPool.submit(componentInvocation);
try {
- return future.get(this.timeout, TimeUnit.MILLISECONDS);
+ return future.get(this.timeoutInSeconds, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Thread [" + Thread.currentThread().getName() + "] was interrupted.");
@@ -653,8 +653,8 @@ public class ResourceContainer implements Serializable {
}
throw e.getCause();
} catch (java.util.concurrent.TimeoutException e) {
- String msg = invokedMethodString(method, args, "timed out after " + timeout
- + " milliseconds - invocation thread will be interrupted.");
+ String msg = invokedMethodString(method, args, "timed out after " + timeoutInSeconds
+ + " seconds - invocation thread will be interrupted.");
LOG.debug(msg);
Throwable cause = new Throwable();
cause.setStackTrace(componentInvocation.getStackTrace());
commit 41d3cd33d161898516399b85dddae292082d6fe6
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sat Dec 28 15:45:26 2013 +0100
Replace empty LinkedHashSet by Collections.emptySet for schedules.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
index 92b7d56..746deea 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
@@ -2974,6 +2974,11 @@ public class InventoryManager extends AgentService implements ContainerService,
resource.setCreateChildResourceRequests(Collections.EMPTY_LIST);
resource.setDeleteResourceRequests(Collections.EMPTY_LIST);
resource.setAutoGroupBackingGroups(Collections.EMPTY_LIST);
+ if (resource.getSchedules()!=null) { // TODO used at all in the agent?
+ if (resource.getSchedules().size()==0) {
+ resource.setSchedules(Collections.EMPTY_SET);
+ }
+ }
if (resource.getVersion()!=null) {
resource.setVersion(resource.getVersion().intern());
@@ -2999,7 +3004,8 @@ public class InventoryManager extends AgentService implements ContainerService,
if (resourceConfiguration != null) {
resourceConfiguration.cleanoutRawConfiguration();
- boolean persisted = ConfigurationCheckExecutor.persistConfigurationToFile(resource.getId(),resourceConfiguration, log);
+ boolean persisted = ConfigurationCheckExecutor.persistConfigurationToFile(resource.getId(),
+ resourceConfiguration, log);
if (persisted) {
resource.setResourceConfiguration(null);
}
commit 2e8dcfcb7e13405810c86c7b5c6b557d7a408663
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Dec 27 17:05:24 2013 +0100
Slim down resource context size from avg 723 bytes to 203 bytes per instance.
Addresses BZ 1031432
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
index 339e46c..ca0a048 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
@@ -64,18 +64,14 @@ public class ResourceContext<T extends ResourceComponent<?>> {
private static final Log LOG = LogFactory.getLog(ResourceContext.class);
- private final String resourceKey;
- private final String resourceUuid;
- private final ResourceType resourceType;
- private final String version;
- private final String resourceDetails;
private final T parentResourceComponent;
private final ResourceContext<?> parentResourceContext;
private final Configuration pluginConfiguration;
private final SystemInfo systemInformation;
private final ResourceDiscoveryComponent<T> resourceDiscoveryComponent;
- private final File temporaryDirectory;
- private final File dataDirectory;
+ private final Resource resource;
+ private File temporaryDirectory; // Lazily evaluated
+ private final File baseDataDirectory; // base data directory from system
private final String pluginContainerName;
private final EventContext eventContext;
private final OperationContext operationContext;
@@ -87,8 +83,8 @@ public class ResourceContext<T extends ResourceComponent<?>> {
private final ComponentInvocationContext componentInvocationContext;
private static class Children {
- public ResourceType resourceType;
- public String parentResourceUuid;
+ public final ResourceType resourceType;
+ public final String parentResourceUuid;
public Children(String parentResourceUuid, ResourceType resourceType) {
this.parentResourceUuid = parentResourceUuid;
@@ -128,11 +124,11 @@ public class ResourceContext<T extends ResourceComponent<?>> {
@Deprecated
public ResourceContext(Resource resource, T parentResourceComponent, ResourceContext<?> parentResourceContext,
ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory,
- File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext,
+ File baseDataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext,
ContentContext contentContext, AvailabilityContext availabilityContext, InventoryContext inventoryContext,
PluginContainerDeployment pluginContainerDeployment) {
this(resource, parentResourceComponent, parentResourceContext, resourceDiscoveryComponent, systemInfo,
- temporaryDirectory, dataDirectory, pluginContainerName, eventContext, operationContext, contentContext,
+ temporaryDirectory, baseDataDirectory, pluginContainerName, eventContext, operationContext, contentContext,
availabilityContext, inventoryContext, pluginContainerDeployment, new ComponentInvocationContext() {
@Override
public boolean isInterrupted() {
@@ -161,7 +157,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @param systemInfo information about the system on which the plugin and its plugin container are
* running
* @param temporaryDirectory a temporary directory for plugin use that is destroyed at plugin container shutdown
- * @param dataDirectory a directory where plugins can store persisted data that survives plugin container restarts
+ * @param baseDataDirectory a directory where plugins can store persisted data that survives plugin container restarts
* @param pluginContainerName the name of the plugin container in which the discovery component is running.
* Components can be assured this name is unique across <b>all</b> plugin
* containers/agents running in the RHQ environment.
@@ -179,28 +175,20 @@ public class ResourceContext<T extends ResourceComponent<?>> {
*/
public ResourceContext(Resource resource, T parentResourceComponent, ResourceContext<?> parentResourceContext,
ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory,
- File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext,
+ File baseDataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext,
ContentContext contentContext, AvailabilityContext availabilityContext, InventoryContext inventoryContext,
PluginContainerDeployment pluginContainerDeployment, ComponentInvocationContext componentInvocationContext) {
- this.resourceKey = resource.getResourceKey();
- this.resourceType = resource.getResourceType();
- this.version = resource.getVersion();
- this.resourceDetails = resource.toString();
+ this.resource = resource;
this.parentResourceComponent = parentResourceComponent;
this.parentResourceContext = parentResourceContext;
this.resourceDiscoveryComponent = resourceDiscoveryComponent;
this.systemInformation = systemInfo;
this.pluginConfiguration = resource.getPluginConfiguration();
- this.dataDirectory = dataDirectory;
- this.pluginContainerName = pluginContainerName;
+ this.baseDataDirectory = baseDataDirectory;
+ this.pluginContainerName = pluginContainerName.intern();
this.pluginContainerDeployment = pluginContainerDeployment;
- if (temporaryDirectory == null) {
- this.temporaryDirectory = new File(System.getProperty("java.io.tmpdir"), "AGENT_TMP");
- this.temporaryDirectory.mkdirs();
- } else {
- this.temporaryDirectory = temporaryDirectory;
- }
+ this.temporaryDirectory = temporaryDirectory;
this.eventContext = eventContext;
this.operationContext = operationContext;
@@ -212,9 +200,8 @@ public class ResourceContext<T extends ResourceComponent<?>> {
if (resource.getParentResource() != null) {
parentResourceUuid = resource.getParentResource().getUuid();
}
- this.trackedProcesses = getTrackedProcesses(parentResourceUuid, resourceType);
+ this.trackedProcesses = getTrackedProcesses(parentResourceUuid, resource.getResourceType());
- this.resourceUuid = resource.getUuid();
this.componentInvocationContext = componentInvocationContext;
}
@@ -226,7 +213,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @return resource key of the associated resource
*/
public String getResourceKey() {
- return this.resourceKey;
+ return this.resource.getResourceKey();
}
/**
@@ -235,7 +222,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @return type of the associated resource
*/
public ResourceType getResourceType() {
- return this.resourceType;
+ return this.resource.getResourceType();
}
/**
@@ -246,7 +233,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @since 1.2
*/
public String getVersion() {
- return this.version;
+ return this.resource.getVersion();
}
/**
@@ -255,10 +242,10 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @return resource data directory
*/
public File getResourceDataDirectory() {
- File resourceDataDirectory = new File(dataDirectory, this.getAncestryBasedResourceKey());
+ File resourceDataDirectory = new File(baseDataDirectory, this.getAncestryBasedResourceKey());
try {
- File oldResourceDataDirectory = new File(dataDirectory, this.resourceUuid);
+ File oldResourceDataDirectory = new File(baseDataDirectory, this.resource.getUuid());
if (oldResourceDataDirectory.exists()) {
oldResourceDataDirectory.renameTo(resourceDataDirectory);
}
@@ -282,7 +269,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @return child resource data directory
*/
public File getFutureChildResourceDataDirectory(String childResourceKey) {
- File childResourceDataDirectory = new File(dataDirectory, this.getAncestryBasedResourceKey(childResourceKey));
+ File childResourceDataDirectory = new File(baseDataDirectory, this.getAncestryBasedResourceKey(childResourceKey));
if (!childResourceDataDirectory.exists()) {
childResourceDataDirectory.mkdirs();
}
@@ -305,7 +292,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* (This method is protected to be able to share that information with the {@link ResourceUpgradeContext}
* but at the same time to not pollute the ResourceContext public API with data that doesn't belong
* to it).
- *
+ *
* @return
*/
protected ResourceContext<?> getParentResourceContext() {
@@ -339,7 +326,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* Returns the information on the native operating system process in which the managed resource is running. If
* native support is not available or the process for some reason can no longer be found, this may return <code>
* null</code>.
- *
+ *
* The returned {@link ProcessInfo} always has a fresh snapshot of non static data: it's whether newly created
* or got refreshed in order to determine if the process was still running.
*
@@ -352,7 +339,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
//right, we've entered the critical section...
//we might have waited for another thread to actually fill in the tracked processes
//so let's check again if we really need to run the discovery
- processInfo = trackedProcesses.getProcessInfo(resourceKey);
+ processInfo = trackedProcesses.getProcessInfo(resource.getResourceKey());
if (isRediscoveryRequired(processInfo)) {
@@ -367,7 +354,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
if (!processes.isEmpty()) {
ResourceDiscoveryContext<T> context;
- context = new ResourceDiscoveryContext<T>(this.resourceType, this.parentResourceComponent,
+ context = new ResourceDiscoveryContext<T>(this.resource.getResourceType(), this.parentResourceComponent,
this.parentResourceContext, this.systemInformation, processes, Collections.EMPTY_LIST,
getPluginContainerName(), getPluginContainerDeployment());
@@ -375,9 +362,9 @@ public class ResourceContext<T extends ResourceComponent<?>> {
}
trackedProcesses.update(details);
- processInfo = trackedProcesses.getProcessInfo(resourceKey);
+ processInfo = trackedProcesses.getProcessInfo(resource.getResourceKey());
} catch (Exception e) {
- LOG.warn("Cannot get native process for resource [" + this.resourceKey + "] - discovery failed", e);
+ LOG.warn("Cannot get native process for resource [" + this.resource.getResourceKey() + "] - discovery failed", e);
}
}
}
@@ -409,7 +396,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
try {
- Set<ProcessScan> processScans = this.resourceType.getProcessScans();
+ Set<ProcessScan> processScans = this.resource.getResourceType().getProcessScans();
if (processScans != null && !processScans.isEmpty()) {
ProcessInfoQuery piq = new ProcessInfoQuery(systemInfo.getAllProcesses());
for (ProcessScan processScan : processScans) {
@@ -437,6 +424,10 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @return location for plugin temporary files
*/
public File getTemporaryDirectory() {
+ if (this.temporaryDirectory==null) {
+ this.temporaryDirectory = new File(System.getProperty("java.io.tmpdir"), "AGENT_TMP");
+ this.temporaryDirectory.mkdirs();
+ }
return temporaryDirectory;
}
@@ -448,14 +439,14 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @return location for plugins to store persisted data
*/
public File getDataDirectory() {
- return dataDirectory;
+ return new File(baseDataDirectory, resource.getResourceType().getPlugin());
}
/**
* The name of the plugin container in which the resource component is running. Components
* can be assured this name is unique across <b>all</b> plugin containers/agents running
* in the RHQ environment.
- *
+ *
* @return the name of the plugin container
*/
public String getPluginContainerName() {
@@ -465,7 +456,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
/**
* Indicates where the plugin container (and therefore where the plugins) are deployed and running.
* See {@link PluginContainerDeployment} for more information on what the return value means.
- *
+ *
* @return indicator of where the plugin container is deployed and running
*
* @since 1.3
@@ -540,7 +531,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* Note that this comes from a static field so it is shared by any resource contexts representing a
* resource of the same type under a single parent. This is to reduce the number of needed discoveries
* to a minimum.
- *
+ *
* @param parentResourceUuid
* @param resourceType
* @return
@@ -581,7 +572,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
messageDigest.add(prefixKey.getBytes());
}
- messageDigest.add(this.resourceKey.getBytes());
+ messageDigest.add(this.resource.getResourceKey().getBytes());
ResourceContext<?> ancestor = this.parentResourceContext;
while (ancestor != null) {
@@ -607,6 +598,6 @@ public class ResourceContext<T extends ResourceComponent<?>> {
* @return a {@link String} representation of the underlying resource
*/
public String getResourceDetails() {
- return resourceDetails;
+ return resource.toString();
}
}
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceTypeProcesses.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceTypeProcesses.java
index 8e509da..7999d94 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceTypeProcesses.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceTypeProcesses.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.core.pluginapi.inventory;
@@ -32,26 +32,39 @@ import org.rhq.core.system.ProcessInfo;
*/
class ResourceTypeProcesses {
- private HashMap<String, ProcessInfo> processes = new HashMap<String, ProcessInfo>();
-
+ private HashMap<String, ProcessInfo> processes;
+
//why do we synchronize on something different than "this"? because if the callers
//synchronize on "this" and try to call some of the below methods outside of that
//synchronized block, they won't deadlock, which they would if the below methods were
//syncing on "this" (i.e. if the methods below were synchronized).
private final Object lock = new Object();
-
+
public ProcessInfo getProcessInfo(String resourceKey) {
synchronized(lock) {
+ if (processes==null) {
+ return null;
+ }
return processes.get(resourceKey);
}
}
-
+
public void update(Set<DiscoveredResourceDetails> discoveryResults) {
synchronized(lock) {
- processes.clear();
+ if (processes!=null) {
+ processes.clear();
+ }
+
+ if (discoveryResults==null || discoveryResults.isEmpty()) {
+ return;
+ }
+
+ if (processes==null) {
+ processes = new HashMap<String, ProcessInfo>(discoveryResults.size());
+ }
for (DiscoveredResourceDetails details : discoveryResults) {
processes.put(details.getResourceKey(), details.getProcessInfo());
}
}
- }
+ }
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
index b5347a1..92b7d56 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
@@ -1958,7 +1958,6 @@ public class InventoryManager extends AgentService implements ContainerService,
private <T extends ResourceComponent<?>> ResourceContext<T> createResourceContext(Resource resource,
T parentComponent, ResourceContext<?> parentResourceContext, ResourceDiscoveryComponent<T> discoveryComponent) {
- File pluginDataDir = new File(this.configuration.getDataDirectory(), resource.getResourceType().getPlugin());
return new ResourceContext<T>(resource, // the resource itself
parentComponent, // its parent component
@@ -1966,7 +1965,7 @@ public class InventoryManager extends AgentService implements ContainerService,
discoveryComponent, // the discovery component (this is actually the proxy to it)
SystemInfoFactory.createSystemInfo(), // for native access
this.configuration.getTemporaryDirectory(), // location for plugin to write temp files
- pluginDataDir, // location for plugin to write data files
+ this.configuration.getDataDirectory(), // location for plugin to write data files
this.configuration.getContainerName(), // the name of the agent/PC
getEventContext(resource), // for event access
getOperationContext(resource), // for operation manager access
commit 7ec05bceca21a337cbfc15dbb33d9b67447a9ad6
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Dec 27 12:15:10 2013 +0100
Don't fail if rawConfigurations (in agent, after cleanout) are null.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
index bf3a9cd..7113b35 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
@@ -393,7 +393,7 @@ public class Configuration implements Serializable, Cloneable, AbstractPropertyM
@Cascade({ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "configuration", fetch = FetchType.EAGER)
@XmlTransient
- private Map<String, Property> properties = new LinkedHashMap<String, Property>();
+ private Map<String, Property> properties = new LinkedHashMap<String, Property>(1);
private class PropertiesProxy implements Collection<Property> {
@@ -828,10 +828,16 @@ public class Configuration implements Serializable, Cloneable, AbstractPropertyM
public void addRawConfiguration(RawConfiguration rawConfiguration) {
rawConfiguration.setConfiguration(this);
+ if (rawConfigurations==null) {
+ rawConfigurations = new HashSet<RawConfiguration>(1);
+ }
rawConfigurations.add(rawConfiguration);
}
public boolean removeRawConfiguration(RawConfiguration rawConfiguration) {
+ if (rawConfigurations==null) {
+ return true;
+ }
boolean removed = rawConfigurations.remove(rawConfiguration);
if (removed) {
rawConfiguration.setConfiguration(null);
@@ -923,6 +929,9 @@ public class Configuration implements Serializable, Cloneable, AbstractPropertyM
}
private void createDeepCopyOfRawConfigs(Configuration copy, boolean keepId) {
+ if (rawConfigurations==null) {
+ return;
+ }
for (RawConfiguration rawConfig : rawConfigurations) {
copy.addRawConfiguration(rawConfig.deepCopy(keepId));
}
@@ -953,12 +962,38 @@ public class Configuration implements Serializable, Cloneable, AbstractPropertyM
Configuration that = (Configuration) obj;
- return (this.properties.equals(that.properties)) && (this.rawConfigurations.equals(that.rawConfigurations));
+ if (this.properties == null || this.properties.isEmpty()){
+ if ( that.properties== null || that.properties.isEmpty()) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ } else {
+ if (!this.properties.equals(that.properties)) {
+ return false;
+ }
+ }
+
+ boolean rcEquals=true;
+ if (this.rawConfigurations!=null) {
+ rcEquals = this.getRawConfigurations().equals(that.getRawConfigurations());
+ }
+ return (this.properties.equals(that.properties)) && rcEquals;
}
@Override
public int hashCode() {
- return properties.hashCode() * rawConfigurations.hashCode() * 19;
+ int hc = 1;
+ if (properties!=null ) {
+ hc = properties.hashCode(); // TODO this requires loading of all properties and is expensive
+ }
+
+ if (rawConfigurations!=null) {
+ int rchc = rawConfigurations.hashCode() ;
+ hc = hc * rchc + 19;
+ }
+ return hc ;
}
@Override
@@ -996,8 +1031,13 @@ public class Configuration implements Serializable, Cloneable, AbstractPropertyM
}
builder.append("], rawConfigurations[");
- for (RawConfiguration rawConfig : rawConfigurations) {
- builder.append("[").append(rawConfig.getPath()).append(", ").append(rawConfig.getSha256()).append("]");
+ if (rawConfigurations!=null) {
+ for (RawConfiguration rawConfig : rawConfigurations) {
+ builder.append("[").append(rawConfig.getPath()).append(", ").append(rawConfig.getSha256()).append("]");
+ }
+ }
+ else {
+ builder.append("-none-");
}
builder.append("]");
}