001// Copyright 2009 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.internal.services;
016
017import java.util.Set;
018
019import org.apache.tapestry5.SymbolConstants;
020import org.apache.tapestry5.internal.services.ComponentDependencyRegistry.DependencyType;
021import org.apache.tapestry5.ioc.annotations.Symbol;
022import org.apache.tapestry5.model.ComponentModel;
023import org.apache.tapestry5.services.ComponentClassResolver;
024
025public class ComponentModelSourceImpl implements ComponentModelSource
026{
027    private final ComponentClassResolver resolver;
028
029    private final ComponentInstantiatorSource source;
030    
031    private final ComponentDependencyRegistry componentDependencyRegistry;
032    
033    private final PageSource pageSource;
034    
035    private final boolean multipleClassLoaders;
036
037    public ComponentModelSourceImpl(ComponentClassResolver resolver, ComponentInstantiatorSource source,
038            ComponentDependencyRegistry componentDependencyRegistry,
039            PageSource pageSource,
040            @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode,
041            @Symbol(SymbolConstants.MULTIPLE_CLASSLOADERS) boolean multipleClassLoaders)
042    {
043        this.resolver = resolver;
044        this.source = source;
045        this.componentDependencyRegistry = componentDependencyRegistry;
046        this.pageSource = pageSource;
047        this.multipleClassLoaders = !productionMode && multipleClassLoaders;
048    }
049
050    public ComponentModel getModel(String componentClassName)
051    {
052        if (multipleClassLoaders && isPage(componentClassName))
053        {
054            
055            final Set<String> superclasses = componentDependencyRegistry.getDependencies(
056                    componentClassName, DependencyType.SUPERCLASS);
057            
058            if (!superclasses.isEmpty())
059            {
060                final String superclass = superclasses.iterator().next();
061                if (isPage(superclass))
062                {
063                    getModel(superclass);
064                    try
065                    {
066                        pageSource.getPage(resolver.getLogicalName(componentClassName));
067                    }
068                    catch (IllegalStateException e)
069                    {
070                        // This can be thrown in PageSourceImpl in case an
071                        // infinite method call recursion is detected. In
072                        // that case, the page instance is already created,
073                        // so the objective of the line above is already
074                        // fulfilled and we can safely ignore the exception
075                    }
076                }
077            }
078        }
079        return source.getInstantiator(componentClassName).getModel();
080    }
081
082    public ComponentModel getPageModel(String pageName)
083    {
084        return getModel(resolver.resolvePageNameToClassName(pageName));
085    }
086    
087    private boolean isPage(String componentClassName)
088    {
089        return componentClassName.contains(".pages.");
090    }
091}