1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.util.bridges.bsf;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.FileUtil;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.StringUtil;
30  
31  import java.io.IOException;
32  import java.io.InputStream;
33  
34  import java.util.Map;
35  
36  import javax.portlet.ActionRequest;
37  import javax.portlet.ActionResponse;
38  import javax.portlet.GenericPortlet;
39  import javax.portlet.PortletConfig;
40  import javax.portlet.PortletContext;
41  import javax.portlet.PortletException;
42  import javax.portlet.PortletPreferences;
43  import javax.portlet.PortletRequest;
44  import javax.portlet.PortletResponse;
45  import javax.portlet.RenderRequest;
46  import javax.portlet.RenderResponse;
47  import javax.portlet.ResourceRequest;
48  import javax.portlet.ResourceResponse;
49  
50  import org.apache.bsf.BSFException;
51  import org.apache.bsf.BSFManager;
52  
53  /**
54   * <a href="BaseBSFPortlet.java.html"><b><i>View Source</i></b></a>
55   *
56   * @author Jorge Ferrer
57   * @author Brian Wing Shun Chan
58   *
59   */
60  public abstract class BaseBSFPortlet extends GenericPortlet {
61  
62      public void init() {
63          editFile = getInitParameter("edit-file");
64          helpFile = getInitParameter("help-file");
65          viewFile = getInitParameter("view-file");
66          actionFile = getInitParameter("action-file");
67          resourceFile = getInitParameter("resource-file");
68          globalFiles = StringUtil.split(getInitParameter("global-files"));
69  
70          BSFManager.registerScriptingEngine(
71              getScriptingEngineLanguage(), getScriptingEngineClassName(),
72              new String[] {getScriptingEngineExtension()});
73  
74          bsfManager = new BSFManager();
75      }
76  
77      public void doDispatch(
78              RenderRequest renderRequest, RenderResponse renderResponse)
79          throws IOException, PortletException {
80  
81          String file = renderRequest.getParameter(getFileParam());
82  
83          if (file != null) {
84              include(file, renderRequest, renderResponse);
85          }
86          else {
87              super.doDispatch(renderRequest, renderResponse);
88          }
89      }
90  
91      public void doEdit(
92              RenderRequest renderRequest, RenderResponse renderResponse)
93          throws IOException, PortletException {
94  
95          if (renderRequest.getPreferences() == null) {
96              super.doEdit(renderRequest, renderResponse);
97          }
98          else {
99              include(editFile, renderRequest, renderResponse);
100         }
101     }
102 
103     public void doHelp(
104             RenderRequest renderRequest, RenderResponse renderResponse)
105         throws IOException {
106 
107         include(helpFile, renderRequest, renderResponse);
108     }
109 
110     public void doView(
111             RenderRequest renderRequest, RenderResponse renderResponse)
112         throws IOException {
113 
114         include(viewFile, renderRequest, renderResponse);
115     }
116 
117     public void processAction(
118             ActionRequest actionRequest, ActionResponse actionResponse)
119         throws IOException {
120 
121         include(actionFile, actionRequest, actionResponse);
122     }
123 
124     public void serveResource(
125             ResourceRequest resourceRequest, ResourceResponse resourceResponse)
126         throws IOException {
127 
128         include(resourceFile, resourceRequest, resourceResponse);
129     }
130 
131     protected void declareBeans(
132             InputStream is, PortletRequest portletRequest,
133             PortletResponse portletResponse)
134         throws BSFException, IOException {
135 
136         declareBeans(
137             new String(FileUtil.getBytes(is)), portletRequest, portletResponse);
138     }
139 
140     protected void declareBeans(
141             String code, PortletRequest portletRequest,
142             PortletResponse portletResponse)
143         throws BSFException, IOException {
144 
145         StringBuilder sb = new StringBuilder();
146 
147         sb.append(getGlobalScript());
148         sb.append(code);
149 
150         String script = sb.toString();
151 
152         PortletConfig portletConfig = getPortletConfig();
153         PortletContext portletContext = getPortletContext();
154         PortletPreferences preferences = portletRequest.getPreferences();
155         Map<String, String> userInfo =
156             (Map<String, String>)portletRequest.getAttribute(
157                 PortletRequest.USER_INFO);
158 
159         bsfManager.declareBean(
160             "portletConfig", portletConfig, PortletConfig.class);
161         bsfManager.declareBean(
162             "portletContext", portletContext, PortletContext.class);
163         bsfManager.declareBean(
164             "preferences", preferences, PortletPreferences.class);
165         bsfManager.declareBean("userInfo", userInfo, Map.class);
166 
167         if (portletRequest instanceof ActionRequest) {
168             bsfManager.declareBean(
169                 "actionRequest", portletRequest, ActionRequest.class);
170         }
171         else if (portletRequest instanceof RenderRequest) {
172             bsfManager.declareBean(
173                 "renderRequest", portletRequest, RenderRequest.class);
174         }
175         else if (portletRequest instanceof ResourceRequest) {
176             bsfManager.declareBean(
177                 "resourceRequest", portletRequest, ResourceRequest.class);
178         }
179 
180         if (portletResponse instanceof ActionResponse) {
181             bsfManager.declareBean(
182                 "actionResponse", portletResponse, ActionResponse.class);
183         }
184         else if (portletResponse instanceof RenderResponse) {
185             bsfManager.declareBean(
186                 "renderResponse", portletResponse, RenderResponse.class);
187         }
188         else if (portletResponse instanceof ResourceResponse) {
189             bsfManager.declareBean(
190                 "resourceResponse", portletResponse, ResourceResponse.class);
191         }
192 
193         bsfManager.exec(getScriptingEngineLanguage(), "(java)", 1, 1, script);
194     }
195 
196     protected String getGlobalScript() throws IOException {
197         StringBuilder sb = new StringBuilder();
198 
199         for (int i = 0; i < globalFiles.length; i++) {
200             InputStream is = getPortletContext().getResourceAsStream(
201                 globalFiles[i]);
202 
203             if (is == null) {
204                 if (_log.isWarnEnabled()) {
205                     _log.warn(
206                         "Global file " + globalFiles[i] + " does not exist");
207                 }
208             }
209 
210             try {
211                 if (is != null) {
212                     sb.append(new String(FileUtil.getBytes(is)));
213                     sb.append(StringPool.NEW_LINE);
214                 }
215             }
216             finally {
217                 is.close();
218             }
219         }
220 
221         return sb.toString();
222     }
223 
224     protected abstract String getFileParam();
225 
226     protected abstract String getScriptingEngineClassName();
227 
228     protected abstract String getScriptingEngineExtension();
229 
230     protected abstract String getScriptingEngineLanguage();
231 
232     protected void include(
233             String path, PortletRequest portletRequest,
234             PortletResponse portletResponse)
235         throws IOException {
236 
237         InputStream is = getPortletContext().getResourceAsStream(path);
238 
239         if (is == null) {
240             _log.error(
241                 path + " is not a valid " + getScriptingEngineLanguage() +
242                     " file");
243 
244             return;
245         }
246 
247         try {
248             declareBeans(is, portletRequest, portletResponse);
249         }
250         catch (BSFException bsfe) {
251             logBSFException(bsfe, path);
252         }
253         finally {
254             is.close();
255         }
256     }
257 
258     protected void logBSFException(BSFException bsfe, String path) {
259         String message =
260             "The script at " + path + " or one of the global files has errors.";
261 
262         Throwable t = bsfe.getTargetException();
263 
264         _log.error(message, t);
265     }
266 
267     protected String editFile;
268     protected String helpFile;
269     protected String viewFile;
270     protected String actionFile;
271     protected String resourceFile;
272     protected String[] globalFiles;
273     protected BSFManager bsfManager;
274 
275     private static Log _log = LogFactoryUtil.getLog(BaseBSFPortlet.class);
276 
277 }