001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.StringUtil;
029    import com.liferay.portal.kernel.util.ThreadLocalDistributor;
030    import com.liferay.portal.kernel.util.ThreadLocalDistributorRegistry;
031    
032    import java.io.EOFException;
033    import java.io.IOException;
034    import java.io.InputStream;
035    import java.io.OutputStream;
036    import java.io.Serializable;
037    
038    import java.nio.ByteBuffer;
039    
040    import java.util.ArrayList;
041    import java.util.Collections;
042    import java.util.Enumeration;
043    import java.util.HashMap;
044    import java.util.List;
045    import java.util.Map;
046    
047    import javax.servlet.http.HttpServletRequest;
048    import javax.servlet.http.HttpSession;
049    
050    /**
051     * @author Shuyang Zhou
052     */
053    public class SPIAgentSerializable implements Serializable {
054    
055            public static Map<String, Serializable> extractDistributedRequestAttributes(
056                    HttpServletRequest request, Direction direction) {
057    
058                    Map<String, Serializable> distributedRequestAttributes =
059                            new HashMap<String, Serializable>();
060    
061                    Enumeration<String> enumeration = request.getAttributeNames();
062    
063                    while (enumeration.hasMoreElements()) {
064                            String name = enumeration.nextElement();
065    
066                            if (DistributedRegistry.isDistributed(name, direction)) {
067                                    Object value = request.getAttribute(name);
068    
069                                    if (value instanceof Serializable) {
070                                            distributedRequestAttributes.put(name, (Serializable)value);
071                                    }
072                                    else if (_log.isWarnEnabled()) {
073                                            _log.warn(
074                                                    "Nonserializable distributed request attribute name " +
075                                                            name + " with value " + value);
076                                    }
077                            }
078                            else if (_log.isDebugEnabled()) {
079                                    _log.debug(
080                                            "Nondistributed request attribute name " + name +
081                                                    " with direction " + direction + " and value " +
082                                                            request.getAttribute(name));
083                            }
084                    }
085    
086                    return distributedRequestAttributes;
087            }
088    
089            public static Map<String, List<String>> extractRequestHeaders(
090                    HttpServletRequest request) {
091    
092                    Map<String, List<String>> headers = new HashMap<String, List<String>>();
093    
094                    Enumeration<String> nameEnumeration = request.getHeaderNames();
095    
096                    while (nameEnumeration.hasMoreElements()) {
097                            String headerName = nameEnumeration.nextElement();
098    
099                            // Remove Accept-Encoding header, to prevent content modification
100    
101                            if (StringUtil.equalsIgnoreCase(
102                                            HttpHeaders.ACCEPT_ENCODING, headerName)) {
103    
104                                    continue;
105                            }
106    
107                            // Directly passing around cookie
108    
109                            if (StringUtil.equalsIgnoreCase(HttpHeaders.COOKIE, headerName)) {
110                                    continue;
111                            }
112    
113                            Enumeration<String> valueEnumeration = request.getHeaders(
114                                    headerName);
115    
116                            if (valueEnumeration != null) {
117                                    List<String> values = new ArrayList<String>();
118    
119                                    while (valueEnumeration.hasMoreElements()) {
120                                            values.add(valueEnumeration.nextElement());
121                                    }
122    
123                                    if (values.isEmpty()) {
124                                            values = Collections.emptyList();
125                                    }
126    
127                                    headers.put(StringUtil.toLowerCase(headerName), values);
128                            }
129                    }
130    
131                    if (headers.isEmpty()) {
132                            headers = Collections.emptyMap();
133                    }
134    
135                    return headers;
136            }
137    
138            public static Map<String, Serializable> extractSessionAttributes(
139                    HttpSession session) {
140    
141                    Map<String, Serializable> sessionAttributes =
142                            new HashMap<String, Serializable>();
143    
144                    Enumeration<String> enumeration = session.getAttributeNames();
145    
146                    while (enumeration.hasMoreElements()) {
147                            String name = enumeration.nextElement();
148                            Object value = session.getAttribute(name);
149    
150                            if (value instanceof Serializable) {
151                                    sessionAttributes.put(name, (Serializable)value);
152                            }
153                            else if (_log.isWarnEnabled()) {
154                                    _log.warn(
155                                            "Nonserializable session attribute name " + name +
156                                                    " with value " + value);
157                            }
158                    }
159    
160                    return sessionAttributes;
161            }
162    
163            public static <T extends SPIAgentSerializable> T readFrom(
164                            InputStream inputStream)
165                    throws IOException {
166    
167                    byte[] data = new byte[8];
168                    int length = 0;
169    
170                    while (length < 8) {
171                            int count = inputStream.read(data, length, 8 - length);
172    
173                            if (count < 0) {
174                                    throw new EOFException();
175                            }
176    
177                            length += count;
178                    }
179    
180                    long receipt = BigEndianCodec.getLong(data, 0);
181    
182                    ByteBuffer byteBuffer = MailboxUtil.receiveMail(receipt);
183    
184                    if (byteBuffer == null) {
185                            throw new IllegalArgumentException(
186                                    "No mail with receipt " + receipt);
187                    }
188    
189                    Deserializer deserializer = new Deserializer(byteBuffer);
190    
191                    try {
192                            return deserializer.readObject();
193                    }
194                    catch (ClassNotFoundException cnfe) {
195                            throw new IOException(cnfe);
196                    }
197            }
198    
199            public void writeTo(
200                            RegistrationReference registrationReference,
201                            OutputStream outputStream)
202                    throws IOException {
203    
204                    Serializer serializer = new Serializer();
205    
206                    serializer.writeObject(this);
207    
208                    try {
209                            byte[] data = new byte[8];
210    
211                            ByteBuffer byteBuffer = serializer.toByteBuffer();
212    
213                            long receipt = MailboxUtil.sendMail(
214                                    registrationReference, byteBuffer);
215    
216                            BigEndianCodec.putLong(data, 0, receipt);
217    
218                            outputStream.write(data);
219    
220                            outputStream.flush();
221                    }
222                    catch (MailboxException me) {
223                            throw new IOException(me);
224                    }
225            }
226    
227            protected void captureThreadLocals() {
228                    threadLocalDistributors =
229                            ThreadLocalDistributorRegistry.getThreadLocalDistributors();
230    
231                    for (ThreadLocalDistributor threadLocalDistributor :
232                                    threadLocalDistributors) {
233    
234                            threadLocalDistributor.capture();
235                    }
236            }
237    
238            protected void restoreThreadLocals() {
239                    for (ThreadLocalDistributor threadLocalDistributor :
240                                    threadLocalDistributors) {
241    
242                            threadLocalDistributor.restore();
243                    }
244            }
245    
246            protected ThreadLocalDistributor[] threadLocalDistributors;
247    
248            private static Log _log = LogFactoryUtil.getLog(SPIAgentSerializable.class);
249    
250    }