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