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    }