You'll need to implement your own version of javax.faces.ViewHandler which does what you need. Then, you register your own view handler in faces-config.xml.
Here's a simple abstract ViewHandler you can extend and then implement the 3 abstract methods for. The abstract methods you override here are where you'll do your conversions to/from URI to physical paths on the file system. This information is just passed right along to the default ViewHandler for JSF to deal with in the usual way. For example, you could override these methods to add and remove the file extension of an incoming view id (like in your example), for extension-less view URIs.
import java.io.IOException;
import java.util.Locale;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A facade view handler which maps URIs into actual physical views that the
* underlying implementation can deal with regularly.
* Therefore, all internal references to view ids, for example in faces-config,
* will use the path to the physical files. Everything publicized, however, will
* see a "converted" / facade url.
*/
public abstract class SimpleConverterViewHandler extends ViewHandler {
private static final Log LOG = LogFactory.getLog(SimpleConverterViewHandler.class);
private final ViewHandler base;
public SimpleConverterViewHandler(ViewHandler base) {
this.base = base;
}
/**
* Distinguishes a URI from a physical file view.
* Tests if a view id is in the expected format -- the format corresponding
* to the physical file views, as opposed to the URIs.
* This test is necessary because JSF takes the view ID from the
* faces-config navigation, and calls renderView() on it, etc.
*/
public abstract boolean isViewFormat(FacesContext context, String viewId);
/**
* Convert a private file path (view id) into a public URI.
*/
public abstract String convertViewToURI(FacesContext context, String viewId);
/**
* Convert a public URI into a private file path (view id)
* note: uri always starts with "/";
*/
public abstract String convertURIToView(FacesContext context, String uri);
public String getActionURL(FacesContext context, String viewId) {
// NOTE: this is used for FORM actions.
String newViewId = convertViewToURI(context, viewId);
LOG.debug("getViewIdPath: " + viewId + "->" + newViewId);
return base.getActionURL(context, newViewId);
}
private String doConvertURIToView(FacesContext context, String reuestURI) {
if (isViewFormat(context, reuestURI)) {
return reuestURI;
} else {
return convertURIToView(context, reuestURI);
}
}
public void renderView(FacesContext context, UIViewRoot viewToRender)
throws IOException, FacesException {
if (null == context || null == viewToRender)
throw new NullPointerException("null context or view");
String reuestURI = viewToRender.getViewId();
String newViewId = doConvertURIToView(context, reuestURI);
LOG.debug("renderView: " + reuestURI + "->" + newViewId);
viewToRender.setViewId(newViewId);
base.renderView(context, viewToRender);
}
public UIViewRoot restoreView(FacesContext context, String viewId) {
String newViewId = doConvertURIToView(context, viewId);
LOG.debug("restoreView: " + viewId + "->" + newViewId);
return base.restoreView(context, newViewId);
}
public Locale calculateLocale(FacesContext arg0) {
return base.calculateLocale(arg0);
}
public String calculateRenderKitId(FacesContext arg0) {
return base.calculateRenderKitId(arg0);
}
public UIViewRoot createView(FacesContext arg0, String arg1) {
return base.createView(arg0, arg1);
}
public String getResourceURL(FacesContext arg0, String arg1) {
return base.getResourceURL(arg0, arg1);
}
public void writeState(FacesContext arg0) throws IOException {
base.writeState(arg0);
}
}
Here's a simple abstract ViewHandler you can extend and then implement the 3 abstract methods for. The abstract methods you override here are where you'll do your conversions to/from URI to physical paths on the file system. This information is just passed right along to the default ViewHandler for JSF to deal with in the usual way. For example, you could override these methods to add and remove the file extension of an incoming view id (like in your example), for extension-less view URIs.
import java.io.IOException;
import java.util.Locale;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A facade view handler which maps URIs into actual physical views that the
* underlying implementation can deal with regularly.
* Therefore, all internal references to view ids, for example in faces-config,
* will use the path to the physical files. Everything publicized, however, will
* see a "converted" / facade url.
*/
public abstract class SimpleConverterViewHandler extends ViewHandler {
private static final Log LOG = LogFactory.getLog(SimpleConverterViewHandler.class);
private final ViewHandler base;
public SimpleConverterViewHandler(ViewHandler base) {
this.base = base;
}
/**
* Distinguishes a URI from a physical file view.
* Tests if a view id is in the expected format -- the format corresponding
* to the physical file views, as opposed to the URIs.
* This test is necessary because JSF takes the view ID from the
* faces-config navigation, and calls renderView() on it, etc.
*/
public abstract boolean isViewFormat(FacesContext context, String viewId);
/**
* Convert a private file path (view id) into a public URI.
*/
public abstract String convertViewToURI(FacesContext context, String viewId);
/**
* Convert a public URI into a private file path (view id)
* note: uri always starts with "/";
*/
public abstract String convertURIToView(FacesContext context, String uri);
public String getActionURL(FacesContext context, String viewId) {
// NOTE: this is used for FORM actions.
String newViewId = convertViewToURI(context, viewId);
LOG.debug("getViewIdPath: " + viewId + "->" + newViewId);
return base.getActionURL(context, newViewId);
}
private String doConvertURIToView(FacesContext context, String reuestURI) {
if (isViewFormat(context, reuestURI)) {
return reuestURI;
} else {
return convertURIToView(context, reuestURI);
}
}
public void renderView(FacesContext context, UIViewRoot viewToRender)
throws IOException, FacesException {
if (null == context || null == viewToRender)
throw new NullPointerException("null context or view");
String reuestURI = viewToRender.getViewId();
String newViewId = doConvertURIToView(context, reuestURI);
LOG.debug("renderView: " + reuestURI + "->" + newViewId);
viewToRender.setViewId(newViewId);
base.renderView(context, viewToRender);
}
public UIViewRoot restoreView(FacesContext context, String viewId) {
String newViewId = doConvertURIToView(context, viewId);
LOG.debug("restoreView: " + viewId + "->" + newViewId);
return base.restoreView(context, newViewId);
}
public Locale calculateLocale(FacesContext arg0) {
return base.calculateLocale(arg0);
}
public String calculateRenderKitId(FacesContext arg0) {
return base.calculateRenderKitId(arg0);
}
public UIViewRoot createView(FacesContext arg0, String arg1) {
return base.createView(arg0, arg1);
}
public String getResourceURL(FacesContext arg0, String arg1) {
return base.getResourceURL(arg0, arg1);
}
public void writeState(FacesContext arg0) throws IOException {
base.writeState(arg0);
}
}
No comments:
Post a Comment