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.hivemind.impl;
016    
017    import java.util.Iterator;
018    
019    import org.apache.commons.logging.Log;
020    import org.apache.commons.logging.LogFactory;
021    import org.apache.hivemind.ErrorHandler;
022    import org.apache.hivemind.Location;
023    import org.apache.hivemind.definition.ConfigurationParserDefinition;
024    import org.apache.hivemind.definition.ConfigurationPointDefinition;
025    import org.apache.hivemind.definition.ContributionDefinition;
026    import org.apache.hivemind.definition.DefinitionMessages;
027    import org.apache.hivemind.definition.ModuleDefinition;
028    import org.apache.hivemind.definition.RegistryDefinition;
029    import org.apache.hivemind.definition.ImplementationDefinition;
030    import org.apache.hivemind.definition.InterceptorDefinition;
031    import org.apache.hivemind.definition.ServicePointDefinition;
032    import org.apache.hivemind.definition.UnresolvedExtension;
033    import org.apache.hivemind.definition.Visibility;
034    import org.apache.hivemind.util.IdUtils;
035    
036    /**
037     * Resolves the {@link UnresolvedExtension unresolved extensions} in all
038     * modules of a {@link RegistryDefinition} during
039     * the construction of a registry by {@link RegistryBuilder}.
040     * Every unresolved extension (e.g. contribution, interceptor) references
041     * an extension point by its fully qualified id. This class looks for these
042     * extension points in the registry definition and adds the formerly unresolved
043     * extension directly to the extension points.
044     * The error handling is delegated to an instance of {@link ErrorHandler}.
045     * 
046     * @author Achim Huegen
047     */
048    public class ExtensionResolver
049    {
050        private static final Log LOG = LogFactory.getLog(ExtensionResolver.class);
051    
052        private ErrorHandler _errorHandler;
053        
054        private RegistryDefinition _definition;
055    
056        public ExtensionResolver(RegistryDefinition definition, ErrorHandler errorHandler)
057        {
058            _errorHandler = errorHandler;
059            _definition = definition;
060        }
061    
062        /**
063         * Resolves all unresolved extensions in the registry definition passed in the constructor.
064         * During this process the object graph represented by the registry definition is changed, 
065         * so that afterwards it doesn't contain unresolved extensions any longer if anything went ok. 
066         * If errors occur it depends on the assigned {@link ErrorHandler} whether an exceptions
067         * is raised or errors are logged only. In the latter case all extensions that couldn't
068         * be resolved will remain in the module definitions.
069         */
070        public void resolveExtensions()
071        {
072            for (Iterator iterModules = _definition.getModules().iterator(); iterModules.hasNext();)
073            {
074                ModuleDefinition module = (ModuleDefinition) iterModules.next();
075            
076                resolveImplementations(module);
077                resolveInterceptors(module);
078                resolveContributions(module);
079                resolveConfigurationParsers(module);
080            }
081        }
082    
083        private void resolveImplementations(ModuleDefinition module)
084        {
085            for (Iterator iter = module.getImplementations().iterator(); iter.hasNext();)
086            {
087                UnresolvedExtension unresolved = (UnresolvedExtension) iter.next();
088                String servicePointId = unresolved.getExtensionPointId();
089                if (LOG.isDebugEnabled()) {
090                    LOG.debug("Trying to resolve service point " + servicePointId + " referenced by" +
091                            " implementation" + logLocation(unresolved.getExtension().getLocation()));
092                }
093                ServicePointDefinition servicePoint = _definition.getServicePoint(servicePointId);
094                if (servicePoint == null)
095                {
096                    _errorHandler.error(
097                            LOG,
098                            DefinitionMessages.unknownServicePoint(
099                                    IdUtils.extractModule(servicePointId),
100                                    IdUtils.stripModule(servicePointId)),
101                            unresolved.getExtension().getLocation(),
102                            null);
103                } else {
104                    servicePoint.addImplementation((ImplementationDefinition) unresolved.getExtension());
105                }
106                iter.remove();
107            }
108        }
109        
110        private String logLocation(Location location)
111        {
112            if (location == null) {
113                return "";
114            } else {
115                return " at " + location.toString();
116            }
117        }
118        
119        private void resolveInterceptors(ModuleDefinition module)
120        {
121            for (Iterator iter = module.getInterceptors().iterator(); iter.hasNext();)
122            {
123                UnresolvedExtension unresolved = (UnresolvedExtension) iter.next();
124                String servicePointId = unresolved.getExtensionPointId();
125                if (LOG.isDebugEnabled()) {
126                    LOG.debug("Trying to resolve service point " + servicePointId + " referenced by" +
127                            " interceptor" + logLocation(unresolved.getExtension().getLocation()));
128                }
129                ServicePointDefinition servicePoint = _definition.getServicePoint(servicePointId);
130                if (servicePoint == null)
131                {
132                    _errorHandler.error(
133                            LOG,
134                            DefinitionMessages.unknownServicePoint(
135                                    IdUtils.extractModule(servicePointId),
136                                    IdUtils.stripModule(servicePointId)),
137                            unresolved.getExtension().getLocation(),
138                            null);
139                } else {
140                    servicePoint.addInterceptor((InterceptorDefinition) unresolved.getExtension());
141                }
142                iter.remove();
143            }
144        }
145        
146        private void resolveContributions(ModuleDefinition module)
147        {
148            for (Iterator iter = module.getContributions().iterator(); iter.hasNext();)
149            {
150                UnresolvedExtension unresolved = (UnresolvedExtension) iter.next();
151                String configurationPointId = unresolved.getExtensionPointId();
152                if (LOG.isDebugEnabled()) {
153                    LOG.debug("Trying to resolve configuration point " + configurationPointId + " referenced by" +
154                            " contribution " + logLocation(unresolved.getExtension().getLocation()));
155                }
156                ConfigurationPointDefinition configurationPoint = _definition.getConfigurationPoint(configurationPointId);
157                if (configurationPoint == null)
158                {
159                    _errorHandler.error(
160                            LOG,
161                            DefinitionMessages.unknownConfigurationPoint(
162                                    IdUtils.extractModule(configurationPointId),
163                                    IdUtils.stripModule(configurationPointId)),
164                            unresolved.getExtension().getLocation(),
165                            null);
166                } else {
167                    configurationPoint.addContribution((ContributionDefinition) unresolved.getExtension());
168                }
169                iter.remove();
170            }
171        }
172        
173        private void resolveConfigurationParsers(ModuleDefinition module)
174        {
175            for (Iterator iter = module.getConfigurationParsers().iterator(); iter.hasNext();)
176            {
177                UnresolvedExtension unresolved = (UnresolvedExtension) iter.next();
178                String configurationPointId = unresolved.getExtensionPointId();
179                if (LOG.isDebugEnabled()) {
180                    LOG.debug("Trying to resolve configuration point " + configurationPointId + " referenced by" +
181                            " ConfigurationParser " + logLocation(unresolved.getExtension().getLocation()));
182                }
183                ConfigurationPointDefinition configurationPoint = _definition.getConfigurationPoint(configurationPointId);
184                if (configurationPoint == null)
185                {
186                    _errorHandler.error(
187                            LOG,
188                            DefinitionMessages.unknownConfigurationPoint(
189                                    IdUtils.extractModule(configurationPointId),
190                                    IdUtils.stripModule(configurationPointId)),
191                            unresolved.getExtension().getLocation(),
192                            null);
193                } else {
194                    if (Visibility.PRIVATE.equals(configurationPoint.getVisibility())
195                       && !module.getId().equals(IdUtils.extractModule(configurationPointId))) {
196                        _errorHandler.error(
197                                LOG,
198                                DefinitionMessages.configurationPointNotVisible(
199                                        configurationPoint,
200                                        module),
201                                unresolved.getExtension().getLocation(),
202                                null);
203                        
204                    }
205                    
206                    configurationPoint.addParser((ConfigurationParserDefinition) unresolved.getExtension());
207                }
208                iter.remove();
209            }
210        }
211    
212    }