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