001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.test.theme;
023:
024: import org.apache.log4j.Logger;
025: import org.jboss.mx.util.MBeanProxy;
026: import org.jboss.mx.util.MBeanServerLocator;
027: import org.jboss.portal.common.util.IteratorStatus;
028: import org.jboss.portal.common.util.MarkupInfo;
029: import org.jboss.portal.common.util.MediaType;
030: import org.jboss.portal.test.framework.driver.DriverCommand;
031: import org.jboss.portal.test.framework.driver.DriverResponse;
032: import org.jboss.portal.test.framework.driver.TestDriverException;
033: import org.jboss.portal.test.framework.driver.command.StartTestCommand;
034: import org.jboss.portal.test.framework.driver.response.FailureResponse;
035: import org.jboss.portal.test.framework.driver.web.WebTestCase;
036: import org.jboss.portal.test.framework.junit.ThrowableDecoder;
037: import org.jboss.portal.test.theme.model.ObjectChange;
038: import org.jboss.portal.test.theme.model.PageObject;
039: import org.jboss.portal.test.theme.model.RenderedObject;
040: import org.jboss.portal.test.theme.model.RenderedObjectContext;
041: import org.jboss.portal.test.theme.model.RenderedObjectContextFactory;
042: import org.jboss.portal.test.theme.model.WindowObject;
043: import org.jboss.portal.theme.LayoutService;
044: import org.jboss.portal.theme.PortalLayout;
045: import org.jboss.portal.theme.PortalRenderSet;
046: import org.jboss.portal.theme.PortalTheme;
047: import org.jboss.portal.theme.ThemeConstants;
048: import org.jboss.portal.theme.ThemeService;
049: import org.jboss.portal.theme.impl.render.dynamic.DynaConstants;
050: import org.jboss.portal.theme.impl.render.dynamic.JSONMarshaller;
051: import org.jboss.portal.theme.impl.render.dynamic.response.UpdatePageStateResponse;
052: import org.jboss.portal.theme.page.PageResult;
053: import org.jboss.portal.theme.page.Region;
054: import org.jboss.portal.theme.page.WindowContext;
055: import org.jboss.portal.theme.page.WindowResult;
056: import org.jboss.portal.theme.render.RenderException;
057: import org.jboss.portal.theme.render.RendererContext;
058: import org.jboss.portal.theme.render.ThemeContext;
059: import org.jboss.portal.theme.render.renderer.PageRendererContext;
060: import org.jboss.portal.theme.render.renderer.RegionRendererContext;
061: import org.jboss.portal.theme.render.renderer.WindowRendererContext;
062: import org.jboss.portal.web.ServletContainerFactory;
063: import org.jboss.portal.web.ServletContextDispatcher;
064: import org.jboss.portal.web.spi.ServletContainerContext;
065:
066: import javax.management.MBeanServer;
067: import javax.management.ObjectName;
068: import java.io.IOException;
069: import java.io.StringWriter;
070: import java.util.ArrayList;
071: import java.util.HashMap;
072: import java.util.Iterator;
073: import java.util.List;
074:
075: /**
076: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
077: * @version $Revision: 8784 $
078: */
079: public class DynaTestContext extends WebTestCase {
080:
081: private final RenderedObjectContextFactory contextFactory = new RenderedObjectContextFactory() {
082: public RenderedObjectContext createContext(
083: final RenderedObject object) {
084: return new RenderedObjectContext() {
085: public void addChange(ObjectChange change) {
086: records.add(new ChangeRecord(object, change));
087: }
088: };
089: }
090: };
091:
092: private final Logger log;
093:
094: /** . */
095: private PageObject page;
096:
097: /** The changes. */
098: private final List records = new ArrayList();
099:
100: /** . */
101: final DynaTest test;
102:
103: /** . */
104: private final TestServlet servlet;
105:
106: /** . */
107: ServletContainerFactory servletContainerFactory;
108:
109: /** . */
110: LayoutService layoutService;
111:
112: /** . */
113: ThemeService themeService;
114:
115: /** . */
116: PortalRenderSet renderSet;
117:
118: /** . */
119: PortalLayout layout;
120:
121: /** . */
122: PortalTheme theme;
123:
124: public DynaTestContext(TestServlet servlet, DynaTest test,
125: String path) {
126: super (test.getId(), path);
127:
128: //
129: this .log = Logger.getLogger(test.getClass());
130: this .servlet = servlet;
131: this .test = test;
132: }
133:
134: public DriverResponse invoke(String testId, DriverCommand cmd)
135: throws TestDriverException {
136: if (cmd instanceof StartTestCommand) {
137: // Setup on servlet
138: servlet.testContext = this ;
139:
140: // Init services
141: try {
142: MBeanServer mbeanServer = MBeanServerLocator
143: .locateJBoss();
144: servletContainerFactory = (ServletContainerFactory) MBeanProxy
145: .get(
146: ServletContainerContext.class,
147: new ObjectName(
148: "portal:service=ServletContainerFactory"),
149: mbeanServer);
150: layoutService = (LayoutService) MBeanProxy.get(
151: LayoutService.class, new ObjectName(
152: "portal:service=LayoutService"),
153: mbeanServer);
154: themeService = (ThemeService) MBeanProxy.get(
155: ThemeService.class, new ObjectName(
156: "portal:service=ThemeService"),
157: mbeanServer);
158: renderSet = layoutService.getRenderSet("testRenderer",
159: MediaType.HTML);
160: layout = layoutService.getLayout("generic", true);
161: theme = themeService.getTheme("testTheme", true);
162:
163: //
164: page = new PageObject(contextFactory);
165: page.setProperty(ThemeConstants.PORTAL_PROP_THEME,
166: theme.getThemeInfo().getName());
167: page.setProperty(ThemeConstants.PORTAL_PROP_RENDERSET,
168: renderSet.getName());
169: page.setProperty(ThemeConstants.PORTAL_PROP_LAYOUT,
170: layout.getLayoutInfo().getName());
171:
172: //
173: // RegionObject testContextRegion = page.createRegion("TestContextRegion");
174: // testContextRegion.setRenderOptions(DynaRenderOptions.getOptions(null, Boolean.FALSE));
175: // WindowObject testContextWindow = testContextRegion.addWindow("TestContextWindow");
176: // testContextWindow.setRenderOptions(DynaRenderOptions.getOptions(null, Boolean.FALSE));
177:
178: //
179: test.init(this );
180: } catch (Exception e) {
181: return new FailureResponse(e);
182: }
183: }
184:
185: //
186: return super .invoke(testId, cmd);
187: }
188:
189: public PageObject getPage() {
190: return page;
191: }
192:
193: void invoke(RequestContext requestContext) throws RenderException,
194: IOException {
195: // The optional action phase has generated a response already, so we don't do anything
196: if (context.getResponse() != null) {
197: return;
198: }
199:
200: // Response
201: DriverResponse response;
202:
203: //
204: try {
205: // Clear recorded changes now
206: records.clear();
207:
208: // Invoke and get response
209: response = test.invoke(requestContext);
210:
211: // Modify the test request context
212: // page.getWindow("TestContextWindow").setMarkup("<div id=\"RequestCount\">" + context.getRequestCount() + "</div>");
213:
214: // Update the page if async
215: if (requestContext.getPhase().getLifeCycle() == TestPhase.RENDER_LIFE_CYCLE) {
216: if (requestContext.isAsync()) {
217: handleAsync(requestContext);
218: } else {
219: renderPage(requestContext);
220: }
221:
222: // Clear recorded changes now
223: records.clear();
224: } else {
225: // Nothing special to do for now
226: }
227: } catch (Throwable t) {
228: log.error("Test failed", t);
229:
230: //
231: response = ThrowableDecoder.decode(t);
232: }
233:
234: // Set response on context
235: if (response != null) {
236: context.setResponse(response);
237: }
238: }
239:
240: int getRequestCount() {
241: return context.getRequestCount();
242: }
243:
244: private void handleAsync(RequestContext requestContext)
245: throws RenderException, IOException {
246: MarkupInfo markupInfo = new MarkupInfo(MediaType.HTML, "UTF-8");
247: ServletContextDispatcher dispatcher = new ServletContextDispatcher(
248: requestContext.request, requestContext.response,
249: servletContainerFactory.getServletContainer());
250: ThemeContext themeContext = new ThemeContext(theme,
251: themeService);
252:
253: //
254: UpdatePageStateResponse resp = new UpdatePageStateResponse(null);
255:
256: //
257: page.setProperty(DynaConstants.RESOURCE_BASE_URL,
258: requestContext.request.getContextPath() + "/dyna");
259: page.setProperty(DynaConstants.SERVER_BASE_URL,
260: requestContext.request.getContextPath()
261: + requestContext.request.getServletPath());
262:
263: //
264: for (int i = 0; i < records.size(); i++) {
265: ChangeRecord record = (ChangeRecord) records.get(i);
266:
267: // For now only that use case exist, so it's ok...
268: WindowObject window = (WindowObject) record.source;
269:
270: //
271: StringWriter buffer = new StringWriter();
272: RendererContext rendererCtx = layout.getRenderContext(
273: themeContext, markupInfo, dispatcher, buffer);
274: rendererCtx.pushObjectRenderContext(page
275: .getRendererContext());
276: rendererCtx.pushObjectRenderContext(window.getRegion()
277: .getRendererContext());
278: rendererCtx.render(window.getRendererContext());
279:
280: //
281: resp.addFragment(window.getId(), buffer.toString());
282: }
283:
284: //
285: JSONMarshaller marshaller = new JSONMarshaller();
286: requestContext.response.setContentType("text/xml");
287: marshaller.write(resp, requestContext.response.getWriter());
288: }
289:
290: /** Renders the page fully in the resposne provided by the request context. */
291: private void renderPage(RequestContext requestContext)
292: throws RenderException {
293: requestContext.response.setContentType("text/html");
294:
295: MarkupInfo markupInfo = new MarkupInfo(MediaType.HTML, "UTF-8");
296: ServletContextDispatcher dispatcher = new ServletContextDispatcher(
297: requestContext.request, requestContext.response,
298: servletContainerFactory.getServletContainer());
299: ThemeContext themeContext = new ThemeContext(theme,
300: themeService);
301:
302: // Build a page structure
303: PageResult pageRenderCtx = createResult(page
304: .getRendererContext());
305:
306: //
307: pageRenderCtx.getProperties().put(
308: DynaConstants.RESOURCE_BASE_URL,
309: requestContext.request.getContextPath() + "/dyna");
310: pageRenderCtx.getProperties().put(
311: DynaConstants.SERVER_BASE_URL,
312: requestContext.request.getContextPath()
313: + requestContext.request.getServletPath());
314:
315: //
316: RendererContext rendererCtx = layout.getRenderContext(
317: themeContext, markupInfo, dispatcher);
318: rendererCtx.render(pageRenderCtx);
319: }
320:
321: /** Necessary for now, until the JSPLayout does not cast the page render context to page result. */
322: private PageResult createResult(PageRendererContext prc) {
323: PageResult result = new PageResult("page");
324:
325: //
326: result.getProperties().putAll(prc.getProperties());
327:
328: //
329: for (Iterator i = prc.getRegions().iterator(); i.hasNext();) {
330: RegionRendererContext rrc = (RegionRendererContext) i
331: .next();
332:
333: //
334: for (IteratorStatus j = new IteratorStatus(rrc.getWindows()
335: .iterator()); j.hasNext();) {
336: WindowRendererContext wrc = (WindowRendererContext) j
337: .next();
338:
339: //
340: WindowResult wr = new WindowResult(wrc.getDecoration()
341: .getTitle(), wrc.getPortlet().getMarkup(),
342: new HashMap(), wrc.getProperties(), "", wrc
343: .getWindowState(), wrc.getMode());
344: WindowContext wc = new WindowContext(wrc.getId(), rrc
345: .getId(), Integer.toString(j.getIndex()), wr);
346: result.addWindowContext(wc);
347: }
348:
349: //
350: Region region = result.getRegion2(rrc.getId());
351: if (region != null) {
352: region.getProperties().putAll(rrc.getProperties());
353: }
354: }
355:
356: //
357: result.setLayoutState(null);
358:
359: //
360: return result;
361: }
362:
363: private class ChangeRecord {
364:
365: /** . */
366: private RenderedObject source;
367:
368: /** . */
369: private ObjectChange change;
370:
371: public ChangeRecord(RenderedObject source, ObjectChange change) {
372: this.source = source;
373: this.change = change;
374: }
375: }
376: }
|