001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.struts;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.json.JSONFactoryUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.servlet.HttpHeaders;
022    import com.liferay.portal.kernel.servlet.ServletContextPool;
023    import com.liferay.portal.kernel.util.ContentTypes;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.ParamUtil;
026    import com.liferay.portal.kernel.util.SetUtil;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.security.auth.AuthTokenUtil;
030    import com.liferay.portal.security.auth.PrincipalException;
031    import com.liferay.portal.servlet.SharedSessionServletRequest;
032    import com.liferay.portal.util.PortalUtil;
033    import com.liferay.portal.util.PropsValues;
034    import com.liferay.portal.util.WebKeys;
035    
036    import java.io.OutputStream;
037    
038    import java.util.Set;
039    
040    import javax.servlet.RequestDispatcher;
041    import javax.servlet.ServletContext;
042    import javax.servlet.http.HttpServletRequest;
043    import javax.servlet.http.HttpServletResponse;
044    
045    import org.apache.struts.action.Action;
046    import org.apache.struts.action.ActionForm;
047    import org.apache.struts.action.ActionForward;
048    import org.apache.struts.action.ActionMapping;
049    
050    /**
051     * @author Ming-Gih Lam
052     * @author Brian Wing Shun Chan
053     * @author Tomas Polesovsky
054     */
055    public abstract class JSONAction extends Action {
056    
057            @Override
058            public ActionForward execute(
059                            ActionMapping mapping, ActionForm form, HttpServletRequest request,
060                            HttpServletResponse response)
061                    throws Exception {
062    
063                    if (rerouteExecute(request, response)) {
064                            return null;
065                    }
066    
067                    String callback = ParamUtil.getString(request, "callback");
068                    String instance = ParamUtil.getString(request, "inst");
069    
070                    String json = null;
071    
072                    try {
073                            checkAuthToken(request);
074    
075                            json = getJSON(mapping, form, request, response);
076    
077                            if (Validator.isNotNull(callback)) {
078                                    json = callback + "(" + json + ");";
079                            }
080                            else if (Validator.isNotNull(instance)) {
081                                    json = "var " + instance + "=" + json + ";";
082                            }
083                    }
084                    catch (PrincipalException pe) {
085                            if (_log.isWarnEnabled()) {
086                                    _log.warn(pe.getMessage());
087                            }
088    
089                            json = JSONFactoryUtil.serializeException(pe);
090                    }
091                    catch (Exception e) {
092                            PortalUtil.sendError(
093                                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e, request,
094                                    response);
095    
096                            return null;
097                    }
098    
099                    boolean refresh = ParamUtil.getBoolean(request, "refresh");
100    
101                    if (refresh) {
102                            return mapping.findForward(ActionConstants.COMMON_REFERER);
103                    }
104                    else if (Validator.isNotNull(json)) {
105                            response.setCharacterEncoding(StringPool.UTF8);
106                            response.setContentType(ContentTypes.TEXT_JAVASCRIPT);
107                            response.setHeader(
108                                    HttpHeaders.CACHE_CONTROL,
109                                    HttpHeaders.CACHE_CONTROL_NO_CACHE_VALUE);
110    
111                            OutputStream outputStream = response.getOutputStream();
112    
113                            byte[] bytes = json.getBytes(StringPool.UTF8);
114    
115                            outputStream.write(bytes);
116    
117                            outputStream.close();
118                    }
119    
120                    return null;
121            }
122    
123            public abstract String getJSON(
124                            ActionMapping mapping, ActionForm form, HttpServletRequest request,
125                            HttpServletResponse response)
126                    throws Exception;
127    
128            public void setServletContext(ServletContext servletContext) {
129                    _servletContext = servletContext;
130            }
131    
132            protected void checkAuthToken(HttpServletRequest request)
133                    throws PortalException {
134    
135                    String authType = GetterUtil.getString(request.getAuthType());
136    
137                    if (authType.equals(HttpServletRequest.BASIC_AUTH) ||
138                            authType.equals(HttpServletRequest.DIGEST_AUTH)) {
139    
140                            return;
141                    }
142    
143                    if (PropsValues.AUTH_TOKEN_CHECK_ENABLED &&
144                            PropsValues.JSON_SERVICE_AUTH_TOKEN_ENABLED) {
145    
146                            if (!isAccessAllowed(request, _hostsAllowed)) {
147                                    AuthTokenUtil.check(request);
148                            }
149                    }
150            }
151    
152            protected String getReroutePath() {
153                    return null;
154            }
155    
156            protected boolean isAccessAllowed(
157                    HttpServletRequest request, Set<String> hostsAllowed) {
158    
159                    if (hostsAllowed.isEmpty()) {
160                            return true;
161                    }
162    
163                    String remoteAddr = request.getRemoteAddr();
164    
165                    if (hostsAllowed.contains(remoteAddr)) {
166                            return true;
167                    }
168    
169                    String computerAddress = PortalUtil.getComputerAddress();
170    
171                    if (computerAddress.equals(remoteAddr) &&
172                            hostsAllowed.contains(_SERVER_IP)) {
173    
174                            return true;
175                    }
176    
177                    return false;
178            }
179    
180            protected boolean rerouteExecute(
181                            HttpServletRequest request, HttpServletResponse response)
182                    throws Exception {
183    
184                    String reroutePath = getReroutePath();
185    
186                    if (Validator.isNull(reroutePath)) {
187                            return false;
188                    }
189    
190                    String requestServletContextName = ParamUtil.getString(
191                            request, "servletContextName");
192    
193                    if (Validator.isNull(requestServletContextName)) {
194                            return false;
195                    }
196    
197                    ServletContext servletContext = _servletContext;
198    
199                    if (servletContext == null) {
200                            servletContext = (ServletContext)request.getAttribute(WebKeys.CTX);
201                    }
202    
203                    String servletContextName = GetterUtil.getString(
204                            servletContext.getServletContextName());
205    
206                    if (servletContextName.equals(requestServletContextName)) {
207                            return false;
208                    }
209    
210                    ServletContext requestServletContext = ServletContextPool.get(
211                            requestServletContextName);
212    
213                    if (requestServletContext == null) {
214                            return false;
215                    }
216    
217                    RequestDispatcher requestDispatcher =
218                            requestServletContext.getRequestDispatcher(reroutePath);
219    
220                    if (requestDispatcher == null) {
221                            return false;
222                    }
223    
224                    requestDispatcher.forward(
225                            new SharedSessionServletRequest(request, true), response);
226    
227                    return true;
228            }
229    
230            private static final String _SERVER_IP = "SERVER_IP";
231    
232            private static Log _log = LogFactoryUtil.getLog(JSONAction.class);
233    
234            private Set<String> _hostsAllowed = SetUtil.fromArray(
235                    PropsValues.JSON_SERVICE_AUTH_TOKEN_HOSTS_ALLOWED);
236            private ServletContext _servletContext;
237    
238    }