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}