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 }