1 | // Copyright 2004-2007 Jean-Francois Poilpret |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package net.sourceforge.hiveremoting.caucho; |
16 | |
17 | import java.io.IOException; |
18 | import java.io.PrintWriter; |
19 | import java.util.HashMap; |
20 | import java.util.Iterator; |
21 | import java.util.List; |
22 | import java.util.Map; |
23 | |
24 | import javax.servlet.GenericServlet; |
25 | import javax.servlet.ServletConfig; |
26 | import javax.servlet.ServletException; |
27 | import javax.servlet.ServletRequest; |
28 | import javax.servlet.ServletResponse; |
29 | import javax.servlet.http.HttpServletRequest; |
30 | import javax.servlet.http.HttpServletResponse; |
31 | |
32 | import org.apache.commons.logging.Log; |
33 | import org.apache.commons.logging.LogFactory; |
34 | import org.apache.hivemind.Registry; |
35 | import org.apache.hivemind.servlet.HiveMindFilter; |
36 | |
37 | import com.caucho.hessian.io.SerializerFactory; |
38 | |
39 | /** |
40 | * Servlet class that "publishes" HiveMind services as remote services, |
41 | * accessible through Caucho Hessian or Burlap protocol. |
42 | * <p> |
43 | * All services to be published must be defined in <code>RemoteServices</code> |
44 | * configuration point. |
45 | * @author Jean-Francois Poilpret |
46 | */ |
47 | public class CauchoRemotingServlet extends GenericServlet |
48 | { |
49 | static private final Log _logger = LogFactory.getLog(CauchoRemotingServlet.class); |
50 | |
51 | @Override public String getServletInfo() |
52 | { |
53 | return "HiveRemoting Caucho Servlet"; |
54 | } |
55 | |
56 | @Override public void init(ServletConfig config) |
57 | throws ServletException |
58 | { |
59 | super.init(config); |
60 | } |
61 | |
62 | //CSOFF: IllegalCatchCheck |
63 | protected void checkInit(HttpServletRequest request) |
64 | { |
65 | if (!_init) |
66 | { |
67 | try |
68 | { |
69 | initServices(request); |
70 | } |
71 | catch (RuntimeException e) |
72 | { |
73 | _logger.fatal("checkInit", e); |
74 | throw e; |
75 | } |
76 | } |
77 | } |
78 | //CSON: IllegalCatchCheck |
79 | |
80 | synchronized protected void initServices(HttpServletRequest request) |
81 | { |
82 | if (!_init) |
83 | { |
84 | // Get HiveMind Registry |
85 | Registry registry = getRegistry(request); |
86 | |
87 | // Initialize special Serialization for Hessian/Burlap |
88 | _factory = (SerializerFactory) registry.getService( |
89 | "hiveremoting.caucho.CauchoSerializerFactory", SerializerFactory.class); |
90 | |
91 | // Initialize Hessian/Burlap services |
92 | List services = registry.getConfiguration("hiveremoting.caucho.RemoteServices"); |
93 | Iterator i = services.iterator(); |
94 | _services = new HashMap<String, RemoteServiceInvoker>(); |
95 | while (i.hasNext()) |
96 | { |
97 | PublishServiceContribution contrib = |
98 | (PublishServiceContribution) i.next(); |
99 | String urlPath = contrib.getUrlPath(); |
100 | if (!urlPath.startsWith("/")) |
101 | { |
102 | urlPath = "/" + urlPath; |
103 | } |
104 | if (contrib.getProtocol() == Protocol.Hessian) |
105 | { |
106 | initHessianService(contrib, urlPath); |
107 | } |
108 | else |
109 | { |
110 | initBurlapService(contrib, urlPath); |
111 | } |
112 | } |
113 | _init = true; |
114 | } |
115 | } |
116 | |
117 | /** |
118 | * Retrieve the HiveMind registry. Uses HiveMindFilter by default. |
119 | * |
120 | * @param request current http request |
121 | * @return the HiveMind registry |
122 | */ |
123 | protected Registry getRegistry(HttpServletRequest request) |
124 | { |
125 | return HiveMindFilter.getRegistry(request); |
126 | } |
127 | |
128 | protected void initHessianService(PublishServiceContribution contrib, String urlPath) |
129 | { |
130 | _services.put( urlPath, |
131 | new HessianRemoteServiceInvoker(contrib, _factory)); |
132 | } |
133 | |
134 | protected void initBurlapService(PublishServiceContribution contrib, String urlPath) |
135 | { |
136 | _services.put( urlPath, |
137 | new BurlapRemoteServiceInvoker(contrib, _factory)); |
138 | } |
139 | |
140 | protected void sendError(HttpServletResponse res, String msg) |
141 | throws IOException, ServletException |
142 | { |
143 | _logger.warn("sendError '" + msg + "'"); |
144 | res.sendError(HttpServletResponse.SC_OK, msg); |
145 | PrintWriter out = res.getWriter(); |
146 | res.setContentType("text/html"); |
147 | out.println("<h1>" + msg + "</h1>"); |
148 | } |
149 | |
150 | @Override public void service(ServletRequest request, ServletResponse response) |
151 | throws IOException, ServletException |
152 | { |
153 | HttpServletRequest req = (HttpServletRequest) request; |
154 | HttpServletResponse res = (HttpServletResponse) response; |
155 | |
156 | if (!req.getMethod().equals("POST")) |
157 | { |
158 | sendError(res, "Hessian/Burlap remoting protocols require POST"); |
159 | return; |
160 | } |
161 | |
162 | // Make sure that the skeletons are initialized |
163 | checkInit(req); |
164 | |
165 | // Find out the service that was called |
166 | String urlPath = req.getPathInfo(); |
167 | // Does it exist? |
168 | RemoteServiceInvoker invoker = _services.get(urlPath); |
169 | if (invoker == null) |
170 | { |
171 | sendError(res, "Service '" + urlPath + "' does not exist"); |
172 | } |
173 | else |
174 | { |
175 | res.setContentType("text/xml"); |
176 | invoker.invoke(req, res); |
177 | } |
178 | } |
179 | |
180 | protected boolean _init = false; |
181 | protected Map<String, RemoteServiceInvoker> _services = null; |
182 | protected SerializerFactory _factory = null; |
183 | } |