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