001    /*
002     * Copyright (c) 2001-2004 Caucho Technology, Inc.  All rights reserved.
003     *
004     * The Apache Software License, Version 1.1
005     *
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions
008     * are met:
009     *
010     * 1. Redistributions of source code must retain the above copyright
011     *    notice, this list of conditions and the following disclaimer.
012     *
013     * 2. Redistributions in binary form must reproduce the above copyright
014     *    notice, this list of conditions and the following disclaimer in
015     *    the documentation and/or other materials provided with the
016     *    distribution.
017     *
018     * 3. The end-user documentation included with the redistribution, if
019     *    any, must include the following acknowlegement:
020     *       "This product includes software developed by the
021     *        Caucho Technology (http://www.caucho.com/)."
022     *    Alternately, this acknowlegement may appear in the software itself,
023     *    if and wherever such third-party acknowlegements normally appear.
024     *
025     * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
026     *    endorse or promote products derived from this software without prior
027     *    written permission. For written permission, please contact
028     *    info@caucho.com.
029     *
030     * 5. Products derived from this software may not be called "Resin"
031     *    nor may "Resin" appear in their names without prior written
032     *    permission of Caucho Technology.
033     *
034     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
035     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
036     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
037     * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
038     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
039     * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
040     * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
041     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
042     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
043     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
044     * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
045     *
046     * @author Scott Ferguson
047     */
048    
049    package com.caucho.services.server;
050    
051    import java.io.InputStream;
052    import java.lang.reflect.Method;
053    import java.util.HashMap;
054    
055    /**
056     * Proxy class for Hessian services.
057     */
058    abstract public class AbstractSkeleton {
059      private Class _apiClass;
060      private Class _homeClass;
061      private Class _objectClass;
062      
063      private HashMap _methodMap = new HashMap();
064    
065      /**
066       * Create a new hessian skeleton.
067       *
068       * @param apiClass the API interface
069       */
070      protected AbstractSkeleton(Class apiClass)
071      {
072        _apiClass = apiClass;
073        
074        Method []methodList = apiClass.getMethods();
075    
076        for (int i = 0; i < methodList.length; i++) {
077          Method method = methodList[i];
078    
079          if (_methodMap.get(method.getName()) == null)
080            _methodMap.put(method.getName(), methodList[i]);
081    
082          Class []param = method.getParameterTypes();
083          String mangledName = method.getName() + "__" + param.length;
084          _methodMap.put(mangledName, methodList[i]);
085          
086          _methodMap.put(mangleName(method, false), methodList[i]);
087        }
088      }
089    
090      /**
091       * Returns the API class of the current object.
092       */
093      public String getAPIClassName()
094      {
095        return _apiClass.getName();
096      }
097    
098      /**
099       * Returns the API class of the factory/home.
100       */
101      public String getHomeClassName()
102      {
103        if (_homeClass != null)
104          return _homeClass.getName();
105        else
106          return getAPIClassName();
107      }
108    
109      /**
110       * Sets the home API class.
111       */
112      public void setHomeClass(Class homeAPI)
113      {
114        _homeClass = homeAPI;
115      }
116    
117      /**
118       * Returns the API class of the object URLs
119       */
120      public String getObjectClassName()
121      {
122        if (_objectClass != null)
123          return _objectClass.getName();
124        else
125          return getAPIClassName();
126      }
127    
128      /**
129       * Sets the object API class.
130       */
131      public void setObjectClass(Class objectAPI)
132      {
133        _objectClass = objectAPI;
134      }
135    
136      /**
137       * Returns the method by the mangled name.
138       *
139       * @param mangledName the name passed by the protocol
140       */
141      protected Method getMethod(String mangledName)
142      {
143        return (Method) _methodMap.get(mangledName);
144      }
145    
146      /**
147       * Creates a unique mangled method name based on the method name and
148       * the method parameters.
149       *
150       * @param method the method to mangle
151       * @param isFull if true, mangle the full classname
152       *
153       * @return a mangled string.
154       */
155      public static String mangleName(Method method, boolean isFull)
156      {
157        StringBuffer sb = new StringBuffer();
158        
159        sb.append(method.getName());
160        
161        Class []params = method.getParameterTypes();
162        for (int i = 0; i < params.length; i++) {
163          sb.append('_');
164          sb.append(mangleClass(params[i], isFull));
165        }
166    
167        return sb.toString();
168      }
169    
170      /**
171       * Mangles a classname.
172       */
173      public static String mangleClass(Class cl, boolean isFull)
174      {
175        String name = cl.getName();
176    
177        if (name.equals("boolean") || name.equals("java.lang.Boolean"))
178          return "boolean";
179        else if (name.equals("int") || name.equals("java.lang.Integer")
180                 || name.equals("short") || name.equals("java.lang.Short")
181                 || name.equals("byte") || name.equals("java.lang.Byte"))
182          return "int";
183        else if (name.equals("long") || name.equals("java.lang.Long"))
184          return "long";
185        else if (name.equals("float") || name.equals("java.lang.Float")
186                 || name.equals("double") || name.equals("java.lang.Double"))
187          return "double";
188        else if (name.equals("java.lang.String")
189                 || name.equals("com.caucho.util.CharBuffer")
190                 || name.equals("char") || name.equals("java.lang.Character")
191                 || name.equals("java.io.Reader"))
192          return "string";
193        else if (name.equals("java.util.Date")
194                 || name.equals("com.caucho.util.QDate"))
195          return "date";
196        else if (InputStream.class.isAssignableFrom(cl)
197                 || name.equals("[B"))
198          return "binary";
199        else if (cl.isArray()) {
200          return "[" + mangleClass(cl.getComponentType(), isFull);
201        }
202        else if (name.equals("org.w3c.dom.Node")
203                 || name.equals("org.w3c.dom.Element")
204                 || name.equals("org.w3c.dom.Document"))
205          return "xml";
206        else if (isFull)
207          return name;
208        else {
209          int p = name.lastIndexOf('.');
210          if (p > 0)
211            return name.substring(p + 1);
212          else
213            return name;
214        }
215      }
216    
217      public String toString()
218      {
219        return getClass().getSimpleName() + "[" + _apiClass.getName() + "]";
220      }
221    }