View Javadoc

1   /*
2    * Copyright (c) 1998-2004 The Jgroup Team.
3    *
4    * This program is free software; you can redistribute it and/or modify
5    * it under the terms of the GNU Lesser General Public License version 2 as
6    * published by the Free Software Foundation.
7    *
8    * This program is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   * GNU Lesser General Public License for more details.
12   *
13   * You should have received a copy of the GNU Lesser General Public License
14   * along with this program; if not, write to the Free Software
15   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16   *
17   */
18  
19  package jgroup.relacs.gmi;
20  
21  import java.io.Serializable;
22  import java.lang.reflect.Method;
23  import java.rmi.Remote;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.Map;
27  
28  import org.apache.log4j.Logger;
29  
30  /**
31   * Table mapping a method (represented by a hash of the method or by
32   * a <code>Method</code> object) to its <code>MethodDetails</code> object.
33   * 
34   * The mapping from <code>Method</code> objects will only be populated
35   * on the client-side since those are only used there.
36   *
37   * @author Hein Meling
38   * @since Jgroup 3.0
39   */
40  public class MethodTable
41    implements Serializable, Iterable<MethodDetails>
42  {
43  
44    private static final long serialVersionUID = -7706887009118848315L;
45  
46    ////////////////////////////////////////////////////////////////////////////////////////////
47    // Logger
48    ////////////////////////////////////////////////////////////////////////////////////////////
49  
50    /** Obtain logger for this class */
51    private static final Logger log = Logger.getLogger(MethodTable.class);
52  
53  
54    ////////////////////////////////////////////////////////////////////////////////////////////
55    // Fields
56    ////////////////////////////////////////////////////////////////////////////////////////////
57  
58    /** Table of methods (mapping from hash value to method details object) */
59    private final Map<Long,MethodDetails> table = new HashMap<Long,MethodDetails>();
60  
61    /** Table mapping from method to method details object (only client-side) */
62    private transient Map<Method,MethodDetails> methTable;
63  
64  
65    ////////////////////////////////////////////////////////////////////////////////////////////
66    // Constructor
67    ////////////////////////////////////////////////////////////////////////////////////////////
68  
69    public MethodTable()
70    {
71    }
72  
73  
74    ////////////////////////////////////////////////////////////////////////////////////////////
75    // Methods
76    ////////////////////////////////////////////////////////////////////////////////////////////
77  
78    /**
79     * Add remote methods implemented by the given server to this
80     * method table.  All methods defined in a <code>Remote</code>
81     * interface will be added, and their associated invocation
82     * semantics details will be computed.
83     */
84    public void addMethods(Object server)
85    {
86      /*
87       * Find all the remote interfaces implemented by the given
88       * server object, and compute relevant method information.
89       */
90      Class serverClass = server.getClass();
91      Class[] interfaces = serverClass.getInterfaces();
92      for (int i = 0; i < interfaces.length; i++) {
93        if (Remote.class.isAssignableFrom(interfaces[i])) {
94          Method methods[] = interfaces[i].getMethods();
95          for (int j = 0; j < methods.length; j++) {
96            MethodDetails meth = new MethodDetails(methods[j], server);
97            table.put(meth.getHash(), meth);
98            if (log.isDebugEnabled())
99              log.debug("Adding: " + meth);
100         }
101       }
102     }
103   }
104 
105   /**
106    * Get the method details associated with the given hash value.
107    */
108   public MethodDetails get(long hash)
109   {
110     return table.get(hash);
111   }
112 
113   /**
114    * Return the method details object associated with the given method.
115    */
116   public MethodDetails get(Method m)
117   {
118     if (methTable == null) {
119       methTable = new HashMap<Method,MethodDetails>();
120     }
121     MethodDetails method = methTable.get(m);
122     if (method == null) {
123       long hash = MethodDetails.computeHash(m);
124       method = get(hash);
125       methTable.put(m, method);
126     }
127     return method;
128   }
129 
130 
131   ////////////////////////////////////////////////////////////////////////////////////////////
132   // Methods from Iterable<MethodDetails>
133   ////////////////////////////////////////////////////////////////////////////////////////////
134 
135   public Iterator<MethodDetails> iterator()
136   {
137     return table.values().iterator();
138   }
139 
140 
141   ////////////////////////////////////////////////////////////////////////////////////////////
142   // Object methods
143   ////////////////////////////////////////////////////////////////////////////////////////////
144 
145   public String toString()
146   {
147     StringBuilder buf = new StringBuilder("MethodTable[");
148     for (Map.Entry<Long,MethodDetails> entry : table.entrySet()) {
149       MethodDetails meth = entry.getValue();
150       buf.append("\n");
151       buf.append(entry.getKey());
152       buf.append(" -> ");
153       buf.append(meth);
154       Object server = meth.getServer();
155       if (server != null) {
156         // the server object is only available on the server-side
157         buf.append("; server=");
158         buf.append(server.getClass().getSimpleName());
159       }
160     }
161     buf.append("]");
162     return buf.toString();
163   }
164 
165 } // END MethodTable