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
015package org.apache.tapestry.services.impl;
016
017import java.util.HashMap;
018import java.util.Iterator;
019import java.util.List;
020import java.util.Map;
021
022import org.apache.hivemind.ApplicationRuntimeException;
023import org.apache.hivemind.ErrorLog;
024import org.apache.tapestry.engine.IEngineService;
025import 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 */
033public 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}