blob: 42bdc1c4c3a8b8358db222c8a08df4815e76b03c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.webconsole.plugins.memoryusage.internal;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.metatype.AttributeDefinition;
import org.osgi.service.metatype.MetaTypeProvider;
import org.osgi.service.metatype.ObjectClassDefinition;
class MemoryUsageConfigurator implements ManagedService, MetaTypeProvider
{
private final MemoryUsageSupport support;
private ObjectClassDefinition ocd;
MemoryUsageConfigurator(final MemoryUsageSupport support)
{
this.support = support;
}
@SuppressWarnings("unchecked")
public void updated(Dictionary properties) throws ConfigurationException
{
// ensure default values if there is no config or config is deleted
if (properties == null)
{
properties = new Hashtable();
}
final Object thresholdValue = properties.get(MemoryUsageConstants.PROP_DUMP_THRESHOLD);
if (thresholdValue != null)
{
final int threshold;
if (thresholdValue instanceof Number)
{
threshold = ((Number) thresholdValue).intValue();
}
else
{
// try to convert
try
{
threshold = Integer.parseInt(thresholdValue.toString());
}
catch (NumberFormatException nfe)
{
throw thresholdFailure(thresholdValue);
}
}
try
{
support.setThreshold(threshold);
}
catch (IllegalArgumentException iae)
{
throw thresholdFailure(iae.getMessage());
}
}
else
{
support.setThreshold(-1);
}
final Object intervalValue = properties.get(MemoryUsageConstants.PROP_DUMP_INTERVAL);
if (intervalValue != null)
{
final int interval;
if (intervalValue instanceof Number)
{
interval = ((Number) intervalValue).intValue();
}
else
{
// try to convert
try
{
interval = Integer.parseInt(intervalValue.toString());
}
catch (NumberFormatException nfe)
{
throw intervalFailure(intervalValue);
}
}
try
{
support.setInterval(interval);
}
catch (IllegalArgumentException iae)
{
throw intervalFailure(iae.getMessage());
}
}
else
{
support.setInterval(-1);
}
final Object locationValue = properties.get(MemoryUsageConstants.PROP_DUMP_LOCATION);
if (locationValue instanceof String)
{
support.setDumpLocation((String) locationValue);
}
else
{
support.setDumpLocation(null);
}
}
public String[] getLocales()
{
return null;
}
public ObjectClassDefinition getObjectClassDefinition(String id, String locale)
{
if (!MemoryUsageConstants.PID.equals(id))
{
return null;
}
if (ocd == null)
{
final ArrayList<AttributeDefinition> adList = new ArrayList<AttributeDefinition>();
adList.add(new AttributeDefinitionImpl(MemoryUsageConstants.PROP_DUMP_THRESHOLD, "Dump Threshold",
"Threshold at which to automatically create a memory dump as a percentage in the range "
+ MemoryUsageConstants.MIN_DUMP_THRESHOLD + " to " + MemoryUsageConstants.MAX_DUMP_THRESHOLD
+ " or zero to disable automatic dump creation.", AttributeDefinition.INTEGER, new String[]
{ String.valueOf(MemoryUsageConstants.DEFAULT_DUMP_THRESHOLD) }, 0, null, null)
{
@Override
public String validate(String value)
{
try
{
int threshold = Integer.parseInt(value);
if (!MemoryUsageConstants.isThresholdValid(threshold))
{
return "Dump Threshold must in the range " + MemoryUsageConstants.MIN_DUMP_THRESHOLD
+ " to " + MemoryUsageConstants.MAX_DUMP_THRESHOLD + " or zero";
}
return ""; // everything ok
}
catch (NumberFormatException nfe)
{
return "Dump Threshhold must be numeric";
}
}
});
adList.add(new AttributeDefinitionImpl(MemoryUsageConstants.PROP_DUMP_INTERVAL, "Dump Interval",
"The minimum interval between two consecutive memory dumps being taken in seconds. "
+ "This property allows the limitation of the number of memory dumps being taken. "
+ "The default value for the interval is 6 hours. This means that a memory threshold "
+ "event is ignored unless the last memory dump has been taken at least 6 hours earlier. "
+ "This property allows limiting the number of memory dumps in case memory consumption is "
+ "oscillating around the threshold point. The property must be an integer value or be "
+ "parseable to an integer value. This should be a positive value or zero to force each "
+ "memory threshold event to cause a memory dump (discouraged).", AttributeDefinition.INTEGER,
new String[]
{ String.valueOf(MemoryUsageConstants.DEFAULT_DUMP_INTERVAL) }, 0, null, null)
{
@Override
public String validate(String value)
{
try
{
int interval = Integer.parseInt(value);
if (interval < 0)
{
return "Dump Interval must be zero or a positive number";
}
return ""; // everything ok
}
catch (NumberFormatException nfe)
{
return "Dump Interval must be numeric";
}
}
});
adList.add(new AttributeDefinitionImpl(MemoryUsageConstants.PROP_DUMP_LOCATION, "Dumpe Location",
"The filesystem location where heap dumps are stored. If this is null or empty (the default) the dumps are stored in "
+ support.getDefaultDumpLocation(), ""));
ocd = new ObjectClassDefinition()
{
private final AttributeDefinition[] attrs = adList.toArray(new AttributeDefinition[adList.size()]);
public String getName()
{
return "Apache Felix Web Console Memory Usage Plugin";
}
public InputStream getIcon(int arg0)
{
return null;
}
public String getID()
{
return MemoryUsageConstants.PID;
}
public String getDescription()
{
return "Configuration of the Apache Felix Web Console Memory Usage Plugin.";
}
public AttributeDefinition[] getAttributeDefinitions(int filter)
{
return (filter == OPTIONAL) ? null : attrs;
}
};
}
return ocd;
}
private ConfigurationException thresholdFailure(final Object invalidValue)
{
return new ConfigurationException(MemoryUsageConstants.PROP_DUMP_THRESHOLD, "Invalid Dump Threshold value '"
+ invalidValue + "': Must be an integer number in the range " + MemoryUsageConstants.MIN_DUMP_THRESHOLD
+ " to " + MemoryUsageConstants.MAX_DUMP_THRESHOLD + " or zero to disable");
}
private ConfigurationException intervalFailure(final Object invalidValue)
{
return new ConfigurationException(MemoryUsageConstants.PROP_DUMP_INTERVAL, "Invalid Dump Interval value '"
+ invalidValue + "': Must be a positive integer number or zero to disable");
}
private static class AttributeDefinitionImpl implements AttributeDefinition
{
private final String id;
private final String name;
private final String description;
private final int type;
private final String[] defaultValues;
private final int cardinality;
private final String[] optionLabels;
private final String[] optionValues;
AttributeDefinitionImpl(final String id, final String name, final String description, final String defaultValue)
{
this(id, name, description, STRING, new String[]
{ defaultValue }, 0, null, null);
}
AttributeDefinitionImpl(final String id, final String name, final String description, final int type,
final String[] defaultValues, final int cardinality, final String[] optionLabels,
final String[] optionValues)
{
this.id = id;
this.name = name;
this.description = description;
this.type = type;
this.defaultValues = defaultValues;
this.cardinality = cardinality;
this.optionLabels = optionLabels;
this.optionValues = optionValues;
}
public int getCardinality()
{
return cardinality;
}
public String[] getDefaultValue()
{
return defaultValues;
}
public String getDescription()
{
return description;
}
public String getID()
{
return id;
}
public String getName()
{
return name;
}
public String[] getOptionLabels()
{
return optionLabels;
}
public String[] getOptionValues()
{
return optionValues;
}
public int getType()
{
return type;
}
public String validate(String arg0)
{
return null;
}
}
}