1    //
2    // SwitchRMI  Framework
3    // Copyright (c) 2000-2002 by Michael J. Henderson & Associates.
4    //
5    // Michael Henderson
6    // http://switchrmi.sf.net
7    // mailto:mikehenderson@dunelm.org.uk
8    //
9    // This library is free software.
10   //
11   // You may redistribute it and/or modify it under the terms of the GNU
12   // Lesser General Public License as published by the Free Software Foundation.
13   //
14   // Version 2.1 of the license should be included with this distribution in
15   // the file LICENSE, as well as License.html. If the license is not
16   // included with this distribution, you may find a copy at the FSF web
17   // site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
18   // Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.
19   //
20   // This library is distributed in the hope that it will be useful,
21   // but WITHOUT ANY WARRANTY; without even the implied waranty of
22   // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23   // Lesser General Public License for more details.
24   //
25   // $Id: XmlRpcMethodSignatures.java,v 1.1 2002/11/11 22:19:48 mikehenderson Exp $
26   package com.mjh.switchrmi.protocol.xmlrpc;
27   
28   import com.mjh.dom.DomUtil;
29   
30   import java.io.InputStream;
31   
32   import java.util.*;
33   
34   import javax.xml.parsers.DocumentBuilder;
35   import javax.xml.parsers.DocumentBuilderFactory;
36   
37   import org.apache.log4j.Logger;
38   import org.w3c.dom.Document;
39   import org.w3c.dom.Element;
40   import org.w3c.dom.Node;
41   import org.w3c.dom.NodeList;
42   
43   public class XmlRpcMethodSignatures
44   {
45       private static final Logger log = 
46               Logger.getLogger(XmlRpcMethodSignatures.class.getName());
47       private static HashMap classMap = new HashMap();
48       private static HashMap ignoredClassMap = new HashMap();
49       private static HashMap encodedSignatureMap = new HashMap();
50   
51       public static synchronized String getExternalNameForEncodedSignature(String signature)
52       {
53           String declaringClassName = 
54                   signature.substring(0, signature.indexOf(':'));
55   
56           if (log.isDebugEnabled())
57           {
58               log.debug("declaringClassName = " + declaringClassName);
59           }
60   
61           XmlRpcMethods xmlrpcMethods = 
62                   findMethodsForClassName(declaringClassName);
63   
64           return (xmlrpcMethods == null)
65                  ? null
66                  : xmlrpcMethods.getExternalNameForEncodedSignature(signature);
67       }
68   
69       private static XmlRpcMethods findMethodsForClassName(String declaringClassName)
70       {
71           XmlRpcMethods xmlrpcMethods = null;
72   
73           if (ignoredClassMap.get(declaringClassName) == null)
74           {
75               xmlrpcMethods = (XmlRpcMethods) classMap.get(declaringClassName);
76   
77               if (xmlrpcMethods == null)
78               {
79                   xmlrpcMethods = XmlRpcMethodSignatures.loadMethodsForClassName(
80                                           declaringClassName);
81   
82                   if (xmlrpcMethods != null)
83                   {
84                       classMap.put(declaringClassName, xmlrpcMethods);
85                   }
86                   else
87                   {
88                       ignoredClassMap.put(declaringClassName, declaringClassName);
89                   }
90               }
91           }
92   
93           return xmlrpcMethods;
94       }
95   
96       public static String getEncodedSignatureForExternalName(Class targetClass, 
97                                                               String externalName)
98       {
99           String result = null;
100          Class[] interfaces = targetClass.getInterfaces();
101  
102          for (int i = 0; i < interfaces.length; i++)
103          {
104              Class interfaze = interfaces[i];
105              String interfaceName = interfaze.getName();
106              XmlRpcMethods xmlrpcMethods = 
107                      findMethodsForClassName(interfaceName);
108  
109              if (xmlrpcMethods != null)
110              {
111                  result = xmlrpcMethods.getEncodedSignatureForExternalName(
112                                   externalName);
113  
114                  if (result != null)
115                  {
116                      break;
117                  }
118              }
119          }
120  
121          return result;
122      }
123  
124      private static XmlRpcMethods loadMethodsForClassName(String declaringClassName)
125      {
126          XmlRpcMethods result = null;
127  
128          try
129          {
130              String resourceName = 
131                      "/" + declaringClassName.replace('.', '/')
132                      + ".xmlrpcSignatures";
133              InputStream in = XmlRpcMethodSignatures.class.getResourceAsStream(
134                                       resourceName);
135  
136              if (in != null)
137              {
138                  result = new XmlRpcMethods(in);
139              }
140          }
141          catch (Exception ex)
142          {
143              log.debug("Exception", ex);
144          }
145  
146          return result;
147      }
148  
149      static class XmlRpcMethods
150      {
151          private final static String METHOD_TAG = "method";
152          private final static String INTERNAL_ATTR = "internal";
153          private final static String EXTERNAL_ATTR = "external";
154          private HashMap internals = new HashMap();
155          private HashMap externals = new HashMap();
156  
157          public XmlRpcMethods(InputStream in)
158                        throws Exception
159          {
160              parse(in);
161          }
162  
163          public String getExternalNameForEncodedSignature(String signature)
164          {
165              return (String) externals.get(signature);
166          }
167  
168          public String getEncodedSignatureForExternalName(String external)
169          {
170              return (String) internals.get(external);
171          }
172  
173          public String toString()
174          {
175              return "XmlRpcMethods {\n" + "  internals = " + internals + ";\n"
176                     + "  externals = " + externals + ";\n" + "}";
177          }
178  
179          private void parse(InputStream in)
180                      throws Exception
181          {
182              boolean debug = log.isDebugEnabled();
183  
184              try
185              {
186                  DocumentBuilderFactory factory = 
187                          DocumentBuilderFactory.newInstance();
188  
189                  if (log.isDebugEnabled())
190                  {
191                      log.debug("factory = " + factory);
192                  }
193  
194                  DocumentBuilder builder = factory.newDocumentBuilder();
195  
196                  if (log.isDebugEnabled())
197                  {
198                      log.debug("builder = " + builder);
199                  }
200  
201                  Document doc = (Document) builder.parse(in);
202  
203                  Node root = doc.getDocumentElement();
204                  NodeList list = 
205                          DomUtil.getChildElementsByTagName(root, METHOD_TAG);
206                  int length = list.getLength();
207  
208                  if (debug)
209                  {
210                      log.debug("length = " + length);
211                  }
212  
213                  for (int i = 0; i < length; i++)
214                  {
215                      Element element = (Element) list.item(i);
216  
217                      if (element.hasAttribute(INTERNAL_ATTR)
218                          && element.hasAttribute(EXTERNAL_ATTR))
219                      {
220                          String internal = element.getAttribute(INTERNAL_ATTR);
221                          String external = element.getAttribute(EXTERNAL_ATTR);
222  
223                          if (debug)
224                          {
225                              log.debug(external + " = " + internal);
226                          }
227  
228                          internals.put(external, internal);
229                          externals.put(internal, external);
230                      }
231                      else
232                      {
233                          throw new Exception("<" + METHOD_TAG
234                                              + " > missing attribute "
235                                              + INTERNAL_ATTR + " or "
236                                              + EXTERNAL_ATTR);
237                      }
238                  }
239              }
240              catch (Exception ex)
241              {
242                  if (log.isDebugEnabled())
243                  {
244                      log.debug("While Parsing", ex);
245                  }
246  
247                  throw ex;
248              }
249          }
250      }
251  }