| /* |
| * 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; |
| } |
| } |
| } |