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.ApplicationRuntimeException;
020import org.apache.hivemind.Location;
021import org.apache.hivemind.service.BodyBuilder;
022import org.apache.hivemind.service.MethodSignature;
023import org.apache.hivemind.util.Defense;
024import org.apache.tapestry.engine.state.ApplicationStateManager;
025import org.apache.tapestry.spec.InjectSpecification;
026
027/**
028 * Injects a boolean property that indicates if a particular application state object already
029 * exists. This is useful in situations where you are trying to prevent the creation of the ASO (and
030 * thus, prevent the creation of the HttpSession).
031 * 
032 * @author Howard M. Lewis Ship
033 * @since 4.0
034 */
035public class InjectStateFlagWorker implements InjectEnhancementWorker
036{
037    private ApplicationStateManager _applicationStateManager;
038
039    public void performEnhancement(EnhancementOperation op, InjectSpecification spec)
040    {
041        injectStateFlag(op, spec.getObject(), spec.getProperty(), spec.getLocation());
042    }
043
044    void injectStateFlag(EnhancementOperation op, String objectName, String propertyName,
045            Location location)
046    {
047        Defense.notNull(op, "op");
048        Defense.notNull(objectName, "objectName");
049        Defense.notNull(propertyName, "propertyName");
050
051        Class propertyType = op.getPropertyType(propertyName);
052
053        // null means no property at all; it's just in the XML
054        // which is ok. Otherwise, make sure it is exactly boolean.
055
056        if (propertyType != null && propertyType != boolean.class)
057            throw new ApplicationRuntimeException(EnhanceMessages.mustBeBoolean(propertyName),
058                    location, null);
059
060        op.claimReadonlyProperty(propertyName);
061
062        String managerField = op.addInjectedField(
063                "_$applicationStateManager",
064                ApplicationStateManager.class,
065                _applicationStateManager);
066
067        BodyBuilder builder = new BodyBuilder();
068        builder.begin();
069        builder.add("return {0}.exists(", managerField);
070        builder.addQuoted(objectName);
071        builder.addln(");");
072        builder.end();
073
074        String methodName = op.getAccessorMethodName(propertyName);
075
076        MethodSignature sig = new MethodSignature(boolean.class, methodName, null, null);
077
078        op.addMethod(Modifier.PUBLIC, sig, builder.toString(), location);
079    }
080
081    public void setApplicationStateManager(ApplicationStateManager applicationStateManager)
082    {
083        _applicationStateManager = applicationStateManager;
084    }
085
086}