1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.util.axis;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.servlet.StringServletResponse;
20  import com.liferay.portal.kernel.servlet.UncommittedServletResponse;
21  import com.liferay.portal.kernel.util.ContentTypes;
22  import com.liferay.portal.kernel.util.GetterUtil;
23  import com.liferay.portal.kernel.util.ReflectionUtil;
24  import com.liferay.portal.kernel.util.ServerDetector;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.xml.Document;
28  import com.liferay.portal.kernel.xml.SAXReaderUtil;
29  import com.liferay.util.servlet.ServletResponseUtil;
30  
31  import java.io.IOException;
32  
33  import java.lang.reflect.Field;
34  
35  import javax.servlet.ServletConfig;
36  import javax.servlet.ServletException;
37  import javax.servlet.http.HttpServletRequest;
38  import javax.servlet.http.HttpServletResponse;
39  
40  import org.apache.axis.utils.cache.MethodCache;
41  
42  /**
43   * <a href="AxisServlet.java.html"><b><i>View Source</i></b></a>
44   *
45   * @author Brian Wing Shun Chan
46   */
47  public class AxisServlet extends org.apache.axis.transport.http.AxisServlet {
48  
49      public void destroy() {
50          if (ServerDetector.isWebLogic()) {
51              doDestroy();
52          }
53          else {
54              DestroyThread destroyThread = new DestroyThread();
55  
56              destroyThread.start();
57  
58              try {
59                  destroyThread.join();
60              }
61              catch (InterruptedException ie) {
62                  throw new RuntimeException(ie);
63              }
64  
65              Exception e = destroyThread.getException();
66  
67              if (e != null) {
68                  if (e instanceof RuntimeException) {
69                      throw (RuntimeException)e;
70                  }
71                  else {
72                      throw new RuntimeException(e);
73                  }
74              }
75          }
76      }
77  
78      public void init(ServletConfig servletConfig) throws ServletException {
79          _servletConfig = servletConfig;
80  
81          if (ServerDetector.isWebLogic()) {
82              doInit();
83          }
84          else {
85              InitThread initThread = new InitThread();
86  
87              initThread.start();
88  
89              try {
90                  initThread.join();
91              }
92              catch (InterruptedException ie) {
93                  throw new ServletException(ie);
94              }
95  
96              Exception e = initThread.getException();
97  
98              if (e != null) {
99                  if (e instanceof ServletException) {
100                     throw (ServletException)e;
101                 }
102                 else {
103                     throw new ServletException(e);
104                 }
105             }
106         }
107     }
108 
109     public void service(
110             HttpServletRequest request, HttpServletResponse response)
111         throws IOException, ServletException {
112 
113         try {
114             if (!_ready) {
115                 return;
116             }
117 
118             StringServletResponse stringResponse = new StringServletResponse(
119                 response);
120 
121             super.service(request, stringResponse);
122 
123             String contentType = stringResponse.getContentType();
124 
125             response.setContentType(contentType);
126 
127             String content = stringResponse.getString();
128 
129             if (_fixContent) {
130                 if (contentType.contains(ContentTypes.TEXT_HTML)) {
131                     content = _HTML_TOP_WRAPPER.concat(content).concat(
132                         _HTML_BOTTOM_WRAPPER);
133                 }
134                 else if (contentType.contains(ContentTypes.TEXT_XML)) {
135                     content = fixXml(content);
136                 }
137             }
138 
139             ServletResponseUtil.write(
140                 new UncommittedServletResponse(response),
141                 content.getBytes(StringPool.UTF8));
142         }
143         catch (IOException ioe) {
144             throw ioe;
145         }
146         catch (ServletException se) {
147             throw se;
148         }
149         catch (Exception e) {
150             throw new ServletException(e);
151         }
152         finally {
153             try {
154                 ThreadLocal<?> cache = (ThreadLocal<?>)_cacheField.get(null);
155 
156                 if (cache != null) {
157                     cache.remove();
158                 }
159             }
160             catch (Exception e) {
161                 _log.error(e, e);
162             }
163         }
164     }
165 
166     protected void doDestroy() {
167         _ready = false;
168 
169         super.destroy();
170     }
171 
172     protected void doInit() throws ServletException {
173         super.init(_servletConfig);
174 
175         _fixContent = GetterUtil.getBoolean(
176             _servletConfig.getInitParameter("fix-content"), true);
177 
178         _ready = true;
179     }
180 
181     protected String fixXml(String xml) throws Exception {
182         if (xml.indexOf("<wsdl:definitions") == -1) {
183             return xml;
184         }
185 
186         xml = StringUtil.replace(
187             xml,
188             new String[] {
189                 "\r\n",
190                 "\n",
191                 "  ",
192                 "> <",
193                 _INCORRECT_LONG_ARRAY,
194                 _INCORRECT_STRING_ARRAY
195             },
196             new String[] {
197                 StringPool.BLANK,
198                 StringPool.BLANK,
199                 StringPool.BLANK,
200                 "><",
201                 _CORRECT_LONG_ARRAY,
202                 _CORRECT_STRING_ARRAY
203             });
204 
205         Document document = SAXReaderUtil.read(xml);
206 
207         return document.formattedString();
208     }
209 
210     private static final String _CORRECT_LONG_ARRAY =
211         "<complexType name=\"ArrayOf_xsd_long\"><complexContent>" +
212             "<restriction base=\"soapenc:Array\"><attribute ref=\"soapenc:" +
213                 "arrayType\" wsdl:arrayType=\"soapenc:long[]\"/>" +
214                     "</restriction></complexContent></complexType>";
215 
216     private static final String _CORRECT_STRING_ARRAY =
217         "<complexType name=\"ArrayOf_xsd_string\"><complexContent>" +
218             "<restriction base=\"soapenc:Array\"><attribute ref=\"soapenc:" +
219                 "arrayType\" wsdl:arrayType=\"soapenc:string[]\"/>" +
220                     "</restriction></complexContent></complexType>";
221 
222     private static final String _HTML_BOTTOM_WRAPPER = "</body></html>";
223 
224     private static final String _HTML_TOP_WRAPPER = "<html><body>";
225 
226     private static final String _INCORRECT_LONG_ARRAY =
227         "<complexType name=\"ArrayOf_xsd_long\"><simpleContent><extension/>" +
228             "</simpleContent></complexType>";
229 
230     private static final String _INCORRECT_STRING_ARRAY =
231         "<complexType name=\"ArrayOf_xsd_string\"><simpleContent><extension/>" +
232             "</simpleContent></complexType>";
233 
234     private static Log _log = LogFactoryUtil.getLog(AxisServlet.class);
235 
236     private static Field _cacheField;
237 
238     private boolean _fixContent;
239     private boolean _ready;
240     private ServletConfig _servletConfig;
241 
242     private class DestroyThread extends Thread {
243 
244         public DestroyThread() {
245             setDaemon(true);
246         }
247 
248         public Exception getException() {
249             return _exception;
250         }
251 
252         public void run() {
253             try {
254                 doDestroy();
255             }
256             catch (Exception e) {
257                 _exception = e;
258             }
259         }
260 
261         private Exception _exception;
262 
263     }
264 
265     private class InitThread extends Thread {
266 
267         public InitThread() {
268             setDaemon(true);
269         }
270 
271         public Exception getException() {
272             return _exception;
273         }
274 
275         public void run() {
276             try {
277                 doInit();
278             }
279             catch (Exception e) {
280                 _exception = e;
281             }
282         }
283 
284         private Exception _exception;
285 
286     }
287 
288     static {
289         try {
290             _cacheField = ReflectionUtil.getDeclaredField(
291                 MethodCache.class, "cache");
292         }
293         catch (Exception e) {
294             _log.error(e, e);
295         }
296     }
297 
298 }