001    // Copyright 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.Location;
020    import org.apache.hivemind.Resource;
021    import org.apache.hivemind.service.MethodSignature;
022    import org.apache.hivemind.util.Defense;
023    import org.apache.tapestry.IScript;
024    import org.apache.tapestry.engine.IScriptSource;
025    import org.apache.tapestry.spec.InjectSpecification;
026    
027    /**
028     * Injects {@link org.apache.tapestry.IScript} instances directly into pages or components.
029     * 
030     * @author Howard M. Lewis Ship
031     * @since 4.0
032     */
033    public class InjectScriptWorker implements InjectEnhancementWorker
034    {
035        private IScriptSource _source;
036    
037        public void performEnhancement(EnhancementOperation op, InjectSpecification spec)
038        {
039            String propertyName = spec.getProperty();
040            String scriptName = spec.getObject();
041            Location location = spec.getLocation();
042    
043            injectScript(op, propertyName, scriptName, location);
044        }
045    
046        /**
047         * Injects a compiled script.
048         * 
049         * @param op
050         *            the enhancement operation
051         * @param propertyName
052         *            the name of the property to inject
053         * @param scriptName
054         *            the name of the script (relative to the location)
055         * @param location
056         *            the location of the specification; primarily used as the base location for finding
057         *            the script.
058         */
059    
060        public void injectScript(EnhancementOperation op, String propertyName, String scriptName,
061                Location location)
062        {
063            Defense.notNull(op, "op");
064            Defense.notNull(propertyName, "propertyName");
065            Defense.notNull(scriptName, "scriptName");
066            Defense.notNull(location, "location");
067    
068            op.claimReadonlyProperty(propertyName);
069    
070            Class propertyType = EnhanceUtils.verifyPropertyType(op, propertyName, IScript.class);
071    
072            // PropertyType will likely be either java.lang.Object or IScript
073    
074            String methodName = op.getAccessorMethodName(propertyName);
075    
076            Resource resource = location.getResource().getRelativeResource(scriptName);
077    
078            DeferredScript script = new DeferredScriptImpl(resource, _source, location);
079    
080            String fieldName = op.addInjectedField("_$script", DeferredScript.class, script);
081    
082            MethodSignature sig = new MethodSignature(propertyType, methodName, null, null);
083    
084            op.addMethod(Modifier.PUBLIC, sig, "return " + fieldName + ".getScript();", location);
085        }
086    
087        public void setSource(IScriptSource source)
088        {
089            _source = source;
090        }
091    }