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