001    /**
002     * Copyright (c) 2000-2012 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.util.axis;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
020    import com.liferay.portal.kernel.servlet.StringServletResponse;
021    import com.liferay.portal.kernel.servlet.UncommittedServletResponse;
022    import com.liferay.portal.kernel.util.ContentTypes;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.ReflectionUtil;
025    import com.liferay.portal.kernel.util.ServerDetector;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.util.StringUtil;
028    import com.liferay.portal.kernel.xml.Document;
029    import com.liferay.portal.kernel.xml.SAXReaderUtil;
030    
031    import java.io.IOException;
032    
033    import java.lang.reflect.Field;
034    
035    import javax.servlet.ServletConfig;
036    import javax.servlet.ServletException;
037    import javax.servlet.http.HttpServletRequest;
038    import javax.servlet.http.HttpServletResponse;
039    
040    import org.apache.axis.utils.cache.MethodCache;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     */
045    public class AxisServlet extends org.apache.axis.transport.http.AxisServlet {
046    
047            @Override
048            public void destroy() {
049                    if (ServerDetector.isWebLogic()) {
050                            doDestroy();
051                    }
052                    else {
053                            DestroyThread destroyThread = new DestroyThread();
054    
055                            destroyThread.start();
056    
057                            try {
058                                    destroyThread.join();
059                            }
060                            catch (InterruptedException ie) {
061                                    throw new RuntimeException(ie);
062                            }
063    
064                            Exception e = destroyThread.getException();
065    
066                            if (e != null) {
067                                    if (e instanceof RuntimeException) {
068                                            throw (RuntimeException)e;
069                                    }
070                                    else {
071                                            throw new RuntimeException(e);
072                                    }
073                            }
074                    }
075            }
076    
077            @Override
078            public void init(ServletConfig servletConfig) throws ServletException {
079                    _servletConfig = servletConfig;
080    
081                    if (ServerDetector.isResin() || ServerDetector.isWebLogic()) {
082                            doInit();
083                    }
084                    else {
085                            InitThread initThread = new InitThread();
086    
087                            initThread.start();
088    
089                            try {
090                                    initThread.join();
091                            }
092                            catch (InterruptedException ie) {
093                                    throw new ServletException(ie);
094                            }
095    
096                            Exception e = initThread.getException();
097    
098                            if (e != null) {
099                                    if (e instanceof ServletException) {
100                                            throw (ServletException)e;
101                                    }
102                                    else {
103                                            throw new ServletException(e);
104                                    }
105                            }
106                    }
107            }
108    
109            @Override
110            public void service(
111                            HttpServletRequest request, HttpServletResponse response)
112                    throws IOException, ServletException {
113    
114                    try {
115                            if (!_ready) {
116                                    return;
117                            }
118    
119                            StringServletResponse stringResponse = new StringServletResponse(
120                                    response);
121    
122                            super.service(request, stringResponse);
123    
124                            String contentType = stringResponse.getContentType();
125    
126                            response.setContentType(contentType);
127    
128                            String content = stringResponse.getString();
129    
130                            if (_fixContent) {
131                                    if (contentType.contains(ContentTypes.TEXT_HTML)) {
132                                            content = _HTML_TOP_WRAPPER.concat(content).concat(
133                                                    _HTML_BOTTOM_WRAPPER);
134                                    }
135                                    else if (contentType.contains(ContentTypes.TEXT_XML)) {
136                                            content = fixXml(content);
137                                    }
138                            }
139    
140                            ServletResponseUtil.write(
141                                    new UncommittedServletResponse(response),
142                                    content.getBytes(StringPool.UTF8));
143                    }
144                    catch (IOException ioe) {
145                            throw ioe;
146                    }
147                    catch (ServletException se) {
148                            throw se;
149                    }
150                    catch (Exception e) {
151                            throw new ServletException(e);
152                    }
153                    finally {
154                            try {
155                                    ThreadLocal<?> cache = (ThreadLocal<?>)_cacheField.get(null);
156    
157                                    if (cache != null) {
158                                            cache.remove();
159                                    }
160                            }
161                            catch (Exception e) {
162                                    _log.error(e, e);
163                            }
164                    }
165            }
166    
167            protected void doDestroy() {
168                    _ready = false;
169    
170                    super.destroy();
171            }
172    
173            protected void doInit() throws ServletException {
174                    super.init(_servletConfig);
175    
176                    _fixContent = GetterUtil.getBoolean(
177                            _servletConfig.getInitParameter("fix-content"), true);
178    
179                    _ready = true;
180            }
181    
182            protected String fixXml(String xml) throws Exception {
183                    if (xml.indexOf("<wsdl:definitions") == -1) {
184                            return xml;
185                    }
186    
187                    xml = StringUtil.replace(
188                            xml,
189                            new String[] {
190                                    "\r\n", "\n", "  ", "> <", _INCORRECT_LONG_ARRAY,
191                                    _INCORRECT_STRING_ARRAY
192                            },
193                            new String[] {
194                                    StringPool.BLANK, StringPool.BLANK, StringPool.BLANK, "><",
195                                    _CORRECT_LONG_ARRAY, _CORRECT_STRING_ARRAY
196                            });
197    
198                    Document document = SAXReaderUtil.read(xml);
199    
200                    return document.formattedString();
201            }
202    
203            private static final String _CORRECT_LONG_ARRAY =
204                    "<complexType name=\"ArrayOf_xsd_long\"><complexContent>" +
205                            "<restriction base=\"soapenc:Array\"><attribute ref=\"soapenc:" +
206                                    "arrayType\" wsdl:arrayType=\"soapenc:long[]\"/>" +
207                                            "</restriction></complexContent></complexType>";
208    
209            private static final String _CORRECT_STRING_ARRAY =
210                    "<complexType name=\"ArrayOf_xsd_string\"><complexContent>" +
211                            "<restriction base=\"soapenc:Array\"><attribute ref=\"soapenc:" +
212                                    "arrayType\" wsdl:arrayType=\"soapenc:string[]\"/>" +
213                                            "</restriction></complexContent></complexType>";
214    
215            private static final String _HTML_BOTTOM_WRAPPER = "</body></html>";
216    
217            private static final String _HTML_TOP_WRAPPER = "<html><body>";
218    
219            private static final String _INCORRECT_LONG_ARRAY =
220                    "<complexType name=\"ArrayOf_xsd_long\"><simpleContent><extension/>" +
221                            "</simpleContent></complexType>";
222    
223            private static final String _INCORRECT_STRING_ARRAY =
224                    "<complexType name=\"ArrayOf_xsd_string\"><simpleContent><extension/>" +
225                            "</simpleContent></complexType>";
226    
227            private static Log _log = LogFactoryUtil.getLog(AxisServlet.class);
228    
229            private static Field _cacheField;
230    
231            private boolean _fixContent;
232            private boolean _ready;
233            private ServletConfig _servletConfig;
234    
235            private class DestroyThread extends Thread {
236    
237                    public DestroyThread() {
238                            setDaemon(true);
239                    }
240    
241                    public Exception getException() {
242                            return _exception;
243                    }
244    
245                    @Override
246                    public void run() {
247                            try {
248                                    doDestroy();
249                            }
250                            catch (Exception e) {
251                                    _exception = e;
252                            }
253                    }
254    
255                    private Exception _exception;
256    
257            }
258    
259            private class InitThread extends Thread {
260    
261                    public InitThread() {
262                            setDaemon(true);
263                    }
264    
265                    public Exception getException() {
266                            return _exception;
267                    }
268    
269                    @Override
270                    public void run() {
271                            try {
272                                    doInit();
273                            }
274                            catch (Exception e) {
275                                    _exception = e;
276                            }
277                    }
278    
279                    private Exception _exception;
280    
281            }
282    
283            static {
284                    try {
285                            _cacheField = ReflectionUtil.getDeclaredField(
286                                    MethodCache.class, "cache");
287                    }
288                    catch (Exception e) {
289                            _log.error(e, e);
290                    }
291            }
292    
293    }