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.ClassLoaderUtil;
030 import com.liferay.portal.kernel.util.StringUtil;
031 import com.liferay.portal.kernel.util.ThreadLocalDistributor;
032 import com.liferay.portal.kernel.util.ThreadLocalDistributorRegistry;
033 import com.liferay.portal.kernel.util.WebKeys;
034 import com.liferay.portal.model.Portlet;
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<>();
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<>();
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<>();
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 = new HashMap<>();
152
153 HttpSession session = request.getSession();
154
155 Enumeration<String> enumeration = session.getAttributeNames();
156
157 while (enumeration.hasMoreElements()) {
158 String name = enumeration.nextElement();
159
160 if (name.startsWith(WebKeys.PORTLET_SESSION_ATTRIBUTES) &&
161 !name.equals(portletSessionAttributesKey)) {
162
163 continue;
164 }
165
166 Object value = session.getAttribute(name);
167
168 if (value instanceof Serializable) {
169 sessionAttributes.put(name, (Serializable)value);
170 }
171 else if (_log.isWarnEnabled()) {
172 _log.warn(
173 "Nonserializable session attribute name " + name +
174 " with value " + value);
175 }
176 }
177
178 HttpSession portletSession = (HttpSession)request.getAttribute(
179 WebKeys.PORTLET_SESSION);
180
181 if (portletSession != null) {
182 request.removeAttribute(WebKeys.PORTLET_SESSION);
183
184 HashMap<String, Serializable> portletSessionAttributes =
185 new HashMap<>();
186
187 enumeration = portletSession.getAttributeNames();
188
189 while (enumeration.hasMoreElements()) {
190 String name = enumeration.nextElement();
191 Object value = portletSession.getAttribute(name);
192
193 if (value instanceof Serializable) {
194 portletSessionAttributes.put(name, (Serializable)value);
195 }
196 else if (_log.isWarnEnabled()) {
197 _log.warn(
198 "Nonserializable session attribute name " + name +
199 " with value " + value);
200 }
201 }
202
203 sessionAttributes.put(
204 portletSessionAttributesKey, portletSessionAttributes);
205 }
206
207 return sessionAttributes;
208 }
209
210 public static <T extends SPIAgentSerializable> T readFrom(
211 InputStream inputStream)
212 throws IOException {
213
214 byte[] data = new byte[8];
215 int length = 0;
216
217 while (length < 8) {
218 int count = inputStream.read(data, length, 8 - length);
219
220 if (count < 0) {
221 throw new EOFException();
222 }
223
224 length += count;
225 }
226
227 long receipt = BigEndianCodec.getLong(data, 0);
228
229 ByteBuffer byteBuffer = MailboxUtil.receiveMail(receipt);
230
231 if (byteBuffer == null) {
232 throw new IllegalArgumentException(
233 "No mail with receipt " + receipt);
234 }
235
236 Deserializer deserializer = new Deserializer(byteBuffer);
237
238 ClassLoader contextClassLoader =
239 ClassLoaderUtil.getContextClassLoader();
240
241 try {
242 String servletContextName = deserializer.readString();
243
244 ClassLoader classLoader = ClassLoaderPool.getClassLoader(
245 servletContextName);
246
247 ClassLoaderUtil.setContextClassLoader(classLoader);
248
249 T t = deserializer.readObject();
250
251 t.servletContextName = servletContextName;
252
253 return t;
254 }
255 catch (ClassNotFoundException cnfe) {
256 throw new IOException(cnfe);
257 }
258 finally {
259 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
260 }
261 }
262
263 public SPIAgentSerializable(String servletContextName) {
264 this.servletContextName = servletContextName;
265 }
266
267 public void writeTo(
268 RegistrationReference registrationReference,
269 OutputStream outputStream)
270 throws IOException {
271
272 Serializer serializer = new Serializer();
273
274 serializer.writeString(servletContextName);
275 serializer.writeObject(this);
276
277 try {
278 byte[] data = new byte[8];
279
280 ByteBuffer byteBuffer = serializer.toByteBuffer();
281
282 long receipt = MailboxUtil.sendMail(
283 registrationReference, byteBuffer);
284
285 BigEndianCodec.putLong(data, 0, receipt);
286
287 outputStream.write(data);
288
289 outputStream.flush();
290 }
291 catch (MailboxException me) {
292 throw new IOException(me);
293 }
294 }
295
296 protected void captureThreadLocals() {
297 threadLocalDistributors =
298 ThreadLocalDistributorRegistry.getThreadLocalDistributors();
299
300 for (ThreadLocalDistributor threadLocalDistributor :
301 threadLocalDistributors) {
302
303 threadLocalDistributor.capture();
304 }
305 }
306
307 protected void restoreThreadLocals() {
308 for (ThreadLocalDistributor threadLocalDistributor :
309 threadLocalDistributors) {
310
311 threadLocalDistributor.restore();
312 }
313 }
314
315 protected transient String servletContextName;
316 protected ThreadLocalDistributor[] threadLocalDistributors;
317
318 private static final Log _log = LogFactoryUtil.getLog(
319 SPIAgentSerializable.class);
320
321 }