    001// Copyright 2009, 2010, 2011 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.tapestry5.internal.transform;
    016
    017import org.apache.tapestry5.annotations.SessionAttribute;
    018import org.apache.tapestry5.http.services.Request;
    019import org.apache.tapestry5.http.services.Session;
    020import org.apache.tapestry5.model.MutableComponentModel;
    021import org.apache.tapestry5.plastic.FieldConduit;
    022import org.apache.tapestry5.plastic.InstanceContext;
    023import org.apache.tapestry5.plastic.PlasticClass;
    024import org.apache.tapestry5.plastic.PlasticField;
    025import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
    026import org.apache.tapestry5.services.transform.TransformationSupport;
    027
    028/**
    029 * Looks for the {@link SessionAttribute} annotation and converts read and write access on such
    030 * fields into calls to the {@link Session#getAttribute(String)} and {@link Session#setAttribute(String, Object)}.
    031 */
    032public class SessionAttributeWorker implements ComponentClassTransformWorker2
    033{
    034    private final Request request;
    035
    036    private class SessionKeyConduit implements FieldConduit<Object>
    037    {
    038        private final String key;
    039
    040        public SessionKeyConduit(String key)
    041        {
    042            this.key = key;
    043        }
    044
    045        public Object get(Object instance, InstanceContext context)
    046        {
    047            Session session = getSession();
    048
    049            if (session == null)
    050            {
    051                return null;
    052            }
    053
    054            return session.getAttribute(key);
    055        }
    056
    057        public void set(Object instance, InstanceContext context, Object newValue)
    058        {
    059            request.getSession(true).setAttribute(key, newValue);
    060        }
    061
    062        private Session getSession()
    063        {
    064            return request.getSession(false);
    065        }
    066    }
    067
    068    public SessionAttributeWorker(Request request)
    069    {
    070        this.request = request;
    071    }
    072
    073
    074    public void transform(PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model)
    075    {
    076        for (PlasticField field : plasticClass.getFieldsWithAnnotation(SessionAttribute.class))
    077        {
    078            convertFieldToSessionAccess(field);
    079        }
    080    }
    081
    082    private void convertFieldToSessionAccess(PlasticField field)
    083    {
    084        SessionAttribute annotation = field.getAnnotation(SessionAttribute.class);
    085
    086        field.claim(annotation);
    087
    088        String key = determineSessionKey(field, annotation.value());
    089
    090        field.setConduit(new SessionKeyConduit(key));
    091    }
    092
    093    private String determineSessionKey(PlasticField field, String value)
    094    {
    095        return value.equals("") ? field.getName() : value;
    096    }
    097}