001    // Copyright 2004, 2005 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    
015    package org.apache.tapestry.enhance;
016    
017    import java.lang.reflect.Modifier;
018    
019    import org.apache.hivemind.ApplicationRuntimeException;
020    import org.apache.hivemind.Location;
021    import org.apache.hivemind.service.MethodSignature;
022    import org.apache.hivemind.util.Defense;
023    import org.apache.tapestry.services.InjectedValueProvider;
024    import org.apache.tapestry.spec.InjectSpecification;
025    
026    /**
027     * Implementation for injection type "object" (the default). Adds read-only properties to the
028     * enhanced class that contain objects injected from HiveMind.
029     * 
030     * @author Howard M. Lewis Ship
031     * @since 4.0
032     */
033    public class InjectObjectWorker implements InjectEnhancementWorker
034    {
035        private InjectedValueProvider _provider;
036    
037        public void performEnhancement(EnhancementOperation op, InjectSpecification is)
038        {
039            String name = is.getProperty();
040            String objectReference = is.getObject();
041            Location location = is.getLocation();
042    
043            injectObject(op, objectReference, name, location);
044        }
045    
046        public void injectObject(EnhancementOperation op, String objectReference, String propertyName,
047                Location location)
048        {
049            Defense.notNull(op, "op");
050            Defense.notNull(propertyName, "propertyName");
051            Defense.notNull(objectReference, "objectReference");
052    
053            Class propertyType = op.getPropertyType(propertyName);
054            if (propertyType == null)
055                propertyType = Object.class;
056    
057            op.claimReadonlyProperty(propertyName);
058    
059            Object injectedValue = _provider.obtainValue(objectReference, location);
060    
061            if (injectedValue == null)
062                throw new ApplicationRuntimeException(EnhanceMessages
063                        .locatedValueIsNull(objectReference), location, null);
064    
065            if (!propertyType.isAssignableFrom(injectedValue.getClass()))
066                throw new ApplicationRuntimeException(EnhanceMessages.incompatibleInjectType(
067                        objectReference,
068                        injectedValue,
069                        propertyType), location, null);
070    
071            String fieldName = op.addInjectedField("_$" + propertyName, propertyType, injectedValue);
072    
073            String methodName = EnhanceUtils.createAccessorMethodName(propertyName);
074    
075            op.addMethod(
076                    Modifier.PUBLIC,
077                    new MethodSignature(propertyType, methodName, null, null),
078                    "return " + fieldName + ";", location);
079        }
080    
081        public void setProvider(InjectedValueProvider provider)
082        {
083            _provider = provider;
084        }
085    }