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