1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.jetspeed.aggregator.impl;
19
20 import java.util.Iterator;
21 import java.util.Map;
22
23 import javax.portlet.UnavailableException;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.jetspeed.PortalReservedParameters;
30 import org.apache.jetspeed.aggregator.ContentDispatcherCtrl;
31 import org.apache.jetspeed.aggregator.CurrentWorkerContext;
32 import org.apache.jetspeed.aggregator.PortletContent;
33 import org.apache.jetspeed.aggregator.PortletRenderer;
34 import org.apache.jetspeed.aggregator.PortletTrackingManager;
35 import org.apache.jetspeed.aggregator.RenderingJob;
36 import org.apache.jetspeed.aggregator.Worker;
37 import org.apache.jetspeed.components.portletentity.PortletEntityImpl;
38 import org.apache.jetspeed.om.common.portlet.MutablePortletEntity;
39 import org.apache.jetspeed.om.page.ContentFragment;
40 import org.apache.jetspeed.request.RequestContext;
41 import org.apache.jetspeed.statistics.PortalStatistics;
42 import org.apache.pluto.PortletContainer;
43 import org.apache.pluto.om.portlet.PortletDefinition;
44 import org.apache.pluto.om.window.PortletWindow;
45
46 /***
47 * The RenderingJob is responsible for storing all necessary objets for
48 * asynchronous portlet rendering as well as implementing the rendering logic
49 * in its Runnable method.
50 *
51 * @author <a href="mailto:raphael@apache.org">Rapha?l Luta</a>
52 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
53 * @author <a>Woonsan Ko</a>
54 * @version $Id: RenderingJobImpl.java 554827 2007-07-10 05:12:23Z taylor $
55 */
56 public class RenderingJobImpl implements RenderingJob
57 {
58 /*** Commons logging */
59 protected final static Log log = LogFactory.getLog(RenderingJobImpl.class);
60
61 /*** WorkerMonitor used to flush the queue */
62 protected PortletWindow window = null;
63 protected HttpServletRequest request = null;
64 protected HttpServletResponse response = null;
65
66 protected PortletContainer container = null;
67 protected PortletRenderer renderer = null;
68 protected ContentFragment fragment = null;
69 protected RequestContext requestContext = null;
70 protected PortletTrackingManager portletTracking = null;
71
72 protected PortletDefinition portletDefinition;
73 protected PortletContent portletContent;
74 protected PortalStatistics statistics;
75 protected ContentDispatcherCtrl dispatcher;
76 protected boolean contentIsCached;
77
78 protected int expirationCache = 0;
79
80 protected Map workerAttributes;
81
82 protected long startTimeMillis = 0;
83 protected long timeout;
84
85 public RenderingJobImpl(PortletContainer container,
86 PortletRenderer renderer,
87 PortletDefinition portletDefinition,
88 PortletContent portletContent,
89 ContentFragment fragment,
90 ContentDispatcherCtrl dispatcher,
91 HttpServletRequest request,
92 HttpServletResponse response,
93 RequestContext requestContext,
94 PortletWindow window,
95 PortalStatistics statistics,
96 int expirationCache,
97 boolean contentIsCached)
98 {
99 this.container = container;
100 this.renderer = renderer;
101 this.portletTracking = renderer.getPortletTrackingManager();
102 this.statistics = statistics;
103 this.portletDefinition = portletDefinition;
104 this.fragment = fragment;
105 this.dispatcher = dispatcher;
106 this.request = request;
107 this.response = response;
108 this.requestContext = requestContext;
109 this.window = window;
110 this.portletContent = portletContent;
111 ((MutablePortletEntity)window.getPortletEntity()).setFragment(fragment);
112 this.expirationCache = expirationCache;
113 this.contentIsCached = contentIsCached;
114 }
115
116 public RenderingJobImpl(PortletContainer container,
117 PortletRenderer renderer,
118 PortletDefinition portletDefinition,
119 PortletContent portletContent,
120 ContentFragment fragment,
121 ContentDispatcherCtrl dispatcher,
122 HttpServletRequest request,
123 HttpServletResponse response,
124 RequestContext requestContext,
125 PortletWindow window,
126 PortalStatistics statistics,
127 int expirationCache,
128 boolean contentIsCached,
129 Map workerAttributes)
130 {
131 this(container, renderer, portletDefinition, portletContent, fragment, dispatcher,
132 request, response, requestContext, window, statistics, expirationCache, contentIsCached);
133 this.workerAttributes = workerAttributes;
134 }
135
136 /***
137 * Sets portlet timout in milliseconds.
138 */
139 public void setTimeout(long timeout) {
140 this.timeout = timeout;
141 }
142
143 /***
144 * Gets portlet timout in milliseconds.
145 */
146 public long getTimeout() {
147 return this.timeout;
148 }
149
150 /***
151 * Checks if the portlet rendering is timeout
152 */
153 public boolean isTimeout() {
154 if ((this.timeout > 0) && (this.startTimeMillis > 0)) {
155 return (System.currentTimeMillis() - this.startTimeMillis > this.timeout);
156 }
157
158 return false;
159 }
160
161 /***
162 * Checks if queue is empty, if not try to empty it by calling
163 * the WorkerMonitor. When done, pause until next scheduled scan.
164 */
165 public void run()
166 {
167 try
168 {
169 if (this.timeout > 0) {
170 this.startTimeMillis = System.currentTimeMillis();
171 }
172
173
174 fragment.setPortletContent(portletContent);
175 execute();
176 }
177 finally
178 {
179
180 synchronized (portletContent)
181 {
182 log.debug("Notifying completion of rendering job for fragment " + fragment.getId());
183 portletContent.notifyAll();
184 }
185 }
186 }
187
188 /***
189 * <p>
190 * execute
191 * </p>
192 *
193 *
194 */
195 public void execute()
196 {
197 long start = System.currentTimeMillis();
198 boolean isParallelMode = false;
199 PortletWindow curWindow = this.window;
200 try
201 {
202 log.debug("Rendering OID "+this.window.getId()+" "+ this.request +" "+this.response);
203
204
205 if (this.workerAttributes != null)
206 {
207 isParallelMode = (Thread.currentThread() instanceof Worker || CurrentWorkerContext.getCurrentWorkerContextUsed());
208 if (isParallelMode)
209 {
210 Iterator itAttrNames = this.workerAttributes.keySet().iterator();
211 while (itAttrNames.hasNext())
212 {
213 String name = (String) itAttrNames.next();
214 CurrentWorkerContext.setAttribute(name, this.workerAttributes.get(name));
215 }
216
217
218
219
220
221
222
223
224 curWindow = (PortletWindow)
225 CurrentWorkerContext.getAttribute(PortalReservedParameters.PORTLET_WINDOW_ATTRIBUTE);
226 PortletEntityImpl curEntity = (PortletEntityImpl) curWindow.getPortletEntity();
227 PortletDefinition oldPortletDefinition = curEntity.getPortletDefinition();
228 PortletDefinition curPortletDefinition = (PortletDefinition)
229 CurrentWorkerContext.getAttribute(PortalReservedParameters.PORTLET_DEFINITION_ATTRIBUTE);
230
231 if (!oldPortletDefinition.getId().equals(curPortletDefinition.getId())) {
232 curEntity.setPortletDefinition(curPortletDefinition);
233 }
234 }
235 }
236
237 this.request.setAttribute(PortalReservedParameters.FRAGMENT_ATTRIBUTE, fragment);
238 this.request.setAttribute(PortalReservedParameters.PAGE_ATTRIBUTE, requestContext.getPage());
239 this.request.setAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE, requestContext);
240 this.request.setAttribute(PortalReservedParameters.REQUEST_CONTEXT_OBJECTS, requestContext.getObjects());
241
242 container.renderPortlet(this.window, this.request, this.response);
243 this.response.flushBuffer();
244 }
245 catch (Throwable t)
246 {
247 if (t instanceof UnavailableException)
248 {
249
250 log.error("Error rendering portlet OID " + curWindow.getId() + ": " + t.toString());
251 }
252 else
253 {
254 log.error("Error rendering portlet OID " + curWindow.getId(), t);
255 }
256 fragment.overrideRenderedContent(t.getMessage());
257 }
258 finally
259 {
260 long end = System.currentTimeMillis();
261 boolean exceededTimeout = portletTracking.exceededTimeout(end - start, window);
262 if (fragment.getOverriddenContent() != null)
263 portletContent.completeWithError();
264 else
265 portletContent.complete();
266
267 if (isParallelMode)
268 {
269 this.renderer.addTitleToHeader(curWindow, fragment,
270 this.request, this.response,
271 this.dispatcher, this.contentIsCached);
272
273 CurrentWorkerContext.removeAllAttributes();
274 }
275
276 if (fragment.getType().equals(ContentFragment.PORTLET))
277 {
278 if (statistics != null)
279 {
280 statistics.logPortletAccess(requestContext, fragment.getName(), PortalStatistics.HTTP_OK, end - start);
281 }
282 if (exceededTimeout)
283 {
284
285 log.info("Portlet Exceeded timeout: " + curWindow.getPortletEntity().getPortletDefinition().getName() + " for window " + curWindow.getId());
286 portletTracking.incrementRenderTimeoutCount(curWindow);
287 }
288 else
289 {
290 portletTracking.success(curWindow);
291 }
292 }
293 }
294 }
295
296 /***
297 *
298 * <p>
299 * getWindow
300 * </p>
301 *
302 * @return The window this job is in charge of rendering
303 */
304 public PortletWindow getWindow()
305 {
306 return window;
307 }
308
309 /***
310 *
311 * <p>
312 * getPortletContent
313 * </p>
314 *
315 * @return The portlet content this job is in charge of rendering
316 */
317 public PortletContent getPortletContent()
318 {
319 return portletContent;
320 }
321
322 public PortletDefinition getPortletDefinition()
323 {
324 return this.portletDefinition;
325 }
326
327 public HttpServletRequest getRequest()
328 {
329 return this.request;
330 }
331
332 public HttpServletResponse getResponse()
333 {
334 return this.response;
335 }
336
337 public ContentFragment getFragment()
338 {
339 return this.fragment;
340 }
341
342 public RequestContext getRequestContext()
343 {
344 return this.requestContext;
345 }
346
347 public int getExpirationCache()
348 {
349 return this.expirationCache;
350 }
351
352 public ContentDispatcherCtrl getDispatcher()
353 {
354 return this.dispatcher;
355 }
356
357 public boolean isContentCached() {
358 return this.contentIsCached;
359 }
360 }