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