001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.management.domain.model;
022
023 import java.util.ArrayList;
024 import java.util.LinkedList;
025 import java.util.List;
026 import java.util.Map;
027 import java.util.Map.Entry;
028
029 import javax.management.MBeanAttributeInfo;
030 import javax.management.MBeanFeatureInfo;
031 import javax.management.MBeanOperationInfo;
032 import javax.management.MBeanParameterInfo;
033
034 import org.apache.qpid.management.configuration.Configuration;
035 import org.apache.qpid.management.configuration.UnknownTypeCodeException;
036 import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
037 import org.apache.qpid.management.Names;
038
039 /**
040 * A builder used to parse incoming schema message and therefore to build a feature (property, statistic, method, event)
041 * definition.
042 * In order to set up the correct state for this builder, clients must create an instance of this class
043 * The product of the builder will be a QpidFeature and a JMX Managemtn feature used for describing that feature in a
044 * JMX environment. So, for example, for building a property definition client code should be :
045 *
046 * <br>- QpidFeatureBuilder builder = QpidFeature.createPropertyBuilder(...);
047 * <br>- builder.build();
048 * <br>- QpidProperty property = (QpidProperty) builder.getQpidFeature();
049 * <br>- MBeanAttributeInfo managementAttributeInfo = (MBeanAttributeInfo)builder.getManagementFeature();
050 *
051 * <br>N.B.: a builder instance is not supposed to be reused. One instance for one feature!
052 *
053 * @author Andrea Gazzarini
054 */
055 class QpidFeatureBuilder
056 {
057
058 static enum Attribute {
059 name,type,access,index,optional,unit,min,max,maxlen,desc,dir,argCount;
060 };
061
062 private List<Attribute> _mandatoryAttributes = new ArrayList<Attribute>();
063
064 /**
065 * Builder state for this class.
066 * Each concrete implementor is a builder for a specific feature.
067 * using the appropriate factory method.
068 *
069 * @author Andrea Gazzarini
070 */
071 interface State {
072 void build() throws UnableToBuildFeatureException;
073 }
074
075 /**
076 * Builder used for building property definition.
077 */
078 final State _propertyBuilder = new State() {
079
080 /**
081 * Builds a property definition as well a management attribute feature.
082 */
083 public void build () throws UnableToBuildFeatureException
084 {
085 QpidProperty property = new QpidProperty();
086 try {
087 int optionalIndex = 0;
088 for (Entry<String, Object> propertyAttribute : _featureDefinition.entrySet())
089 {
090 Attribute attribute = Attribute.valueOf(propertyAttribute.getKey());
091 switch(attribute)
092 {
093 case name :
094 {
095 property.setName(String.valueOf(propertyAttribute.getValue()));
096 break;
097 }
098 case access :
099 {
100 int code = (Integer)propertyAttribute.getValue();
101 property.setAccessMode(Configuration.getInstance().getAccessMode(code));
102 break;
103 }
104 case unit :
105 {
106 property.setUnit(String.valueOf(propertyAttribute.getValue()));
107 break;
108 }
109 case min :
110 {
111 property.setMinValue((Integer)propertyAttribute.getValue());
112 break;
113 }
114 case max :
115 {
116 property.setMaxValue((Integer)propertyAttribute.getValue());
117 break;
118 }
119 case maxlen :
120 {
121 property.setMaxLength((Integer)propertyAttribute.getValue());
122 break;
123 }
124 case desc :
125 {
126 property.setDescription(String.valueOf(propertyAttribute.getValue()));
127 break;
128 }
129 case type :
130 {
131 int code = (Integer) propertyAttribute.getValue();
132 property.setType(Configuration.getInstance().getType(code));
133 break;
134 }
135 case index :
136 {
137 break;
138 }
139 case optional :
140 {
141 int code = (Integer) propertyAttribute.getValue();
142 if (code == 1)
143 {
144 property.markAsOptional(optionalIndex);
145 optionalIndex++;
146 }
147 break;
148 }
149 }
150 _mandatoryAttributes.remove(attribute);
151 }
152 } catch(Exception exception)
153 {
154 throw new UnableToBuildFeatureException(exception,property.getName());
155 }
156
157 if (!_mandatoryAttributes.isEmpty())
158 {
159 throw new MissingFeatureAttributesException(_mandatoryAttributes);
160 }
161
162 _managementFeatureInfo = new MBeanAttributeInfo(
163 property.getName(),
164 property.getJavaType().getName(),
165 property.getDescription(),
166 true,
167 property.getAccessMode()==AccessMode.RW,
168 false);
169 _qpidFeature = property;
170 }
171 };
172
173 final State _statisticBuilder = new State()
174 {
175 public void build () throws UnableToBuildFeatureException
176 {
177 QpidStatistic statistic = new QpidStatistic();
178 try
179 {
180 for (Entry<String, Object> statisticAttribute : _featureDefinition.entrySet())
181 {
182 Attribute attribute = Attribute.valueOf(statisticAttribute.getKey());
183 switch(attribute)
184 {
185 case name :
186 {
187 statistic.setName(String.valueOf(statisticAttribute.getValue()));
188 break;
189 }
190 case unit :
191 {
192 statistic.setUnit(String.valueOf(statisticAttribute.getValue()));
193 break;
194 }
195 case desc :
196 {
197 statistic.setDescription(String.valueOf(statisticAttribute.getValue()));
198 break;
199 }
200 case type :
201 {
202 int code = (Integer) statisticAttribute.getValue();
203 statistic.setType(Configuration.getInstance().getType(code));
204 break;
205 }
206 }
207 _mandatoryAttributes.remove(attribute);
208 }
209 } catch(Exception exception)
210 {
211 throw new UnableToBuildFeatureException(exception,statistic.getName());
212 }
213
214 if (!_mandatoryAttributes.isEmpty())
215 {
216 throw new MissingFeatureAttributesException(_mandatoryAttributes);
217 }
218
219 _managementFeatureInfo = new MBeanAttributeInfo(
220 statistic.getName(),
221 statistic.getJavaType().getName(),
222 statistic.getDescription(),
223 true,
224 false,
225 false);
226 _qpidFeature = statistic;
227 }
228 };
229
230 /**
231 * Builder used for building a statistic definition.
232 */
233 final State _argumentBuilder = new State()
234 {
235 /**
236 * Builds a property definition as well a management attribute feature.
237 */
238 public void build () throws UnableToBuildFeatureException
239 {
240 QpidArgument argument = new QpidArgument();
241 for (Entry<String, Object> argumentAttribute : _featureDefinition.entrySet())
242 {
243 String key = argumentAttribute.getKey();
244 if (Names.DEFAULT_PARAM_NAME.equals(key))
245 {
246 argument.setDefaultValue(argumentAttribute.getValue());
247 } else {
248 Attribute attribute = Attribute.valueOf(key);
249 switch (attribute)
250 {
251 case name :
252 {
253 argument.setName((String)argumentAttribute.getValue());
254 break;
255 }
256 case desc :
257 {
258 argument.setDescription((String)argumentAttribute.getValue());
259 break;
260 }
261 case type :
262 {
263 try
264 {
265 argument.setType(Configuration.getInstance().getType((Integer)argumentAttribute.getValue()));
266 break;
267 } catch(UnknownTypeCodeException exception)
268 {
269 throw new UnableToBuildFeatureException(exception,argument.getName());
270 }
271 }
272 case dir :
273 {
274 argument.setDirection((String)argumentAttribute.getValue());
275 break;
276 }
277 case unit :
278 {
279 argument.setUnit((String)argumentAttribute.getValue());
280 break;
281
282 }
283 }
284 }
285 }
286
287 if (!_mandatoryAttributes.isEmpty())
288 {
289 throw new MissingFeatureAttributesException(_mandatoryAttributes);
290 }
291
292 _qpidFeature = argument;
293 _managementFeatureInfo = new MBeanParameterInfo(
294 argument.getName(),
295 argument.getJavaType().getName(),
296 argument.getDescription());
297 }
298 };
299
300 final State _methodBuilder = new State()
301 {
302 public void build () throws UnableToBuildFeatureException
303 {
304 Map<String,Object> definition = _methodOrEventDefinition.getDefinition();
305 String name = (String)definition.get(Attribute.name.name());
306 if (name == null)
307 {
308 throw new MissingFeatureAttributesException(_mandatoryAttributes);
309 }
310
311 QpidMethod method = new QpidMethod((String)definition.get(Attribute.name.name()),(String) definition.get(Attribute.desc.name()));
312
313 List<Map<String,Object>> args = _methodOrEventDefinition.getArgumentsDefinitions();
314
315 List<MBeanParameterInfo> signature = new LinkedList<MBeanParameterInfo>();
316
317 for (Map<String,Object> argumentDefinition : args)
318 {
319 QpidFeatureBuilder builder = QpidFeatureBuilder.createArgumentBuilder(argumentDefinition);
320 builder.build();
321
322 QpidArgument argument = (QpidArgument) builder.getQpidFeature();
323 method.addArgument(argument);
324 if (argument.isInput())
325 {
326 signature.add((MBeanParameterInfo) builder.getManagementFeature());
327 }
328 }
329
330 _qpidFeature = method;
331 _managementFeatureInfo = new MBeanOperationInfo(
332 method.getName(),
333 method.getDescription(),
334 (MBeanParameterInfo[])signature.toArray(new MBeanParameterInfo[signature.size()]),
335 void.class.getName(),
336 MBeanOperationInfo.ACTION);
337 }
338 };
339
340 final State _eventBuilder = new State()
341 {
342 public void build () throws UnableToBuildFeatureException
343 {
344 }
345 };
346
347 private MBeanFeatureInfo _managementFeatureInfo;
348 private QpidFeature _qpidFeature;
349 private final Map <String, Object> _featureDefinition;
350 private final MethodOrEventDataTransferObject _methodOrEventDefinition;
351 private State _state;
352
353 static QpidFeatureBuilder createPropertyBuilder(Map<String, Object> propertyDefinition)
354 {
355 QpidFeatureBuilder result = new QpidFeatureBuilder(propertyDefinition);
356 result._state = result._propertyBuilder;
357 result._mandatoryAttributes.add(Attribute.name);
358 result._mandatoryAttributes.add(Attribute.access);
359 result._mandatoryAttributes.add(Attribute.type);
360 result._mandatoryAttributes.add(Attribute.optional);
361 result._mandatoryAttributes.add(Attribute.index);
362 return result;
363 }
364
365 static QpidFeatureBuilder createStatisticBuilder(Map<String, Object> statisticDefinition)
366 {
367 QpidFeatureBuilder result = new QpidFeatureBuilder(statisticDefinition);
368 result._state = result._statisticBuilder;
369 result._mandatoryAttributes.add(Attribute.name);
370 result._mandatoryAttributes.add(Attribute.type);
371 return result;
372 }
373
374 static QpidFeatureBuilder createEventBuilder(Map<String, Object> eventDefinition)
375 {
376 QpidFeatureBuilder result = new QpidFeatureBuilder(eventDefinition);
377 result._state = result._eventBuilder;
378 return result;
379 }
380
381 static QpidFeatureBuilder createMethodBuilder(MethodOrEventDataTransferObject methodDefinition)
382 {
383 QpidFeatureBuilder result = new QpidFeatureBuilder(methodDefinition);
384 result._state = result._methodBuilder;
385 result._mandatoryAttributes.add(Attribute.name);
386 return result;
387 }
388
389 private static QpidFeatureBuilder createArgumentBuilder(Map<String, Object> argumentDefinition)
390 {
391 QpidFeatureBuilder result = new QpidFeatureBuilder(argumentDefinition);
392 result._state = result._argumentBuilder;
393 return result;
394 }
395
396
397 /**
398 * Builds new builder with the given data.
399 * This constructor is used for building properties, statistics and arguments.
400 *
401 * @param definition the feature definition data.
402 */
403 private QpidFeatureBuilder(Map<String, Object> definition)
404 {
405 this._featureDefinition = definition;
406 this._methodOrEventDefinition = null;
407 }
408
409 /**
410 * Builds new builder with the given data.
411 * This constructor is used for building properties, statistics and arguments.
412 *
413 * @param definition the feature definition data.
414 */
415 private QpidFeatureBuilder(MethodOrEventDataTransferObject definition)
416 {
417 this._featureDefinition = null;
418 this._methodOrEventDefinition = definition;
419 }
420
421 /**
422 * Returns the just built qpid feature.
423 *
424 * @return the qpid feature.
425 */
426 QpidFeature getQpidFeature()
427 {
428 return _qpidFeature;
429 }
430
431 /**
432 * Return the jmx metadata for the built feature.
433 *
434 * @return the jmx metadata for the built feature.
435 */
436 MBeanFeatureInfo getManagementFeature()
437 {
438 return _managementFeatureInfo;
439 }
440
441 void build() throws UnableToBuildFeatureException
442 {
443 try
444 {
445 _state.build();
446 } catch(UnableToBuildFeatureException exception)
447 {
448 throw exception;
449 } catch(Exception exception)
450 {
451 throw new UnableToBuildFeatureException(exception,"Feature name is not available for debugging.");
452 }
453 }
454 }
|