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