001 // Copyright 2004, 2005 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.tapestry.services.impl;
016
017 import java.util.HashMap;
018 import java.util.Iterator;
019 import java.util.List;
020 import java.util.Map;
021
022 import org.apache.hivemind.ApplicationRuntimeException;
023 import org.apache.hivemind.ErrorLog;
024 import org.apache.tapestry.engine.IEngineService;
025 import org.apache.tapestry.services.ServiceMap;
026
027 /**
028 * Implementation of {@link org.apache.tapestry.services.ServiceMap}.
029 *
030 * @author Howard Lewis Ship
031 * @since 4.0
032 */
033 public class ServiceMapImpl implements ServiceMap, EngineServiceSource
034 {
035 /**
036 * List of {@link EngineServiceContribution}.
037 */
038 private List _applicationServices;
039
040 /**
041 * List of {@link EngineServiceContribution}.
042 */
043 private List _factoryServices;
044
045 private ErrorLog _errorLog;
046
047 /**
048 * Map of {@link EngineServiceContribution} keyed on String name.
049 */
050 private Map _services;
051
052 /**
053 * Map of {@link org.apache.tapestry.services.impl.EngineServiceOuterProxy}, keyed on String
054 * name.
055 */
056
057 private Map _proxies = new HashMap();
058
059 public void initializeService()
060 {
061 Map factoryMap = buildServiceMap(_factoryServices);
062 Map applicationMap = buildServiceMap(_applicationServices);
063
064 // Add services from the applicationMap to factoryMap, overwriting
065 // factoryMap entries with the same name.
066
067 factoryMap.putAll(applicationMap);
068
069 _services = factoryMap;
070 }
071
072 private Map buildServiceMap(List services)
073 {
074 Map result = new HashMap();
075
076 Iterator i = services.iterator();
077 while (i.hasNext())
078 {
079 EngineServiceContribution contribution = (EngineServiceContribution) i.next();
080 String name = contribution.getName();
081
082 EngineServiceContribution existing = (EngineServiceContribution) result.get(name);
083
084 if (existing != null)
085 {
086 _errorLog.error(
087 ImplMessages.dupeService(name, existing),
088 existing.getLocation(),
089 null);
090 continue;
091 }
092
093 result.put(name, contribution);
094 }
095
096 return result;
097 }
098
099 public synchronized IEngineService getService(String name)
100 {
101 IEngineService result = (IEngineService) _proxies.get(name);
102
103 if (result == null)
104 {
105 result = buildProxy(name);
106 _proxies.put(name, result);
107 }
108
109 return result;
110 }
111
112 public boolean isValid(String name)
113 {
114 return _services.containsKey(name);
115 }
116
117 /**
118 * This returns the actual service, not the outer proxy.
119 */
120
121 public IEngineService resolveEngineService(String name)
122 {
123 EngineServiceContribution contribution = (EngineServiceContribution) _services.get(name);
124
125 if (contribution == null)
126 throw new ApplicationRuntimeException(ImplMessages.noSuchService(name));
127
128 IEngineService service = contribution.getService();
129 String serviceName = service.getName();
130
131 if (!name.equals(serviceName))
132 throw new ApplicationRuntimeException(ImplMessages.serviceNameMismatch(
133 service,
134 name,
135 serviceName), contribution.getLocation(), null);
136
137 return service;
138 }
139
140 private IEngineService buildProxy(String name)
141 {
142 if (!_services.containsKey(name))
143 throw new ApplicationRuntimeException(ImplMessages.noSuchService(name));
144
145 EngineServiceOuterProxy outer = new EngineServiceOuterProxy(name);
146
147 EngineServiceInnerProxy inner = new EngineServiceInnerProxy(name, outer, this);
148
149 outer.installDelegate(inner);
150
151 return outer;
152 }
153
154 public void setApplicationServices(List applicationServices)
155 {
156 _applicationServices = applicationServices;
157 }
158
159 public void setFactoryServices(List factoryServices)
160 {
161 _factoryServices = factoryServices;
162 }
163
164 public void setErrorLog(ErrorLog errorLog)
165 {
166 _errorLog = errorLog;
167 }
168 }