    001// Copyright 2007 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.ioc.internal;
    016
    017import org.apache.tapestry5.ioc.def.ServiceDef;
    018import org.apache.tapestry5.ioc.services.ServiceActivity;
    019import org.apache.tapestry5.ioc.services.ServiceActivityScoreboard;
    020import org.apache.tapestry5.ioc.services.Status;
    021
    022import java.util.List;
    023import java.util.Map;
    024import java.util.Set;
    025import java.util.TreeMap;
    026
    027import org.apache.tapestry5.commons.util.CollectionFactory;
    028import org.apache.tapestry5.ioc.ScopeConstants;
    029import org.apache.tapestry5.ioc.services.PerThreadValue;
    030import org.apache.tapestry5.ioc.services.PerthreadManager;
    031
    032public class ServiceActivityTrackerImpl implements ServiceActivityScoreboard,
    033        ServiceActivityTracker
    034{
    035    public static class MutableServiceActivity implements ServiceActivity
    036    {
    037        private final ServiceDef serviceDef;
    038
    039        private Status status;
    040
    041        private final PerThreadValue<Status> perThreadStatus;
    042
    043        public MutableServiceActivity(ServiceDef serviceDef, PerthreadManager perthreadManager, Status status)
    044        {
    045            this.serviceDef = serviceDef;
    046            if (serviceDef.getServiceScope().equals(ScopeConstants.PERTHREAD)) {
    047                perThreadStatus = perthreadManager.createValue();
    048                perThreadStatus.set(status);
    049                this.status = status; // this is now the default status
    050            } else {
    051                perThreadStatus = null;
    052                this.status = status;
    053            }
    054        }
    055
    056        @Override
    057        public String getServiceId()
    058        {
    059            return serviceDef.getServiceId();
    060        }
    061
    062        @Override
    063        public Class getServiceInterface()
    064        {
    065            return serviceDef.getServiceInterface();
    066        }
    067
    068        @Override
    069        public String getScope()
    070        {
    071            return serviceDef.getServiceScope();
    072        }
    073
    074        @Override
    075        public Set<Class> getMarkers()
    076        {
    077            return serviceDef.getMarkers();
    078        }
    079
    080        // Mutable properties must be synchronized
    081
    082        @Override
    083        public synchronized Status getStatus()
    084        {
    085            if (perThreadStatus != null) {
    086                if (!perThreadStatus.exists()) perThreadStatus.set(status);
    087                return perThreadStatus.get();
    088            }
    089            else return status;
    090        }
    091
    092        synchronized void setStatus(Status status)
    093        {
    094            if (perThreadStatus != null) perThreadStatus.set(status);
    095            else this.status = status;
    096        }
    097    }
    098
    099    private final PerthreadManager perthreadManager;
    100
    101    public ServiceActivityTrackerImpl(PerthreadManager perthreadManager) {
    102        this.perthreadManager = perthreadManager;
    103    }
    104
    105    /**
    106     * Tree map keeps everything in order by key (serviceId).
    107     */
    108    private final Map<String, MutableServiceActivity> serviceIdToServiceStatus = new TreeMap<String, MutableServiceActivity>();
    109
    110    @Override
    111    public synchronized List<ServiceActivity> getServiceActivity()
    112    {
    113        // Need to wrap the values in a new list because
    114        // a) we don't want people arbitrarily changing the internal state of
    115        // _serviceIdtoServiceStatus
    116        // b) values() is Collection and we want to return List
    117
    118        // Note: ugly code here to keep Sun compiler happy.
    119
    120        List<ServiceActivity> result = CollectionFactory.newList();
    121
    122        result.addAll(serviceIdToServiceStatus.values());
    123
    124        return result;
    125    }
    126
    127    void startup()
    128    {
    129        // Does nothing, first pass does not use a worker thread
    130    }
    131
    132    void shutdown()
    133    {
    134        // Does nothing, first pass does not use a worker thread
    135    }
    136
    137    @Override
    138    public synchronized void define(ServiceDef serviceDef, Status initialStatus)
    139    {
    140        serviceIdToServiceStatus.put(serviceDef.getServiceId(), new MutableServiceActivity(
    141                serviceDef, perthreadManager, initialStatus));
    142    }
    143
    144    @Override
    145    public synchronized void setStatus(String serviceId, Status status)
    146    {
    147        serviceIdToServiceStatus.get(serviceId).setStatus(status);
    148    }
    149
    150}