001
014
015 package com.liferay.portal.resiliency.spi.agent;
016
017 import com.liferay.portal.kernel.io.BigEndianCodec;
018 import com.liferay.portal.kernel.io.Deserializer;
019 import com.liferay.portal.kernel.io.Serializer;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.nio.intraband.RegistrationReference;
023 import com.liferay.portal.kernel.nio.intraband.mailbox.MailboxException;
024 import com.liferay.portal.kernel.nio.intraband.mailbox.MailboxUtil;
025 import com.liferay.portal.kernel.resiliency.spi.agent.annotation.Direction;
026 import com.liferay.portal.kernel.resiliency.spi.agent.annotation.DistributedRegistry;
027 import com.liferay.portal.kernel.servlet.HttpHeaders;
028 import com.liferay.portal.kernel.util.ClassLoaderPool;
029 import com.liferay.portal.kernel.util.StringUtil;
030 import com.liferay.portal.kernel.util.ThreadLocalDistributor;
031 import com.liferay.portal.kernel.util.ThreadLocalDistributorRegistry;
032 import com.liferay.portal.model.Portlet;
033 import com.liferay.portal.util.ClassLoaderUtil;
034 import com.liferay.portal.util.WebKeys;
035
036 import java.io.EOFException;
037 import java.io.IOException;
038 import java.io.InputStream;
039 import java.io.OutputStream;
040 import java.io.Serializable;
041
042 import java.nio.ByteBuffer;
043
044 import java.util.ArrayList;
045 import java.util.Collections;
046 import java.util.Enumeration;
047 import java.util.HashMap;
048 import java.util.List;
049 import java.util.Map;
050
051 import javax.servlet.http.HttpServletRequest;
052 import javax.servlet.http.HttpSession;
053
054
057 public class SPIAgentSerializable implements Serializable {
058
059 public static Map<String, Serializable> extractDistributedRequestAttributes(
060 HttpServletRequest request, Direction direction) {
061
062 Map<String, Serializable> distributedRequestAttributes =
063 new HashMap<String, Serializable>();
064
065 Enumeration<String> enumeration = request.getAttributeNames();
066
067 while (enumeration.hasMoreElements()) {
068 String name = enumeration.nextElement();
069
070 if (DistributedRegistry.isDistributed(name, direction)) {
071 Object value = request.getAttribute(name);
072
073 if (value instanceof Serializable) {
074 distributedRequestAttributes.put(name, (Serializable)value);
075 }
076 else if (_log.isWarnEnabled()) {
077 _log.warn(
078 "Nonserializable distributed request attribute name " +
079 name + " with value " + value);
080 }
081 }
082 else if (_log.isDebugEnabled()) {
083 _log.debug(
084 "Nondistributed request attribute name " + name +
085 " with direction " + direction + " and value " +
086 request.getAttribute(name));
087 }
088 }
089
090 return distributedRequestAttributes;
091 }
092
093 public static Map<String, List<String>> extractRequestHeaders(
094 HttpServletRequest request) {
095
096 Map<String, List<String>> headers = new HashMap<String, List<String>>();
097
098 Enumeration<String> nameEnumeration = request.getHeaderNames();
099
100 while (nameEnumeration.hasMoreElements()) {
101 String headerName = nameEnumeration.nextElement();
102
103
104
105 if (StringUtil.equalsIgnoreCase(
106 HttpHeaders.ACCEPT_ENCODING, headerName)) {
107
108 continue;
109 }
110
111
112
113 if (StringUtil.equalsIgnoreCase(HttpHeaders.COOKIE, headerName)) {
114 continue;
115 }
116
117 Enumeration<String> valueEnumeration = request.getHeaders(
118 headerName);
119
120 if (valueEnumeration != null) {
121 List<String> values = new ArrayList<String>();
122
123 while (valueEnumeration.hasMoreElements()) {
124 values.add(valueEnumeration.nextElement());
125 }
126
127 if (values.isEmpty()) {
128 values = Collections.emptyList();
129 }
130
131 headers.put(StringUtil.toLowerCase(headerName), values);
132 }
133 }
134
135 if (headers.isEmpty()) {
136 headers = Collections.emptyMap();
137 }
138
139 return headers;
140 }
141
142 public static Map<String, Serializable> extractSessionAttributes(
143 HttpServletRequest request) {
144
145 Portlet portlet = (Portlet)request.getAttribute(
146 WebKeys.SPI_AGENT_PORTLET);
147
148 String portletSessionAttributesKey =
149 WebKeys.PORTLET_SESSION_ATTRIBUTES.concat(portlet.getContextName());
150
151 Map<String, Serializable> sessionAttributes =
152 new HashMap<String, Serializable>();
153
154 HttpSession session = request.getSession();
155
156 Enumeration<String> enumeration = session.getAttributeNames();
157
158 while (enumeration.hasMoreElements()) {
159 String name = enumeration.nextElement();
160
161 if (name.startsWith(WebKeys.PORTLET_SESSION_ATTRIBUTES) &&
162 !name.equals(portletSessionAttributesKey)) {
163
164 continue;
165 }
166
167 Object value = session.getAttribute(name);
168
169 if (value instanceof Serializable) {
170 sessionAttributes.put(name, (Serializable)value);
171 }
172 else if (_log.isWarnEnabled()) {
173 _log.warn(
174 "Nonserializable session attribute name " + name +
175 " with value " + value);
176 }
177 }
178
179 HttpSession portletSession = (HttpSession)request.getAttribute(
180 WebKeys.PORTLET_SESSION);
181
182 if (portletSession != null) {
183 request.removeAttribute(WebKeys.PORTLET_SESSION);
184
185 HashMap<String, Serializable> portletSessionAttributes =
186 new HashMap<String, Serializable>();
187
188 enumeration = portletSession.getAttributeNames();
189
190 while (enumeration.hasMoreElements()) {
191 String name = enumeration.nextElement();
192 Object value = portletSession.getAttribute(name);
193
194 if (value instanceof Serializable) {
195 portletSessionAttributes.put(name, (Serializable)value);
196 }
197 else if (_log.isWarnEnabled()) {
198 _log.warn(
199 "Nonserializable session attribute name " + name +
200 " with value " + value);
201 }
202 }
203
204 sessionAttributes.put(
205 portletSessionAttributesKey, portletSessionAttributes);
206 }
207
208 return sessionAttributes;
209 }
210
211 public static <T extends SPIAgentSerializable> T readFrom(
212 InputStream inputStream)
213 throws IOException {
214
215 byte[] data = new byte[8];
216 int length = 0;
217
218 while (length < 8) {
219 int count = inputStream.read(data, length, 8 - length);
220
221 if (count < 0) {
222 throw new EOFException();
223 }
224
225 length += count;
226 }
227
228 long receipt = BigEndianCodec.getLong(data, 0);
229
230 ByteBuffer byteBuffer = MailboxUtil.receiveMail(receipt);
231
232 if (byteBuffer == null) {
233 throw new IllegalArgumentException(
234 "No mail with receipt " + receipt);
235 }
236
237 Deserializer deserializer = new Deserializer(byteBuffer);
238
239 ClassLoader contextClassLoader =
240 ClassLoaderUtil.getContextClassLoader();
241
242 try {
243 String servletContextName = deserializer.readString();
244
245 ClassLoader classLoader = ClassLoaderPool.getClassLoader(
246 servletContextName);
247
248 ClassLoaderUtil.setContextClassLoader(classLoader);
249
250 T t = deserializer.readObject();
251
252 t.servletContextName = servletContextName;
253
254 return t;
255 }
256 catch (ClassNotFoundException cnfe) {
257 throw new IOException(cnfe);
258 }
259 finally {
260 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
261 }
262 }
263
264 public SPIAgentSerializable(String servletContextName) {
265 this.servletContextName = servletContextName;
266 }
267
268 public void writeTo(
269 RegistrationReference registrationReference,
270 OutputStream outputStream)
271 throws IOException {
272
273 Serializer serializer = new Serializer();
274
275 serializer.writeString(servletContextName);
276 serializer.writeObject(this);
277
278 try {
279 byte[] data = new byte[8];
280
281 ByteBuffer byteBuffer = serializer.toByteBuffer();
282
283 long receipt = MailboxUtil.sendMail(
284 registrationReference, byteBuffer);
285
286 BigEndianCodec.putLong(data, 0, receipt);
287
288 outputStream.write(data);
289
290 outputStream.flush();
291 }
292 catch (MailboxException me) {
293 throw new IOException(me);
294 }
295 }
296
297 protected void captureThreadLocals() {
298 threadLocalDistributors =
299 ThreadLocalDistributorRegistry.getThreadLocalDistributors();
300
301 for (ThreadLocalDistributor threadLocalDistributor :
302 threadLocalDistributors) {
303
304 threadLocalDistributor.capture();
305 }
306 }
307
308 protected void restoreThreadLocals() {
309 for (ThreadLocalDistributor threadLocalDistributor :
310 threadLocalDistributors) {
311
312 threadLocalDistributor.restore();
313 }
314 }
315
316 protected transient String servletContextName;
317 protected ThreadLocalDistributor[] threadLocalDistributors;
318
319 private static Log _log = LogFactoryUtil.getLog(SPIAgentSerializable.class);
320
321 }