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