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
015package org.apache.tapestry.enhance;
016
017import java.lang.reflect.Modifier;
018
019import org.apache.hivemind.Location;
020import org.apache.hivemind.Resource;
021import org.apache.hivemind.service.MethodSignature;
022import org.apache.hivemind.util.Defense;
023import org.apache.tapestry.IScript;
024import org.apache.tapestry.engine.IScriptSource;
025import 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 */
033public 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}