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 "Burlap", "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.burlap.server;
050    
051    import com.caucho.burlap.io.BurlapInput;
052    import com.caucho.burlap.io.BurlapOutput;
053    import com.caucho.services.server.AbstractSkeleton;
054    import com.caucho.services.server.ServiceContext;
055    
056    import java.lang.reflect.InvocationTargetException;
057    import java.lang.reflect.Method;
058    import java.util.logging.*;
059    
060    /**
061     * Proxy class for Burlap services.
062     */
063    public class BurlapSkeleton extends AbstractSkeleton {
064      private static final Logger log
065        = Logger.getLogger(BurlapSkeleton.class.getName());
066      
067      private Object _service;
068      
069      /**
070       * Create a new burlap skeleton.
071       *
072       * @param service the underlying service object.
073       * @param apiClass the API interface
074       */
075      public BurlapSkeleton(Object service, Class apiClass)
076      {
077        super(apiClass);
078    
079        _service = service;
080      }
081      
082      /**
083       * Create a new burlap skeleton.
084       *
085       * @param service the underlying service object.
086       * @param apiClass the API interface
087       */
088      public BurlapSkeleton(Class apiClass)
089      {
090        super(apiClass);
091      }
092    
093      /**
094       * Invoke the object with the request from the input stream.
095       *
096       * @param in the Burlap input stream
097       * @param out the Burlap output stream
098       */
099      public void invoke(BurlapInput in, BurlapOutput out)
100        throws Exception
101      {
102        invoke(_service, in, out);
103      }
104    
105      /**
106       * Invoke the object with the request from the input stream.
107       *
108       * @param in the Burlap input stream
109       * @param out the Burlap output stream
110       */
111      public void invoke(Object service, BurlapInput in, BurlapOutput out)
112        throws Exception
113      {
114        in.readCall();
115    
116        ServiceContext context = ServiceContext.getContext();
117        
118        String header;
119        while ((header = in.readHeader()) != null) {
120          Object value = in.readObject();
121    
122          context.addHeader(header, value);
123        }
124    
125        String methodName = in.readMethod();
126        Method method = getMethod(methodName);
127    
128        if (log.isLoggable(Level.FINE))
129          log.fine(this + " invoking " + methodName + " (" + method + ")");
130    
131        if (method != null) {
132        }
133        else if ("_burlap_getAttribute".equals(in.getMethod())) {
134          String attrName = in.readString();
135          in.completeCall();
136    
137          String value = null;
138    
139          if ("java.api.class".equals(attrName))
140            value = getAPIClassName();
141          else if ("java.home.class".equals(attrName))
142            value = getHomeClassName();
143          else if ("java.object.class".equals(attrName))
144            value = getObjectClassName();
145    
146          out.startReply();
147    
148          out.writeObject(value);
149    
150          out.completeReply();
151          return;
152        }
153        else if (method == null) {
154          out.startReply();
155          out.writeFault("NoSuchMethodException",
156                         "The service has no method named: " + in.getMethod(),
157                         null);
158          out.completeReply();
159          return;
160        }
161    
162        Class []args = method.getParameterTypes();
163        Object []values = new Object[args.length];
164    
165        for (int i = 0; i < args.length; i++)
166          values[i] = in.readObject(args[i]);
167    
168        in.completeCall();
169    
170        Object result = null;
171        
172        try {
173          result = method.invoke(service, values);
174        } catch (Throwable e) {
175          log.log(Level.FINE,
176                  service + "." + method.getName() + "() failed with exception:\n"
177                  + e.toString(),
178                  e);
179          
180          if (e instanceof InvocationTargetException
181              && e.getCause() instanceof Exception)
182            e = ((InvocationTargetException) e).getTargetException();
183          out.startReply();
184          out.writeFault("ServiceException", e.getMessage(), e);
185          out.completeReply();
186          return;
187        }
188    
189        out.startReply();
190    
191        out.writeObject(result);
192        
193        out.completeReply();
194      }
195    }