PageRenderTime 49ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib-imola/cics-bc/jbi4cics/src/main/java/it/imolinfo/jbi4cics/webservices/runtime/ServiceCreator.java

https://bitbucket.org/pymma/openesb-components
Java | 414 lines | 231 code | 48 blank | 135 comment | 9 complexity | 3dc4081fd62975bc8a45a8f2db8f31fe MD5 | raw file
  1. /*
  2. * Copyright (c) 2005, 2006 Imola Informatica.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the LGPL License v2.1
  5. * which accompanies this distribution, and is available at
  6. * http://www.gnu.org/licenses/lgpl.html
  7. */
  8. package it.imolinfo.jbi4cics.webservices.runtime;
  9. import it.imolinfo.jbi4cics.Logger;
  10. import it.imolinfo.jbi4cics.LoggerFactory;
  11. import it.imolinfo.jbi4cics.connection.jca.cics.CICSInteractionDescription;
  12. import it.imolinfo.jbi4cics.exception.Jbi4cicsException;
  13. import it.imolinfo.jbi4cics.exception.LocationException;
  14. import it.imolinfo.jbi4cics.jbi.BCELClassLoader;
  15. import it.imolinfo.jbi4cics.jbi.wsdl.Jbi4CicsAddress;
  16. import it.imolinfo.jbi4cics.jbi.wsdl.Jbi4CicsBinding;
  17. import it.imolinfo.jbi4cics.jbi.wsdl.Jbi4CicsExtension;
  18. import it.imolinfo.jbi4cics.jbi.xfire.JbiTransport;
  19. import it.imolinfo.jbi4cics.locator.SimpleLocation;
  20. import it.imolinfo.jbi4cics.security.Account;
  21. import it.imolinfo.jbi4cics.webservices.descriptor.ServiceDescriptor;
  22. import it.imolinfo.jbi4cics.webservices.utils.generators.ServiceBeanGenerator;
  23. import it.imolinfo.jbi4cics.webservices.utils.generators.ServiceInterfaceGenerator;
  24. import java.io.ByteArrayInputStream;
  25. import java.io.ByteArrayOutputStream;
  26. import java.io.IOException;
  27. import java.io.InputStream;
  28. import java.util.HashMap;
  29. import java.util.Map;
  30. import javax.jbi.component.ComponentContext;
  31. import javax.wsdl.Binding;
  32. import javax.wsdl.BindingFault;
  33. import javax.wsdl.BindingInput;
  34. import javax.wsdl.BindingOperation;
  35. import javax.wsdl.BindingOutput;
  36. import javax.wsdl.Definition;
  37. import javax.wsdl.Operation;
  38. import javax.wsdl.Port;
  39. import javax.wsdl.WSDLException;
  40. import javax.wsdl.extensions.ExtensionRegistry;
  41. import javax.wsdl.factory.WSDLFactory;
  42. import javax.wsdl.xml.WSDLReader;
  43. import javax.xml.namespace.QName;
  44. import org.codehaus.xfire.DefaultXFire;
  45. import org.codehaus.xfire.XFire;
  46. import org.codehaus.xfire.aegis.AegisBindingProvider;
  47. import org.codehaus.xfire.aegis.type.TypeMapping;
  48. import org.codehaus.xfire.service.Service;
  49. import org.codehaus.xfire.service.binding.ObjectServiceFactory;
  50. import org.codehaus.xfire.soap.SoapConstants;
  51. import org.codehaus.xfire.transport.Transport;
  52. import org.codehaus.xfire.transport.TransportManager;
  53. import org.codehaus.xfire.wsdl.AbstractWSDL;
  54. import org.xml.sax.InputSource;
  55. /**
  56. * Helper class to create XFire service starting from {@link ServiceDescriptor}.
  57. */
  58. public final class ServiceCreator {
  59. /**
  60. * Initial buffer size, expressed in bytes.
  61. */
  62. private static final int BUFFER_SIZE = 4096;
  63. /**
  64. * The logger for this class and its instances.
  65. */
  66. private static final Logger LOG
  67. = LoggerFactory.getLogger(ServiceCreator.class);
  68. /**
  69. * Creates an instance of this class.
  70. */
  71. public ServiceCreator() {
  72. }
  73. /**
  74. * Creates the XFire service from specified parameters.
  75. *
  76. * @param desc the service descriptor.
  77. * @param xfire the XFire instance to use for creation.
  78. * @return the newly created XFire service.
  79. */
  80. public Service createService(final ServiceDescriptor desc,
  81. final XFire xfire) {
  82. QName interfaceName = new QName(desc.getServiceNameSpace(),
  83. desc.getServiceInterfaceName());
  84. return doCreateService(desc, xfire, interfaceName, false);
  85. }
  86. /**
  87. * Creates the JBI XFire service from specified parameters.
  88. *
  89. * @param desc the service descriptor.
  90. * @param xfire the XFire instance to use for creation.
  91. * @param interfaceName the interface qualified name.
  92. * @return the newly created JBI XFire service.
  93. */
  94. public Service createJbiService(final ServiceDescriptor desc,
  95. final XFire xfire, final QName interfaceName) {
  96. return doCreateService(desc, xfire, interfaceName, true);
  97. }
  98. /**
  99. * Creates the XFire service from specified parameters.
  100. *
  101. * @param desc the service descriptor.
  102. * @param xfire the XFire instance to use for creation.
  103. * @param interfaceName the interface qualified name.
  104. * @param isJbiService <code>true</code> to create a JBI service (i.e.
  105. * under a JBI container), <code>false</code>
  106. * otherwise (outside a JBI environment).
  107. * @return the newly created XFire service.
  108. */
  109. private Service doCreateService(final ServiceDescriptor desc,
  110. final XFire xfire, final QName interfaceName,
  111. final boolean isJbiService) {
  112. ObjectServiceFactory factory
  113. = new ObjectServiceFactory(xfire.getTransportManager());
  114. AegisBindingProvider bindingProvider
  115. = (AegisBindingProvider) factory.getBindingProvider();
  116. Map<String, Object> props = null;
  117. Service service;
  118. TypeMapping typeMapping;
  119. if (isJbiService) {
  120. props = new HashMap<String, Object>();
  121. props.put(ObjectServiceFactory.PORT_TYPE, interfaceName);
  122. props.put(ObjectServiceFactory.STYLE, SoapConstants.STYLE_WRAPPED);
  123. props.put(ObjectServiceFactory.USE, SoapConstants.USE_LITERAL);
  124. factory.getSoap12Transports().clear();
  125. factory.getSoap11Transports().clear();
  126. factory.getSoap11Transports().add(JbiTransport.JBI_BINDING);
  127. }
  128. service = factory.create(desc.getServiceInterface(),
  129. desc.getServiceName(), desc.getServiceNameSpace(), props);
  130. service.setInvoker(new ServiceInvoker(desc));
  131. // Adds the import in WSDL schema
  132. service.setProperty(AbstractWSDL.GENERATE_IMPORTS, "true");
  133. typeMapping = bindingProvider.getTypeMapping(service);
  134. typeMapping.register(new BigIntegerType());
  135. typeMapping.register(new BigDecimalType());
  136. return service;
  137. }
  138. /**
  139. * Creates a WSDL object from specified copy Cobol. This method may be used
  140. * to generate a WSDL (file) starting from a CPY file, for example.
  141. *
  142. * @param copyCobol the copy Cobol to generates the WSDL. Must be
  143. * not <code>null</code>.
  144. * @param outputCopyCobol the optional output copy Cobol to generates
  145. * the WSDL. If <code>null</code> or blank, is
  146. * like to not specify this parameter, so only
  147. * <code>copyCobol</code> will be considered and
  148. * will be used for input and for output during
  149. * CICS call.
  150. * @param desc the WSDL descriptor. Must be not
  151. * <code>null</code>.
  152. * @return the WSDL document corresponding to the copy Cobol received.
  153. * @throws Jbi4cicsException in case of errors that prevent WSDL creation.
  154. */
  155. public Definition createWsdlFromCopyCobol(final String copyCobol,
  156. final String outputCopyCobol, final ServiceDescriptor desc)
  157. throws Jbi4cicsException {
  158. BCELClassLoader loader
  159. = new BCELClassLoader(getClass().getClassLoader());
  160. Service service;
  161. ByteArrayOutputStream buffer = new ByteArrayOutputStream(BUFFER_SIZE);
  162. // Creates service input bean
  163. new ServiceBeanGenerator(desc, true).generateBeanClass(loader);
  164. // Creates service output bean
  165. new ServiceBeanGenerator(desc, false).generateBeanClass(loader);
  166. // Creates the service interface
  167. new ServiceInterfaceGenerator(desc).generateServiceInterface(loader);
  168. // Creates the service
  169. service = createJbiService(desc, createXFire(null), new QName(
  170. desc.getServiceNameSpace(), desc.getServiceInterfaceName()));
  171. // Modifies the service adding CICS elements
  172. try {
  173. service.getWSDLWriter().write(buffer);
  174. return bindToCics(new ByteArrayInputStream(buffer.toByteArray()),
  175. copyCobol, outputCopyCobol, desc);
  176. } catch (WSDLException e) {
  177. LOG.error(e.getLocalizedMessage(), e);
  178. throw new Jbi4cicsException(e.getMessage(), e);
  179. } catch (IOException e) {
  180. LOG.error(e.getLocalizedMessage(), e);
  181. throw new Jbi4cicsException(e.getMessage(), e);
  182. }
  183. }
  184. // Leave this method here and don't put it inside Jbi4cicsLifeCycle class,
  185. // because that class uses ServiceMix classes and will cause another library
  186. // to be added to Netbeans plugin
  187. /**
  188. * Creates a new XFire instance.
  189. *
  190. * @param componentContext the JBI component context. May be
  191. * <code>null</code>.
  192. * @return the newly created XFire instance, with a JBI transport related
  193. * to <code>componentContext</code>.
  194. */
  195. public static XFire createXFire(final ComponentContext componentContext) {
  196. XFire xfire = new DefaultXFire();
  197. TransportManager manager = xfire.getTransportManager();
  198. // Iterates over the array instead of the Collection to avoid
  199. // java.util.ConcurrentModificationException
  200. for (Object o : manager.getTransports().toArray()) {
  201. manager.unregister((Transport) o);
  202. }
  203. manager.register(new JbiTransport(componentContext));
  204. return xfire;
  205. }
  206. private Definition bindToCics(final InputStream wsdl,
  207. final String copyCobol, final String outputCopyCobol,
  208. final ServiceDescriptor desc)
  209. throws WSDLException, IOException, LocationException {
  210. WSDLFactory factory = WSDLFactory.newInstance();
  211. WSDLReader reader = factory.newWSDLReader();
  212. ExtensionRegistry registry = factory.newPopulatedExtensionRegistry();
  213. Definition def;
  214. javax.wsdl.Service service;
  215. Port port;
  216. Binding binding;
  217. Jbi4CicsExtension.register(registry);
  218. reader.setExtensionRegistry(registry);
  219. def = reader.readWSDL(null, new InputSource(wsdl));
  220. def.setExtensionRegistry(registry);
  221. def.addNamespace(Jbi4CicsExtension.DEFAULT_PREFIX,
  222. Jbi4CicsExtension.NS_URI_JBI4CICS);
  223. service = def.getService(new QName(desc.getServiceNameSpace(),
  224. desc.getServiceName()));
  225. // Remove all ports
  226. service.getPorts().clear();
  227. // Adds the port
  228. port = def.createPort();
  229. port.setName(desc.getServiceName() + "CicsPort");
  230. service.addPort(port);
  231. // Adds the extended address
  232. port.addExtensibilityElement(createJbi4CicsAddressElement(desc));
  233. // Adds the binding, using an existing port type
  234. binding = def.createBinding();
  235. binding.setUndefined(false);
  236. binding.setQName(new QName(desc.getServiceNameSpace(),
  237. desc.getServiceName() + "CicsBinding"));
  238. binding.setPortType(def.getPortType(new QName(
  239. desc.getServiceNameSpace(), desc.getServiceInterfaceName())));
  240. port.setBinding(binding);
  241. def.addBinding(binding);
  242. removeWsdlSoapElements(def, binding, desc);
  243. // Adds the extended binding
  244. binding.addExtensibilityElement(
  245. createJbi4CicsBindingElement(copyCobol, outputCopyCobol, desc));
  246. return def;
  247. }
  248. /**
  249. * Creates a new <code>Jbi4CicsAddress</code> element from the specified
  250. * service descriptor.
  251. *
  252. * @param desc the service descriptor.
  253. * @return the newly created Cics address element, representing the service
  254. * described by <code>desc</code>.
  255. * @throws LocationException if the CICS connection type contained in the
  256. * service descriptor is not valid.
  257. */
  258. private static Jbi4CicsAddress createJbi4CicsAddressElement(
  259. final ServiceDescriptor desc) throws LocationException {
  260. Jbi4CicsAddress addr = new Jbi4CicsAddress();
  261. Account account = desc.getAccount();
  262. // XXX Now we use only SimpleLocation, but in the future...
  263. SimpleLocation location = (SimpleLocation) desc.getServiceLocation();
  264. // XXX InteractionDescription has no methods: design problem?
  265. CICSInteractionDescription interactionDesc
  266. = (CICSInteractionDescription) desc.getInteractionDescription();
  267. addr.setElementType(Jbi4CicsExtension.Q_ELEM_JBI4CICS_ADDRESS);
  268. addr.setUsername(account.getUsername());
  269. addr.setPassword(account.getPassword());
  270. addr.setConnectionType(location.getConnectionTypeName());
  271. addr.setJNDIConnectionName(location.getLocationName());
  272. addr.setProgramName(interactionDesc.getProgramName());
  273. addr.setTransactionName(interactionDesc.getTransactionName());
  274. addr.setTpn(Boolean.valueOf(interactionDesc.isTpn()));
  275. return addr;
  276. }
  277. /**
  278. * Removes any SOAP element from the specified WSDL service.
  279. *
  280. * @param def the WSDL definition.
  281. * @param binding the new CICS binding added to <code>def</code>.
  282. * @param desc the service descriptor used to create the WSDL
  283. * definition <code>def</code>.
  284. */
  285. private static void removeWsdlSoapElements(final Definition def,
  286. final Binding binding, final ServiceDescriptor desc) {
  287. QName oldBindingName = new QName(desc.getServiceNameSpace(),
  288. desc.getServiceName() + "JBIBinding");
  289. for (Object o : def.getBinding(oldBindingName).getBindingOperations()) {
  290. BindingOperation bindingOp = (BindingOperation) o;
  291. Operation operation = bindingOp.getOperation();
  292. BindingInput input = bindingOp.getBindingInput();
  293. BindingOutput output = bindingOp.getBindingOutput();
  294. // Clones the <wsdl:operation> element to remove inner elements
  295. // contained in the "wsdlsoap" namespace
  296. BindingOperation newBindingOp = def.createBindingOperation();
  297. Operation newOperation = def.createOperation();
  298. BindingInput newInput = def.createBindingInput();
  299. BindingOutput newOutput = def.createBindingOutput();
  300. newBindingOp.setName(bindingOp.getName());
  301. newOperation.setName(operation.getName());
  302. newInput.setName(input.getName());
  303. newOutput.setName(output.getName());
  304. newBindingOp.setOperation(newOperation);
  305. newBindingOp.setBindingInput(newInput);
  306. newBindingOp.setBindingOutput(newOutput);
  307. for (Object obj : bindingOp.getBindingFaults().values()) {
  308. BindingFault fault = (BindingFault) obj;
  309. BindingFault newFault = def.createBindingFault();
  310. newFault.setName(fault.getName());
  311. newBindingOp.addBindingFault(newFault);
  312. }
  313. binding.addBindingOperation(newBindingOp);
  314. }
  315. def.removeBinding(oldBindingName);
  316. }
  317. /**
  318. * Creates a new <code>Jbi4CicsBinding</code> element from the specified
  319. * values.
  320. *
  321. * @param copyCobol the copy Cobol, used for the input and also for
  322. * the output step if <code>outputCopyCobol</code>
  323. * is <code>null</code> or blank.
  324. * @param outputCopyCobol the optional output copy Cobol to generates the
  325. * WSDL. If <code>null</code> or blank, is like to
  326. * not specify this parameter, so only
  327. * <code>copyCobol</code> will be considered and
  328. * will be used for input and for output during
  329. * CICS call.
  330. * @param desc the service descriptor.
  331. * @return the newly created Cics binding element, containing the values
  332. * received as parameters.
  333. */
  334. private static Jbi4CicsBinding createJbi4CicsBindingElement(
  335. final String copyCobol, final String outputCopyCobol,
  336. final ServiceDescriptor desc) {
  337. Jbi4CicsBinding binding = new Jbi4CicsBinding();
  338. binding.setElementType(Jbi4CicsExtension.Q_ELEM_JBI4CICS_BINDING);
  339. binding.setServicePackageName(desc.getServiceInterfacePackageName());
  340. binding.setCodePage(desc.getCodePage());
  341. binding.setCopyCobol(copyCobol);
  342. if ((outputCopyCobol != null) && !isBlank(outputCopyCobol)) {
  343. binding.setSameCopyCobol(Boolean.FALSE);
  344. binding.setOutputCopyCobol(outputCopyCobol);
  345. }
  346. return binding;
  347. }
  348. /**
  349. * Tests if the specified string is empty or contains only blank characters.
  350. * <p>
  351. * A <i>blank</i> character has code &lt;= <code>'&#92;u0020'</code> (the
  352. * space character).
  353. *
  354. * @param str the string to test.
  355. * @return <code>true</code> if and only if <code>str</code> has length
  356. * zero or is made only by blank characters.
  357. */
  358. private static boolean isBlank(String str) {
  359. for (int i = str.length() - 1; i >= 0; --i) {
  360. if (str.charAt(i) > ' ') {
  361. return false;
  362. }
  363. }
  364. return true;
  365. }
  366. }