/* AuDynaMediar.java
Purpose:
Description:
History:
Fri Jan 11 19:14:17 2008, Created by tomyeh
Copyright (C) 2008 Potix Corporation. All Rights Reserved.
{{IS_RIGHT
This program is distributed under LGPL Version 2.1 in the hope that
it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
package org.zkoss.zk.au.http;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.lang.Exceptions;
import org.zkoss.mesg.Messages;
import org.zkoss.util.media.Media;
import org.zkoss.web.servlet.http.Https;
import org.zkoss.zk.mesg.MZk;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.ComponentNotFoundException;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.WebApp;
import org.zkoss.zk.ui.ext.render.DynamicMedia;
import org.zkoss.zk.ui.http.ExecutionImpl;
import org.zkoss.zk.ui.sys.ComponentCtrl;
import org.zkoss.zk.ui.sys.DesktopCtrl;
import org.zkoss.zk.ui.sys.UiEngine;
import org.zkoss.zk.ui.sys.WebAppCtrl;
import org.zkoss.zk.ui.util.Configuration;
/**
* The AU processor used to response the content for {@link DynamicMedia#getMedia}
*
* @author tomyeh
* @since 3.0.2
*/
public class AuDynaMediar implements AuExtension {
private static final Logger log = LoggerFactory.getLogger(AuDynaMediar.class);
private ServletContext _ctx;
public AuDynaMediar() {
}
public void init(DHtmlUpdateServlet servlet) {
_ctx = servlet.getServletContext();
}
public void destroy() {
}
/** Retrieves the media from {@link DynamicMedia#getMedia}.
*/
public void service(HttpServletRequest request, HttpServletResponse response, String pi)
throws ServletException, IOException {
// if (log.isDebugEnabled()) log.debug("View "+pi);
final Session sess = Sessions.getCurrent(false);
if (sess == null) {
response.sendError(HttpServletResponse.SC_GONE, Messages.get(MZk.PAGE_NOT_FOUND, pi));
return;
}
int j = pi.indexOf('/', 1) + 1;
int k = pi.indexOf('/', j);
if (j <= 0 || k <= 0)
throw new ServletException("Wrong path info: " + pi);
final String dtid = pi.substring(j, k);
final int l = pi.indexOf('/', ++k);
final String uuid = l >= 0 ? pi.substring(k, l) : pi.substring(k);
Media media;
boolean download = false;
try {
final WebApp wapp = sess.getWebApp();
final WebAppCtrl wappc = (WebAppCtrl) wapp;
final UiEngine uieng = wappc.getUiEngine();
final Desktop desktop = wappc.getDesktopCache(sess).getDesktop(dtid);
final DesktopCtrl desktopCtrl = (DesktopCtrl) desktop;
final Execution oldexec = Executions.getCurrent();
final Execution exec = new ExecutionImpl(_ctx, request, response, desktop, null);
uieng.activate(exec);
final Configuration config = wapp.getConfiguration();
boolean err = false;
try {
config.invokeExecutionInits(exec, oldexec);
desktopCtrl.invokeExecutionInits(exec, oldexec);
media = desktopCtrl.getDownloadMedia(uuid, false);
if (media != null) {
download = true; //yes, it is for download
} else {
final Component comp = desktop.getComponentByUuidIfAny(uuid);
if (comp == null) { // B65-ZK-1599
response.sendError(HttpServletResponse.SC_GONE,
Messages.get(MZk.PAGE_NOT_FOUND, pi + " - " + uuid));
log.debug("Failed to load media, " + pi);
return;
}
final Object cc = ((ComponentCtrl) comp).getExtraCtrl();
if (!(cc instanceof DynamicMedia))
throw new ServletException(
DynamicMedia.class + " must be implemented by getExtraCtrl() of " + comp);
int m = l >= 0 ? pi.indexOf('/', l + 1) : -1;
if (m < 0)
m = l;
media = ((DynamicMedia) cc).getMedia(m >= 0 ? pi.substring(m) : "");
if (media == null) {
response.sendError(HttpServletResponse.SC_GONE,
Messages.get(MZk.PAGE_NOT_FOUND, pi + " - " + comp));
return;
}
}
} catch (Throwable ex) {
err = true;
final List<Throwable> errs = new LinkedList<Throwable>();
errs.add(ex);
desktopCtrl.invokeExecutionCleanups(exec, oldexec, errs);
config.invokeExecutionCleanups(exec, oldexec, errs);
final StringBuffer errmsg = new StringBuffer(100);
if (!errs.isEmpty()) {
for (Iterator it = errs.iterator(); it.hasNext();) {
final Throwable t = (Throwable) it.next();
log.error("Failed to load media, " + pi, t);
errmsg.append('\n').append(Exceptions.getMessage(t));
}
}
response.sendError(HttpServletResponse.SC_GONE,
Messages.get(MZk.PAGE_FAILED, new Object[] { pi, errmsg, "" }));
return;
} finally {
if (!err) {
desktopCtrl.invokeExecutionCleanups(exec, oldexec, null);
config.invokeExecutionCleanups(exec, oldexec, null);
}
uieng.deactivate(exec);
}
} catch (ComponentNotFoundException ex) {
//possible because view might be as late as origin comp is gone
response.sendError(HttpServletResponse.SC_GONE, Messages.get(MZk.UPDATE_OBSOLETE_PAGE, uuid));
return;
}
Https.write(request, response, media, download, false);
//see bug 2691017 for why not repeatable
//FUTURE: support last-modified
}
}