/*
* Copyright 2004 The Apache Software Foundation.
*
* 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.
*
* $Header:$
*/
package org.apache.beehive.netui.pageflow.internal;
import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
import org.apache.beehive.netui.pageflow.FacesBackingBean;
import org.apache.beehive.netui.pageflow.PageFlowUtils;
import org.apache.beehive.netui.pageflow.handler.Handlers;
import org.apache.beehive.netui.util.internal.FileUtils;
import org.apache.beehive.netui.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletContext;
public class FacesBackingBeanFactory
implements InternalConstants
{
private static final Logger _log = Logger.getInstance( FacesBackingBeanFactory.class );
public static FacesBackingBean getFacesBackingBeanForRequest( HttpServletRequest request,
HttpServletResponse response,
ServletContext servletContext )
{
String uri = InternalUtils.getDecodedServletPath( request );
assert uri.charAt( 0 ) == '/' : uri;
String backingClassName = FileUtils.stripFileExtension( uri.substring( 1 ).replace( '/', '.' ) );
FacesBackingBean currentBean = InternalUtils.getFacesBackingBean( request );
//
// If there is no current backing bean, or if the current one doesn't match the desired classname, create one.
//
if ( currentBean == null || ! currentBean.getClass().getName().equals( backingClassName ) )
{
FacesBackingBean bean = null;
if ( FileUtils.uriEndsWith( uri, FACES_EXTENSION ) || FileUtils.uriEndsWith( uri, JSF_EXTENSION ) )
{
bean = loadFacesBackingBean( request, servletContext, backingClassName );
//
// If we didn't create (or failed to create) a backing bean, and if this is a JSF request, then create
// a default one. This ensures that there will be a place for things like page inputs, that get stored
// in the backing bean across postbacks to the same JSF.
//
if ( bean == null ) bean = new DefaultFacesBackingBean();
//
// If we created a backing bean, invoke its create callback, and tell it to store itself in the session.
//
if ( bean != null )
{
try
{
bean.create( request, response, servletContext );
}
catch ( Exception e )
{
_log.error( "Error while creating backing bean instance of " + backingClassName, e );
}
bean.persistInSession( request, response );
return bean;
}
}
//
// We didn't create a backing bean. If there's one in the session (an inappropriate one), remove it.
//
HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
ScopedServletUtils.removeScopedSessionAttr( FACES_BACKING_ATTR, unwrappedRequest );
}
else if ( currentBean != null )
{
if ( _log.isDebugEnabled() )
{
_log.debug( "Using existing backing bean instance " + currentBean + " for request " +
request.getRequestURI() );
}
currentBean.reinitialize( request, response, servletContext );
}
return currentBean;
}
private static FacesBackingBean loadFacesBackingBean( HttpServletRequest request, ServletContext servletContext,
String backingClassName )
{
try
{
Class backingClass =
Handlers.get( servletContext ).getReloadableClassHandler().loadCachedClass( backingClassName );
if ( backingClass == null )
{
if ( _log.isTraceEnabled() )
{
_log.trace( "No backing bean class " + backingClassName + " found for request "
+ request.getRequestURI() );
}
}
else
{
AnnotationReader annReader = AnnotationReader.getAnnotationReader( backingClass, servletContext );
if ( annReader.getJpfAnnotation( backingClass, "FacesBacking" ) != null )
{
if ( _log.isDebugEnabled() )
{
_log.debug( "Found backing class " + backingClassName + " for request "
+ request.getRequestURI() + "; creating a new instance." );
}
return ( FacesBackingBean ) backingClass.newInstance();
}
else
{
if ( _log.isDebugEnabled() )
{
_log.debug( "Found matching backing class " + backingClassName + " for request "
+ request.getRequestURI() + ", but it does not have the "
+ ANNOTATION_QUALIFIER + "FacesBacking" + " annotation." );
}
}
}
}
catch ( InstantiationException e )
{
_log.error( "Could not create backing bean instance of " + backingClassName, e );
}
catch ( IllegalAccessException e )
{
_log.error( "Could not create backing bean instance of " + backingClassName, e );
}
return null;
}
private static class DefaultFacesBackingBean
extends FacesBackingBean
{
}
}