PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/jboss-as-7.1.1.Final/ee/src/main/java/org/jboss/as/ee/component/deployers/ModuleJndiBindingProcessor.java

#
Java | 305 lines | 215 code | 40 blank | 50 comment | 45 complexity | b683d1d12273f88c0a57e354eb0d34cd MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1. /*
  2. * JBoss, Home of Professional Open Source.
  3. * Copyright 2011, Red Hat, Inc., and individual contributors
  4. * as indicated by the @author tags. See the copyright.txt file in the
  5. * distribution for a full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.jboss.as.ee.component.deployers;
  23. import java.util.HashMap;
  24. import java.util.HashSet;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Set;
  28. import org.jboss.as.controller.ServiceVerificationHandler;
  29. import org.jboss.as.ee.component.Attachments;
  30. import org.jboss.as.ee.component.BindingConfiguration;
  31. import org.jboss.as.ee.component.ClassDescriptionTraversal;
  32. import org.jboss.as.ee.component.ComponentConfiguration;
  33. import org.jboss.as.ee.component.ComponentNamingMode;
  34. import org.jboss.as.ee.component.EEApplicationClasses;
  35. import org.jboss.as.ee.component.EEModuleClassDescription;
  36. import org.jboss.as.ee.component.EEModuleConfiguration;
  37. import org.jboss.as.ee.component.EEModuleDescription;
  38. import org.jboss.as.ee.component.InjectionSource;
  39. import org.jboss.as.ee.component.InterceptorDescription;
  40. import org.jboss.as.ee.metadata.MetadataCompleteMarker;
  41. import org.jboss.as.ee.naming.ContextInjectionSource;
  42. import org.jboss.as.ee.structure.DeploymentType;
  43. import org.jboss.as.ee.structure.DeploymentTypeMarker;
  44. import org.jboss.as.naming.ManagedReferenceFactory;
  45. import org.jboss.as.naming.ServiceBasedNamingStore;
  46. import org.jboss.as.naming.deployment.ContextNames;
  47. import org.jboss.as.naming.service.BinderService;
  48. import org.jboss.as.server.CurrentServiceContainer;
  49. import org.jboss.as.server.deployment.DeploymentPhaseContext;
  50. import org.jboss.as.server.deployment.DeploymentUnit;
  51. import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
  52. import org.jboss.as.server.deployment.DeploymentUnitProcessor;
  53. import org.jboss.as.server.deployment.reflect.ClassIndex;
  54. import org.jboss.as.server.deployment.reflect.DeploymentClassIndex;
  55. import org.jboss.msc.service.AbstractServiceListener;
  56. import org.jboss.msc.service.CircularDependencyException;
  57. import org.jboss.msc.service.DuplicateServiceException;
  58. import org.jboss.msc.service.ServiceBuilder;
  59. import org.jboss.msc.service.ServiceController;
  60. import org.jboss.msc.service.ServiceName;
  61. import static org.jboss.as.ee.EeLogger.ROOT_LOGGER;
  62. import static org.jboss.as.ee.EeMessages.MESSAGES;
  63. /**
  64. * Processor that sets up JNDI bindings that are owned by the module. It also handles class level jndi bindings
  65. * that belong to components that do not have their own java:comp namespace, and class level bindings declared in
  66. * namespaces above java:comp.
  67. * <p/>
  68. * This processor is also responsible for throwing an exception if any ee component classes have been marked as invalid.
  69. *
  70. * @author Stuart Douglas
  71. */
  72. public class
  73. ModuleJndiBindingProcessor implements DeploymentUnitProcessor {
  74. private static class IntHolder {
  75. private int value = 0;
  76. }
  77. public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
  78. final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
  79. final EEApplicationClasses applicationClasses = deploymentUnit.getAttachment(Attachments.EE_APPLICATION_CLASSES_DESCRIPTION);
  80. final EEModuleConfiguration moduleConfiguration = deploymentUnit.getAttachment(Attachments.EE_MODULE_CONFIGURATION);
  81. final EEModuleDescription eeModuleDescription = deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
  82. final DeploymentClassIndex classIndex = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.CLASS_INDEX);
  83. if (moduleConfiguration == null) {
  84. return;
  85. }
  86. final Set<ServiceName> dependencies = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.JNDI_DEPENDENCIES);
  87. final Map<ServiceName, BindingConfiguration> deploymentDescriptorBindings = new HashMap<ServiceName, BindingConfiguration>();
  88. // bindings
  89. // Handle duplicates binding from the same source
  90. // TODO: Should the view configuration just return a Set instead of a List? Or is there a better way to
  91. // handle these duplicates?
  92. IntHolder moduleCount = new IntHolder();
  93. final List<BindingConfiguration> bindingConfigurations = eeModuleDescription.getBindingConfigurations();
  94. //we need to make sure that java:module/env and java:comp/env are always available
  95. if (!DeploymentTypeMarker.isType(DeploymentType.EAR, deploymentUnit)) {
  96. bindingConfigurations.add(new BindingConfiguration("java:module/env", new ContextInjectionSource("env", "java:module/env")));
  97. }
  98. if (deploymentUnit.getParent() == null) {
  99. bindingConfigurations.add(new BindingConfiguration("java:app/env", new ContextInjectionSource("env", "java:app/env")));
  100. }
  101. final ServiceName moduleOwnerName = deploymentUnit.getServiceName().append("module").append(moduleConfiguration.getApplicationName()).append(moduleConfiguration.getModuleName());
  102. for (BindingConfiguration binding : bindingConfigurations) {
  103. final ContextNames.BindInfo bindInfo = ContextNames.bindInfoForEnvEntry(moduleConfiguration.getApplicationName(), moduleConfiguration.getModuleName(), null, false, binding.getName());
  104. deploymentDescriptorBindings.put(bindInfo.getBinderServiceName(), binding);
  105. addJndiBinding(moduleConfiguration, binding, phaseContext, bindInfo.getBinderServiceName(), moduleOwnerName, moduleCount, dependencies);
  106. }
  107. //now we process all component level bindings, for components that do not have their own java:comp namespace.
  108. // these are bindings that have been added via a deployment descriptor
  109. for (final ComponentConfiguration componentConfiguration : moduleConfiguration.getComponentConfigurations()) {
  110. // TODO: Should the view configuration just return a Set instead of a List? Or is there a better way to
  111. // handle these duplicates?
  112. for (BindingConfiguration binding : componentConfiguration.getComponentDescription().getBindingConfigurations()) {
  113. final String bindingName = binding.getName();
  114. final boolean compBinding = bindingName.startsWith("java:comp") || !bindingName.startsWith("java:");
  115. if (componentConfiguration.getComponentDescription().getNamingMode() == ComponentNamingMode.CREATE && compBinding) {
  116. //components with there own comp context do their own binding
  117. continue;
  118. }
  119. final ContextNames.BindInfo bindInfo = ContextNames.bindInfoForEnvEntry(moduleConfiguration.getApplicationName(), moduleConfiguration.getModuleName(), null, false, binding.getName());
  120. deploymentDescriptorBindings.put(bindInfo.getBinderServiceName(), binding);
  121. addJndiBinding(moduleConfiguration, binding, phaseContext, bindInfo.getBinderServiceName(), moduleOwnerName, moduleCount, dependencies);
  122. }
  123. }
  124. //now add all class level bindings
  125. final Set<String> handledClasses = new HashSet<String>();
  126. for (final ComponentConfiguration componentConfiguration : moduleConfiguration.getComponentConfigurations()) {
  127. final Set<Class<?>> classConfigurations = new HashSet<Class<?>>();
  128. classConfigurations.add(componentConfiguration.getComponentClass());
  129. for (final InterceptorDescription interceptor : componentConfiguration.getComponentDescription().getAllInterceptors()) {
  130. try {
  131. final ClassIndex interceptorClass = classIndex.classIndex(interceptor.getInterceptorClassName());
  132. classConfigurations.add(interceptorClass.getModuleClass());
  133. } catch (ClassNotFoundException e) {
  134. throw MESSAGES.cannotLoadInterceptor(e, interceptor.getInterceptorClassName(), componentConfiguration.getComponentClass());
  135. }
  136. }
  137. processClassConfigurations(phaseContext, applicationClasses, moduleConfiguration, deploymentDescriptorBindings, handledClasses, componentConfiguration.getComponentDescription().getNamingMode(), classConfigurations, componentConfiguration.getComponentName(), moduleOwnerName, moduleCount, dependencies);
  138. }
  139. }
  140. private void processClassConfigurations(final DeploymentPhaseContext phaseContext, final EEApplicationClasses applicationClasses, final EEModuleConfiguration moduleConfiguration, final Map<ServiceName, BindingConfiguration> deploymentDescriptorBindings, final Set<String> handledClasses, final ComponentNamingMode namingMode, final Set<Class<?>> classes, final String componentName, final ServiceName ownerName, final IntHolder handleCount, final Set<ServiceName> dependencies) throws DeploymentUnitProcessingException {
  141. for (final Class<?> clazz : classes) {
  142. new ClassDescriptionTraversal(clazz, applicationClasses) {
  143. @Override
  144. protected void handle(final Class<?> currentClass, final EEModuleClassDescription classDescription) throws DeploymentUnitProcessingException {
  145. if (classDescription == null) {
  146. return;
  147. }
  148. if (classDescription.isInvalid()) {
  149. throw MESSAGES.componentClassHasErrors(classDescription.getClassName(), componentName, classDescription.getInvalidMessage());
  150. }
  151. //only process classes once
  152. if (handledClasses.contains(classDescription.getClassName())) {
  153. return;
  154. }
  155. handledClasses.add(classDescription.getClassName());
  156. // TODO: Should the view configuration just return a Set instead of a List? Or is there a better way to
  157. // handle these duplicates?
  158. if (!MetadataCompleteMarker.isMetadataComplete(phaseContext.getDeploymentUnit())) {
  159. final Set<BindingConfiguration> classLevelBindings = new HashSet<BindingConfiguration>(classDescription.getBindingConfigurations());
  160. for (BindingConfiguration binding : classLevelBindings) {
  161. final String bindingName = binding.getName();
  162. final boolean compBinding = bindingName.startsWith("java:comp") || !bindingName.startsWith("java:");
  163. if (namingMode == ComponentNamingMode.CREATE && compBinding) {
  164. //components with their own comp context do their own binding
  165. continue;
  166. }
  167. final ContextNames.BindInfo bindInfo = ContextNames.bindInfoForEnvEntry(moduleConfiguration.getApplicationName(), moduleConfiguration.getModuleName(), null, false, binding.getName());
  168. ROOT_LOGGER.tracef("Binding %s using service %s", binding.getName(), bindInfo.getBinderServiceName());
  169. if (deploymentDescriptorBindings.containsKey(bindInfo.getBinderServiceName())) {
  170. continue; //this has been overridden by a DD binding
  171. }
  172. addJndiBinding(moduleConfiguration, binding, phaseContext, bindInfo.getBinderServiceName(), ownerName, handleCount, dependencies);
  173. }
  174. }
  175. }
  176. }.run();
  177. }
  178. }
  179. protected void addJndiBinding(final EEModuleConfiguration module, final BindingConfiguration bindingConfiguration, final DeploymentPhaseContext phaseContext, ServiceName serviceName, ServiceName ownerName, IntHolder handleCount, final Set<ServiceName> dependencies) throws DeploymentUnitProcessingException {
  180. // Gather information about the dependency
  181. final String bindingName = bindingConfiguration.getName().startsWith("java:") ? bindingConfiguration.getName() : "java:module/env/" + bindingConfiguration.getName();
  182. final ServiceVerificationHandler serviceVerificationHandler = phaseContext.getDeploymentUnit().getAttachment(org.jboss.as.server.deployment.Attachments.SERVICE_VERIFICATION_HANDLER);
  183. InjectionSource.ResolutionContext resolutionContext = new InjectionSource.ResolutionContext(
  184. true,
  185. module.getModuleName(),
  186. module.getModuleName(),
  187. module.getApplicationName()
  188. );
  189. // Check to see if this entry should actually be bound into JNDI.
  190. if (bindingName != null) {
  191. final ContextNames.BindInfo bindInfo = ContextNames.bindInfoForEnvEntry(module.getApplicationName(), module.getModuleName(), module.getModuleName(), false, bindingName);
  192. if (bindingName.startsWith("java:comp") || bindingName.startsWith("java:module") || bindingName.startsWith("java:app")) {
  193. //this is a binding that does not need to be shared.
  194. try {
  195. final BinderService service = new BinderService(bindInfo.getBindName(), bindingConfiguration.getSource());
  196. dependencies.add(bindInfo.getBinderServiceName());
  197. ServiceBuilder<ManagedReferenceFactory> serviceBuilder = phaseContext.getServiceTarget().addService(bindInfo.getBinderServiceName(), service);
  198. bindingConfiguration.getSource().getResourceValue(resolutionContext, serviceBuilder, phaseContext, service.getManagedObjectInjector());
  199. serviceBuilder.addDependency(bindInfo.getParentContextServiceName(), ServiceBasedNamingStore.class, service.getNamingStoreInjector());
  200. serviceBuilder.install();
  201. } catch (DuplicateServiceException e) {
  202. ServiceController<ManagedReferenceFactory> registered = (ServiceController<ManagedReferenceFactory>) CurrentServiceContainer.getServiceContainer().getService(bindInfo.getBinderServiceName());
  203. if (registered == null)
  204. throw e;
  205. BinderService service = (BinderService) registered.getService();
  206. if (!service.getSource().equals(bindingConfiguration.getSource()))
  207. throw MESSAGES.conflictingBinding(bindingName, bindingConfiguration.getSource());
  208. } catch (CircularDependencyException e) {
  209. throw MESSAGES.circularDependency(bindingName);
  210. }
  211. } else {
  212. ServiceController<ManagedReferenceFactory> controller = null;
  213. BinderService service;
  214. try {
  215. service = new BinderService(bindInfo.getBindName(), bindingConfiguration.getSource());
  216. dependencies.add(bindInfo.getBinderServiceName());
  217. ServiceBuilder<ManagedReferenceFactory> serviceBuilder = CurrentServiceContainer.getServiceContainer().addService(bindInfo.getBinderServiceName(), service);
  218. bindingConfiguration.getSource().getResourceValue(resolutionContext, serviceBuilder, phaseContext, service.getManagedObjectInjector());
  219. serviceBuilder.addDependency(bindInfo.getParentContextServiceName(), ServiceBasedNamingStore.class, service.getNamingStoreInjector());
  220. serviceBuilder.addListener(serviceVerificationHandler);
  221. controller = serviceBuilder.install();
  222. service.acquire();
  223. } catch (DuplicateServiceException e) {
  224. controller = (ServiceController<ManagedReferenceFactory>) CurrentServiceContainer.getServiceContainer().getService(bindInfo.getBinderServiceName());
  225. if (controller == null)
  226. throw e;
  227. service = (BinderService) controller.getService();
  228. if (!service.getSource().equals(bindingConfiguration.getSource())) {
  229. throw MESSAGES.conflictingBinding(bindingName, bindingConfiguration.getSource());
  230. }
  231. service.acquire();
  232. }
  233. //as these bindings are not child services
  234. //we need to add a listener that released the service when the deployment stops
  235. ServiceController<?> unitService = CurrentServiceContainer.getServiceContainer().getService(phaseContext.getDeploymentUnit().getServiceName());
  236. final BinderService binderService = service;
  237. unitService.addListener(new BinderReleaseListener(binderService));
  238. }
  239. } else {
  240. throw MESSAGES.nullBindingName(bindingConfiguration);
  241. }
  242. }
  243. public void undeploy(DeploymentUnit context) {
  244. }
  245. private static class BinderReleaseListener<T> extends AbstractServiceListener<T> {
  246. private final BinderService binderService;
  247. public BinderReleaseListener(final BinderService binderService) {
  248. this.binderService = binderService;
  249. }
  250. @Override
  251. public void listenerAdded(final ServiceController<? extends T> serviceController) {
  252. if (serviceController.getState() == ServiceController.State.DOWN || serviceController.getState() == ServiceController.State.STOPPING) {
  253. binderService.release();
  254. serviceController.removeListener(this);
  255. }
  256. }
  257. @Override
  258. public void transition(final ServiceController<? extends T> serviceController, final ServiceController.Transition transition) {
  259. if (transition.getAfter() == ServiceController.Substate.STOPPING) {
  260. binderService.release();
  261. serviceController.removeListener(this);
  262. }
  263. }
  264. }
  265. }