/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.util.axis; import com.liferay.portal.kernel.exception.LoggedExceptionInInitializerError; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.servlet.BufferCacheServletResponse; import com.liferay.portal.kernel.servlet.ServletResponseUtil; import com.liferay.portal.kernel.servlet.UncommittedServletResponse; import com.liferay.portal.kernel.util.ContentTypes; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.ReflectionUtil; import com.liferay.portal.kernel.util.ServerDetector; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.xml.Document; import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil; import java.io.IOException; import java.lang.reflect.Field; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.axis.utils.cache.MethodCache; /** * @author Brian Wing Shun Chan */ public class AxisServlet extends org.apache.axis.transport.http.AxisServlet { @Override public void destroy() { if (ServerDetector.isWebLogic()) { doDestroy(); } else { Thread currentThread = Thread.currentThread(); ClassLoader contextClassLoader = currentThread.getContextClassLoader(); Class<?> clazz = getClass(); currentThread.setContextClassLoader(clazz.getClassLoader()); try { DestroyThread destroyThread = new DestroyThread(); destroyThread.start(); try { destroyThread.join(); } catch (InterruptedException ie) { throw new RuntimeException(ie); } Exception e = destroyThread.getException(); if (e != null) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } else { throw new RuntimeException(e); } } } finally { currentThread.setContextClassLoader(contextClassLoader); } } } @Override public void init(ServletConfig servletConfig) throws ServletException { _servletConfig = servletConfig; StringBundler sb = new StringBundler(9); sb.append("<complexType abstract=\"true\" name=\"OrderByComparator\">"); sb.append("<sequence><element name=\"ascending\" "); sb.append("type=\"xsd:boolean\"/><element name=\"orderBy\" "); sb.append("nillable=\"true\" type=\"soapenc:string\"/><element "); sb.append("name=\"orderByConditionFields\" nillable=\"true\" "); sb.append("type=\"impl:ArrayOf_xsd_string\"/><element "); sb.append("name=\"orderByFields\" nillable=\"true\" "); sb.append("type=\"impl:ArrayOf_xsd_string\"/></sequence>"); sb.append("</complexType>"); _correctOrderByComparator = sb.toString(); sb = new StringBundler(5); sb.append("<complexType name=\"ArrayOf_xsd_long\"><complexContent>"); sb.append("<restriction base=\"soapenc:Array\"><attribute "); sb.append("ref=\"soapenc:arrayType\" "); sb.append("wsdl:arrayType=\"soapenc:long[]\"/></restriction>"); sb.append("</complexContent></complexType>"); _correctLongArray = sb.toString(); sb = new StringBundler(5); sb.append("<complexType name=\"ArrayOf_xsd_string\"><complexContent>"); sb.append("<restriction base=\"soapenc:Array\"><attribute "); sb.append("ref=\"soapenc:arrayType\" "); sb.append("wsdl:arrayType=\"soapenc:string[]\"/></restriction>"); sb.append("</complexContent></complexType>"); _correctStringArray = sb.toString(); sb = new StringBundler(2); sb.append("<complexType name=\"OrderByComparator\"><simpleContent>"); sb.append("<extension/></simpleContent></complexType>"); _incorrectOrderByComparator = sb.toString(); sb = new StringBundler(2); sb.append("<complexType name=\"ArrayOf_xsd_long\"><simpleContent>"); sb.append("<extension/></simpleContent></complexType>"); _incorrectLongArray = sb.toString(); sb = new StringBundler(2); sb.append("<complexType name=\"ArrayOf_xsd_string\"><simpleContent>"); sb.append("<extension/></simpleContent></complexType>"); _incorrectStringArray = sb.toString(); if (ServerDetector.isResin() || ServerDetector.isWebLogic()) { doInit(); } else { InitThread initThread = new InitThread(); initThread.start(); try { initThread.join(); } catch (InterruptedException ie) { throw new ServletException(ie); } Exception e = initThread.getException(); if (e != null) { if (e instanceof ServletException) { throw (ServletException)e; } else { throw new ServletException(e); } } } } @Override public void service( HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { if (!_ready) { return; } BufferCacheServletResponse bufferCacheServletResponse = new BufferCacheServletResponse(response); super.service(request, bufferCacheServletResponse); String contentType = bufferCacheServletResponse.getContentType(); response.setContentType(contentType); String content = bufferCacheServletResponse.getString(); if (_fixContent) { if (contentType.contains(ContentTypes.TEXT_HTML)) { content = _HTML_TOP_WRAPPER.concat(content).concat( _HTML_BOTTOM_WRAPPER); } else if (contentType.contains(ContentTypes.TEXT_XML)) { content = fixXml(content); } } ServletResponseUtil.write( new UncommittedServletResponse(response), content.getBytes(StringPool.UTF8)); } catch (IOException ioe) { throw ioe; } catch (ServletException se) { throw se; } catch (Exception e) { throw new ServletException(e); } finally { try { ThreadLocal<?> cache = (ThreadLocal<?>)_CACHE_FIELD.get(null); if (cache != null) { cache.remove(); } } catch (Exception e) { _log.error(e, e); } } } protected void doDestroy() { _ready = false; super.destroy(); } protected void doInit() throws ServletException { super.init(_servletConfig); _fixContent = GetterUtil.getBoolean( _servletConfig.getInitParameter("fix-content"), true); _ready = true; } protected String fixXml(String xml) throws Exception { if (!xml.contains("<wsdl:definitions")) { return xml; } xml = StringUtil.replace( xml, new String[] { "\r\n", "\n", " ", "> <", _incorrectOrderByComparator, _incorrectLongArray, _incorrectStringArray }, new String[] { StringPool.BLANK, StringPool.BLANK, StringPool.BLANK, "><", _correctOrderByComparator, _correctLongArray, _correctStringArray }); Document document = UnsecureSAXReaderUtil.read(xml); return document.formattedString(); } private static final Field _CACHE_FIELD; private static final String _HTML_BOTTOM_WRAPPER = "</body></html>"; private static final String _HTML_TOP_WRAPPER = "<html><body>"; private static final Log _log = LogFactoryUtil.getLog(AxisServlet.class); static { try { _CACHE_FIELD = ReflectionUtil.getDeclaredField( MethodCache.class, "cache"); } catch (Exception e) { throw new LoggedExceptionInInitializerError(e); } } private String _correctLongArray; private String _correctOrderByComparator; private String _correctStringArray; private boolean _fixContent; private String _incorrectLongArray; private String _incorrectOrderByComparator; private String _incorrectStringArray; private boolean _ready; private ServletConfig _servletConfig; private class DestroyThread extends Thread { public DestroyThread() { setDaemon(true); } public Exception getException() { return _exception; } @Override public void run() { try { doDestroy(); } catch (Exception e) { _exception = e; } } private Exception _exception; } private class InitThread extends Thread { public InitThread() { setDaemon(true); } public Exception getException() { return _exception; } @Override public void run() { try { doInit(); } catch (Exception e) { _exception = e; } } private Exception _exception; } }