| /*
|
| * Copyright 1999-2011 Alibaba Group.
|
| *
|
| * Licensed under the Apache License, Version 2.0 (the "License");
|
| * you may not use this file except in compliance with the License.
|
| * You may obtain a copy of the License at
|
| *
|
| * http://www.apache.org/licenses/LICENSE-2.0
|
| *
|
| * Unless required by applicable law or agreed to in writing, software
|
| * distributed under the License is distributed on an "AS IS" BASIS,
|
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| * See the License for the specific language governing permissions and
|
| * limitations under the License.
|
| */
|
| package com.alibaba.dubbo.rpc.protocol.hessian; |
| |
| import java.io.IOException;
|
| import java.net.SocketTimeoutException;
|
| import java.util.ArrayList;
|
| import java.util.Map;
|
| import java.util.concurrent.ConcurrentHashMap;
|
|
|
| import javax.servlet.ServletException;
|
| import javax.servlet.http.HttpServletRequest;
|
| import javax.servlet.http.HttpServletResponse;
|
|
|
| import com.alibaba.dubbo.common.Constants;
|
| import com.alibaba.dubbo.common.URL;
|
| import com.alibaba.dubbo.remoting.http.HttpBinder;
|
| import com.alibaba.dubbo.remoting.http.HttpHandler;
|
| import com.alibaba.dubbo.remoting.http.HttpServer;
|
| import com.alibaba.dubbo.rpc.RpcContext;
|
| import com.alibaba.dubbo.rpc.RpcException;
|
| import com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol;
|
| import com.caucho.hessian.HessianException;
|
| import com.caucho.hessian.client.HessianConnectionException;
|
| import com.caucho.hessian.client.HessianProxyFactory;
|
| import com.caucho.hessian.io.HessianMethodSerializationException;
|
| import com.caucho.hessian.server.HessianSkeleton;
|
| |
| /** |
| * http rpc support. |
| * |
| * @author qianlei |
| */ |
| public class HessianProtocol extends AbstractProxyProtocol { |
| |
| private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<String, HttpServer>(); |
|
|
| private final Map<String, HessianSkeleton> skeletonMap = new ConcurrentHashMap<String, HessianSkeleton>();
|
| |
| private HttpBinder httpBinder;
|
|
|
| public HessianProtocol() {
|
| super(HessianException.class);
|
| } |
|
|
| public void setHttpBinder(HttpBinder httpBinder) {
|
| this.httpBinder = httpBinder;
|
| }
|
| |
| public int getDefaultPort() { |
| return 80; |
| }
|
|
|
| private class HessianHandler implements HttpHandler {
|
|
|
| public void handle(HttpServletRequest request, HttpServletResponse response)
|
| throws IOException, ServletException {
|
| String uri = request.getRequestURI();
|
| HessianSkeleton skeleton = skeletonMap.get(uri);
|
| if (! request.getMethod().equalsIgnoreCase("POST")) {
|
| response.setStatus(500);
|
| } else {
|
| RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort());
|
| try {
|
| skeleton.invoke(request.getInputStream(), response.getOutputStream());
|
| } catch (Throwable e) {
|
| throw new ServletException(e);
|
| }
|
| }
|
| }
|
|
|
| } |
| |
| protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException { |
| String addr = url.getIp() + ":" + url.getPort(); |
| HttpServer server = serverMap.get(addr); |
| if (server == null) { |
| server = httpBinder.bind(url, new HessianHandler()); |
| serverMap.put(addr, server); |
| }
|
| final String path = url.getAbsolutePath();
|
| HessianSkeleton skeleton = new HessianSkeleton(impl, type);
|
| skeletonMap.put(path, skeleton); |
| return new Runnable() { |
| public void run() {
|
| skeletonMap.remove(path); |
| } |
| }; |
| } |
|
|
| @SuppressWarnings("unchecked")
|
| protected <T> T doRefer(Class<T> serviceType, URL url) throws RpcException {
|
| HessianProxyFactory hessianProxyFactory = new HessianProxyFactory();
|
| String client = url.getParameter(Constants.CLIENT_KEY, Constants.DEFAULT_HTTP_CLIENT);
|
| if ("httpclient".equals(client)) {
|
| hessianProxyFactory.setConnectionFactory(new HttpClientConnectionFactory());
|
| } else if (client != null && client.length() > 0 && ! Constants.DEFAULT_HTTP_CLIENT.equals(client)) {
|
| throw new IllegalStateException("Unsupported http protocol client=\"" + client + "\"!");
|
| }
|
| int timeout = url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
|
| hessianProxyFactory.setConnectTimeout(timeout);
|
| hessianProxyFactory.setReadTimeout(timeout); |
| return (T) hessianProxyFactory.create(serviceType, url.setProtocol("http").toJavaURL(), Thread.currentThread().getContextClassLoader()); |
| } |
|
|
| protected int getErrorCode(Throwable e) {
|
| if (e instanceof HessianConnectionException) {
|
| if (e.getCause() != null) {
|
| Class<?> cls = e.getCause().getClass();
|
| if (SocketTimeoutException.class.equals(cls)) {
|
| return RpcException.TIMEOUT_EXCEPTION;
|
| }
|
| }
|
| return RpcException.NETWORK_EXCEPTION;
|
| } else if (e instanceof HessianMethodSerializationException) {
|
| return RpcException.SERIALIZATION_EXCEPTION;
|
| }
|
| return super.getErrorCode(e);
|
| }
|
| |
| public void destroy() { |
| super.destroy(); |
| for (String key : new ArrayList<String>(serverMap.keySet())) { |
| HttpServer server = serverMap.remove(key); |
| if (server != null) { |
| try { |
| if (logger.isInfoEnabled()) { |
| logger.info("Close hessian server " + server.getUrl()); |
| } |
| server.close(); |
| } catch (Throwable t) { |
| logger.warn(t.getMessage(), t); |
| } |
| } |
| } |
| } |
| |
| } |