001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2008 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027package org.opends.server.types;
028
029import javax.management.Attribute;
030import javax.management.MBeanException;
031import javax.management.MBeanOperationInfo;
032import javax.management.MBeanParameterInfo;
033
034import org.opends.server.api.InvokableComponent;
035import org.opends.server.config.ConfigAttribute;
036
037import org.forgerock.i18n.slf4j.LocalizedLogger;
038
039
040
041/**
042 * This class defines a data structure that holds information about a
043 * method that may be invoked for an invokable component.
044 */
045@org.opends.server.types.PublicAPI(
046     stability=org.opends.server.types.StabilityLevel.VOLATILE,
047     mayInstantiate=false,
048     mayExtend=false,
049     mayInvoke=true)
050public class InvokableMethod
051{
052  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
053
054
055
056
057  /**
058   * Indicates whether this method retrieves information about the
059   * associated component.
060   */
061  private boolean retrievesComponentInfo;
062
063  /**
064   * Indicates whether this method updates information about the
065   * associated component.
066   */
067  private boolean updatesComponentInfo;
068
069  /** The set of arguments for this method. */
070  private ConfigAttribute[] arguments;
071
072  /** The description for this method. */
073  private String description;
074
075  /** The name for this method. */
076  private String name;
077
078  /** The return type for this method. */
079  private String returnType;
080
081
082
083  /**
084   * Creates a new invokable method with the provided information.
085   *
086   * @param  name                    The name for this invokable
087   *                                 method.
088   * @param  description             The description for this
089   *                                 invokable method.
090   * @param  arguments               The object types for this
091   *                                 method's arguments.
092   * @param  returnType              The object type for this method's
093   *                                 return value.
094   * @param  retrievesComponentInfo  Indicates whether this method
095   *                                 retrieves information about the
096   *                                 associated component.
097   * @param  updatesComponentInfo    Indicates whether this method
098   *                                 updates information about the
099   *                                 associated component.
100   */
101  public InvokableMethod(String name, String description,
102                         ConfigAttribute[] arguments,
103                         String returnType,
104                         boolean retrievesComponentInfo,
105                         boolean updatesComponentInfo)
106  {
107    this.name                     = name;
108    this.description              = description;
109    this.returnType               = returnType;
110    this.retrievesComponentInfo   = retrievesComponentInfo;
111    this.updatesComponentInfo     = updatesComponentInfo;
112
113    if (arguments == null)
114    {
115      this.arguments = new ConfigAttribute[0];
116    }
117    else
118    {
119      this.arguments = arguments;
120    }
121  }
122
123
124
125  /**
126   * Retrieves the name of this invokable method.
127   *
128   * @return  The name of this invokable method.
129   */
130  public String getName()
131  {
132    return name;
133  }
134
135
136
137  /**
138   * Retrieves a description of this invokable method.
139   *
140   * @return  A description of this invokable method.
141   */
142  public String getDescription()
143  {
144    return description;
145  }
146
147
148
149  /**
150   * Retrieves the set of arguments for this invokable method.
151   *
152   * @return  The set of arguments for this invokable method.
153   */
154  public ConfigAttribute[] getArguments()
155  {
156    return arguments;
157  }
158
159
160
161  /**
162   * Retrieves the return type for this invokable method.
163   *
164   * @return  The return type for this invokable method.
165   */
166  public String getReturnType()
167  {
168    return returnType;
169  }
170
171
172
173  /**
174   * Indicates whether this method retrieves information about the
175   * associated component.
176   *
177   * @return  <CODE>true</CODE> if this method retrieves information
178   *          about the associated component, or <CODE>false</CODE> if
179   *          it does not.
180   */
181  public boolean retrievesComponentInfo()
182  {
183    return retrievesComponentInfo;
184  }
185
186
187
188  /**
189   * Indicates whether this method updates information about the
190   * associated component.
191   *
192   * @return  <CODE>true</CODE> if this method updates information
193   *          about the associated component, or <CODE>false</CODE> if
194   *          it does not.
195   */
196  public boolean updatesComponentInfo()
197  {
198    return updatesComponentInfo;
199  }
200
201
202
203  /**
204   * Retrieves an <CODE>MBeanOperationInfo</CODE> object that
205   * encapsulates the information in this invokable method.
206   *
207   * @return  An <CODE>MBeanOperationInfo</CODE> object that
208   *          encapsulates the information in this invokable method.
209   */
210  public MBeanOperationInfo toOperationInfo()
211  {
212    MBeanParameterInfo[] signature =
213         new MBeanParameterInfo[arguments.length];
214    for (int i=0; i < arguments.length; i++)
215    {
216      signature[i] = arguments[i].toJMXParameterInfo();
217    }
218
219
220    int impact;
221    if (retrievesComponentInfo)
222    {
223      if (updatesComponentInfo)
224      {
225        impact = MBeanOperationInfo.ACTION_INFO;
226      }
227      else
228      {
229        impact = MBeanOperationInfo.INFO;
230      }
231    }
232    else if (updatesComponentInfo)
233    {
234      impact = MBeanOperationInfo.ACTION;
235    }
236    else
237    {
238      impact = MBeanOperationInfo.UNKNOWN;
239    }
240
241
242    return new MBeanOperationInfo(name, description, signature,
243                                  returnType, impact);
244
245  }
246
247
248
249  /**
250   * Indicates whether this invokable method has the provided
251   * signature.
252   *
253   * @param  methodName     The method name to use in the
254   *                        determination.
255   * @param  argumentTypes  The argument object types to use in the
256   *                        determination.
257   *
258   * @return  <CODE>true</CODE> if this invokable method has the
259   *          provided signature, or <CODE>false</CODE> if not.
260   */
261  public boolean hasSignature(String methodName,
262                              String[] argumentTypes)
263  {
264    if (! methodName.equals(name))
265    {
266      return false;
267    }
268
269    if (argumentTypes.length != arguments.length)
270    {
271      return false;
272    }
273
274    for (int i=0; i < arguments.length; i++)
275    {
276      MBeanParameterInfo paramInfo =
277           arguments[i].toJMXParameterInfo();
278      if (! argumentTypes[i].equals(paramInfo.getType()))
279      {
280        return false;
281      }
282    }
283
284    return true;
285  }
286
287
288
289  /**
290   * Calls upon the provided component to invoke this method using the
291   * given parameters.
292   *
293   * @param  component      The component to use to invoke this
294   *                        method.
295   * @param  parameters     The set of method arguments to use when
296   *                        invoking this method.
297   *
298   * @return  The return value resulting from invoking the method, or
299   *          <CODE>null</CODE> if it did not return a value.
300   *
301   * @throws  MBeanException  If a problem occurred while invoking the
302   *                          method.
303   */
304  public Object invoke(InvokableComponent component,
305                       Object[] parameters)
306         throws MBeanException
307  {
308    try
309    {
310      ConfigAttribute[] methodArguments =
311           new ConfigAttribute[arguments.length];
312      for (int i=0; i < arguments.length; i++)
313      {
314        Attribute jmxAttr = new Attribute(arguments[i].getName(),
315                                          parameters[i]);
316
317        methodArguments[i] = arguments[i].duplicate();
318        methodArguments[i].setValue(jmxAttr);
319      }
320
321      return component.invokeMethod(name, methodArguments);
322    }
323    catch (DirectoryException de)
324    {
325      logger.traceException(de);
326
327      throw new MBeanException(de, de.getMessage());
328    }
329    catch (Exception e)
330    {
331      logger.traceException(e);
332
333      throw new MBeanException(e);
334    }
335  }
336
337
338
339  /**
340   * Retrieves a string representation of this invokable method.  It
341   * will be in the form of a method signature, like "returnType
342   * name(arguments)".
343   *
344   * @return  a string representation of this invokable method.
345   */
346  public String toString()
347  {
348    StringBuilder buffer = new StringBuilder();
349
350    if (returnType == null)
351    {
352      buffer.append("void ");
353    }
354    else
355    {
356      buffer.append(returnType);
357    }
358
359    buffer.append(name);
360    buffer.append('(');
361
362    if (arguments != null && arguments.length > 0)
363    {
364      buffer.append(arguments[0].getDataType());
365      buffer.append(' ');
366      buffer.append(arguments[0].getName());
367
368      for (int i=1; i < arguments.length; i++)
369      {
370        buffer.append(", ");
371        buffer.append(arguments[i].getDataType());
372        buffer.append(' ');
373        buffer.append(arguments[i].getName());
374      }
375    }
376
377    buffer.append(')');
378
379    return buffer.toString();
380  }
381}
382