001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.internal.bindings; 014 015import org.apache.tapestry5.Binding; 016import org.apache.tapestry5.ComponentResources; 017import org.apache.tapestry5.beanmodel.PropertyConduit; 018import org.apache.tapestry5.beanmodel.services.PropertyConduitSource; 019import org.apache.tapestry5.commons.Location; 020import org.apache.tapestry5.commons.internal.services.StringInterner; 021import org.apache.tapestry5.commons.internal.util.TapestryException; 022import org.apache.tapestry5.services.BindingFactory; 023import org.apache.tapestry5.services.pageload.PageClassLoaderContext; 024import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager; 025 026/** 027 * Binding factory for reading and updating JavaBean properties. 028 * 029 * Expression are evaluated via a {@link PropertyConduit}, which is generated by {@link PropertyConduitSource} (which 030 * therefore defines the expression language). 031 */ 032public class PropBindingFactory implements BindingFactory 033{ 034 private final PropertyConduitSource source; 035 036 private final StringInterner interner; 037 038 private final PageClassLoaderContextManager pageClassLoaderContextManager; 039 040 public PropBindingFactory(PropertyConduitSource propertyConduitSource, StringInterner interner, 041 PageClassLoaderContextManager pageClassLoaderContextManager) 042 { 043 source = propertyConduitSource; 044 this.interner = interner; 045 this.pageClassLoaderContextManager = pageClassLoaderContextManager; 046 } 047 048 public Binding newBinding(String description, ComponentResources container, 049 ComponentResources component, String expression, Location location) 050 { 051 052 Object target = container.getComponent(); 053 Class targetClass = target.getClass(); 054 targetClass = getClassLoaderAppropriateClass(targetClass); 055 056 PropertyConduit conduit = source.create(targetClass, expression); 057 058 String toString = interner.format("PropBinding[%s %s(%s)]", description, container 059 .getCompleteId(), expression); 060 061 return new PropBinding(location, target, conduit, expression, toString); 062 } 063 064 private Class getClassLoaderAppropriateClass(Class targetClass) 065 { 066 final String className = targetClass.getName(); 067 try 068 { 069 final PageClassLoaderContext context = pageClassLoaderContextManager.get(className); 070 targetClass = context.getProxyFactory() 071 .getClassLoader().loadClass(className); 072 } catch (ClassNotFoundException e) 073 { 074 throw new TapestryException(e.getMessage(), e); 075 } 076 return targetClass; 077 } 078}