/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.orchestra.conversation.spring;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectFactory;

/**
 * Used with a "scoping proxy" object as generated by _SpringUtils.newProxy.
 * <p>
 * When user code invokes any method on the proxy, it invokes getTarget on its
 * source object to get the "real" object, then invokes the same method on the
 * returned object. 
 * <p>
 * Here the getTarget method is implemented by using an AbstractSpringOrchestraScope
 * object to look up the ConversationContext for the user, then a particular
 * Conversation instance (by name), then a bean within that Conversation.
 * <p>
 * TODO: deal with serialization issues here. When an http session containing
 * conversation-scoped beans is serialized, instances of this type will of course
 * be serialized too. But the "scope" and "objectFactory" members here are not
 * serializable. Somehow instances of this class need enough information to
 * relocate the appropriate objects on deserialization.
 * 
 * @since 1.1
 */
public class ScopedBeanTargetSource extends AbstractBeanFactoryBasedTargetSource
{
    private AbstractSpringOrchestraScope scope;
    private String conversationName;
    private String targetBeanName;
    private ObjectFactory objectFactory;

    public ScopedBeanTargetSource(
            AbstractSpringOrchestraScope scope, 
            String conversationName,
            String targetBeanName,
            ObjectFactory objectFactory,
            BeanFactory beanFactory)
    {
        this.scope = scope;
        this.conversationName = conversationName;
        this.targetBeanName = targetBeanName;
        this.objectFactory = objectFactory;
        
        super.setTargetBeanName(targetBeanName);
        super.setBeanFactory(beanFactory);
    }

    public Object getTarget() throws Exception
    {
        final Log log = LogFactory.getLog(ScopedBeanTargetSource.class);
        log.debug("getRealBean for " + targetBeanName);
        return scope.getRealBean(conversationName, targetBeanName, objectFactory);
    }
}
