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",
191                                    "\n",
192                                    "  ",
193                                    "> <",
194                                    _INCORRECT_LONG_ARRAY,
195                                    _INCORRECT_STRING_ARRAY
196                            },
197                            new String[] {
198                                    StringPool.BLANK,
199                                    StringPool.BLANK,
200                                    StringPool.BLANK,
201                                    "><",
202                                    _CORRECT_LONG_ARRAY,
203                                    _CORRECT_STRING_ARRAY
204                            });
205    
206                    Document document = SAXReaderUtil.read(xml);
207    
208                    return document.formattedString();
209            }
210    
211            private static final String _CORRECT_LONG_ARRAY =
212                    "<complexType name=\"ArrayOf_xsd_long\"><complexContent>" +
213                            "<restriction base=\"soapenc:Array\"><attribute ref=\"soapenc:" +
214                                    "arrayType\" wsdl:arrayType=\"soapenc:long[]\"/>" +
215                                            "</restriction></complexContent></complexType>";
216    
217            private static final String _CORRECT_STRING_ARRAY =
218                    "<complexType name=\"ArrayOf_xsd_string\"><complexContent>" +
219                            "<restriction base=\"soapenc:Array\"><attribute ref=\"soapenc:" +
220                                    "arrayType\" wsdl:arrayType=\"soapenc:string[]\"/>" +
221                                            "</restriction></complexContent></complexType>";
222    
223            private static final String _HTML_BOTTOM_WRAPPER = "</body></html>";
224    
225            private static final String _HTML_TOP_WRAPPER = "<html><body>";
226    
227            private static final String _INCORRECT_LONG_ARRAY =
228                    "<complexType name=\"ArrayOf_xsd_long\"><simpleContent><extension/>" +
229                            "</simpleContent></complexType>";
230    
231            private static final String _INCORRECT_STRING_ARRAY =
232                    "<complexType name=\"ArrayOf_xsd_string\"><simpleContent><extension/>" +
233                            "</simpleContent></complexType>";
234    
235            private static Log _log = LogFactoryUtil.getLog(AxisServlet.class);
236    
237            private static Field _cacheField;
238    
239            private boolean _fixContent;
240            private boolean _ready;
241            private ServletConfig _servletConfig;
242    
243            private class DestroyThread extends Thread {
244    
245                    public DestroyThread() {
246                            setDaemon(true);
247                    }
248    
249                    public Exception getException() {
250                            return _exception;
251                    }
252    
253                    @Override
254                    public void run() {
255                            try {
256                                    doDestroy();
257                            }
258                            catch (Exception e) {
259                                    _exception = e;
260                            }
261                    }
262    
263                    private Exception _exception;
264    
265            }
266    
267            private class InitThread extends Thread {
268    
269                    public InitThread() {
270                            setDaemon(true);
271                    }
272    
273                    public Exception getException() {
274                            return _exception;
275                    }
276    
277                    @Override
278                    public void run() {
279                            try {
280                                    doInit();
281                            }
282                            catch (Exception e) {
283                                    _exception = e;
284                            }
285                    }
286    
287                    private Exception _exception;
288    
289            }
290    
291            static {
292                    try {
293                            _cacheField = ReflectionUtil.getDeclaredField(
294                                    MethodCache.class, "cache");
295                    }
296                    catch (Exception e) {
297                            _log.error(e, e);
298                    }
299            }
300    
301    }