/*
* © Copyright IBM Corp. 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.xsp.sbtsdk.runtime;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ibm.commons.runtime.Application;
import com.ibm.commons.runtime.Context;
import com.ibm.commons.runtime.RuntimeFactory;
import com.ibm.commons.runtime.impl.servlet.RuntimeFactoryServlet;
import com.ibm.commons.util.NotImplementedException;
import com.ibm.domino.xsp.module.nsf.NotesContext;
import com.ibm.xsp.application.ApplicationEx;
import com.ibm.xsp.application.events.ApplicationListener;
import com.ibm.xsp.context.FacesContextEx;
import com.ibm.xsp.event.FacesContextListener;
/**
* Runtime factory implementation for an XPages environment.
*
* We assume that we are running within an XPages application.
* In this case, the JSf application must be created for the NSFComponentModule.
*
*
*
*
* @author Philippe Riand
*/
public class XspRuntimeFactory extends RuntimeFactoryServlet {
private static XspRuntimeFactory instance = new XspRuntimeFactory();
public static final RuntimeFactory get() {
return instance;
}
protected ClassLoader getContextClassLoader() {
// Get it from the faces context, if available
FacesContextEx ctx = FacesContextEx.getCurrentInstance();
if(ctx!=null) {
return ctx.getContextClassLoader();
}
// Else, execute this is a privileged block
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
}
public XspApplication getApplicationUnchecked() {
XspApplication app = (XspApplication)super.getApplicationUnchecked();
if(app==null) {
// There is no application created
// This might be because we are in a faces request, and no call to the SBT library had been made so far
// In this case, we create the application object and we destroy it when the XPages application is destroyed
FacesContextEx facesContext = FacesContextEx.getCurrentInstance();
if(facesContext!=null) {
final XspApplication newApp = app = (XspApplication)initApplication(facesContext.getExternalContext().getContext());
ApplicationEx facesApplication = facesContext.getApplicationEx();
facesApplication.addApplicationListener(new ApplicationListener() {
public void applicationDestroyed(ApplicationEx application) {
}
public void applicationCreated(ApplicationEx application) {
destroyApplication(newApp);
}
});
}
}
return app;
}
@Override
public Application createApplication(Object context) {
ApplicationEx facesApplication = ApplicationEx.getInstance();
// Try to find the application name
// We start from the the NotesContext, which should be defined
String name = null;
NotesContext ctx = NotesContext.getCurrentUnchecked();
if(ctx!=null) {
name = ctx.getModule().getModuleName();
} else {
name = facesApplication.getApplicationId();
}
return new XspApplication(facesApplication,(ServletContext)context,name);
}
public XspContext getContextUnchecked() {
XspContext ctx = (XspContext)super.getContextUnchecked();
if(ctx==null) {
FacesContextEx facesContext = FacesContextEx.getCurrentInstance();
if(facesContext!=null) {
Application app = getApplicationUnchecked();
// We initialize a temporary context
ExternalContext extCtx = facesContext.getExternalContext();
final XspContext newContext = ctx = (XspContext)initContext(app, extCtx.getRequest(), extCtx.getResponse());
// we should clear the context when the JSF context is discarded
facesContext.addRequestListener(new FacesContextListener() {
public void beforeRenderingPhase(FacesContext facesContext) {
}
public void beforeContextReleased(FacesContext facesContext) {
destroyContext(newContext);
}
});
}
}
return ctx;
}
@Override
public Context createContext(Application application, Object request, Object response) {
boolean deleteFacesContext = false;
// FacesContext must had been created by initContext(), when not in a faces request
FacesContextEx facesContext = FacesContextEx.getCurrentInstance();
if(facesContext==null) {
// We create a temporary context
facesContext = createFacesContext(application, request, response);
deleteFacesContext = true;
}
return new XspContext(application,facesContext,(HttpServletRequest)request,(HttpServletResponse)response,deleteFacesContext);
}
//
// Fake FacesContext for non faces requests
//
protected FacesContextEx createFacesContext(Application application, Object servletRequest, Object servletResponse) {
ServletContext servletContext = (ServletContext)application.getApplicationContext();
HttpServletRequest request=(HttpServletRequest)servletRequest;
HttpServletResponse response=(HttpServletResponse)servletResponse;
// Create a temporary FacesContext and make it available
FacesContextFactory contextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
FacesContextEx context = (FacesContextEx)contextFactory.getFacesContext(servletContext, request, response, dummyLifeCycle);
return context;
}
protected void releaseContext(FacesContext context) {
context.release();
}
// The FacesContext factory requires a lifecycle parameter which is not used, but when not present, it generates
// a NullPointerException. Silly thing! So we create an empty one that does nothing...
private static Lifecycle dummyLifeCycle = new Lifecycle() {
@Override
public void render(FacesContext context) throws FacesException {
throw new NotImplementedException();
}
@Override
public void removePhaseListener(PhaseListener listener) {
throw new NotImplementedException();
}
@Override
public PhaseListener[] getPhaseListeners() {
throw new NotImplementedException();
}
@Override
public void execute(FacesContext context) throws FacesException {
throw new NotImplementedException();
}
@Override
public void addPhaseListener(PhaseListener listener) {
throw new NotImplementedException();
}
};
}