001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.remoting.jaxrpc;
018:
019: import java.net.URL;
020: import java.util.Properties;
021:
022: import javax.xml.namespace.QName;
023: import javax.xml.rpc.Service;
024: import javax.xml.rpc.ServiceException;
025: import javax.xml.rpc.ServiceFactory;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029:
030: import org.springframework.beans.BeanUtils;
031:
032: /**
033: * Factory for locally defined JAX-RPC {@link javax.xml.rpc.Service} references.
034: * Uses a JAX-RPC {@link javax.xml.rpc.ServiceFactory} underneath.
035: *
036: * <p>Serves as base class for {@link LocalJaxRpcServiceFactoryBean} as well as
037: * {@link JaxRpcPortClientInterceptor} and {@link JaxRpcPortProxyFactoryBean}.
038: *
039: * @author Juergen Hoeller
040: * @since 15.12.2003
041: * @see javax.xml.rpc.ServiceFactory
042: * @see javax.xml.rpc.Service
043: * @see LocalJaxRpcServiceFactoryBean
044: * @see JaxRpcPortClientInterceptor
045: * @see JaxRpcPortProxyFactoryBean
046: */
047: public class LocalJaxRpcServiceFactory {
048:
049: /** Logger available to subclasses */
050: protected final Log logger = LogFactory.getLog(getClass());
051:
052: private ServiceFactory serviceFactory;
053:
054: private Class serviceFactoryClass;
055:
056: private URL wsdlDocumentUrl;
057:
058: private String namespaceUri;
059:
060: private String serviceName;
061:
062: private Class jaxRpcServiceInterface;
063:
064: private Properties jaxRpcServiceProperties;
065:
066: private JaxRpcServicePostProcessor[] servicePostProcessors;
067:
068: /**
069: * Set the ServiceFactory instance to use.
070: * <p>This is an alternative to the common "serviceFactoryClass" property,
071: * allowing for a pre-initialized ServiceFactory instance to be specified.
072: * @see #setServiceFactoryClass
073: */
074: public void setServiceFactory(ServiceFactory serviceFactory) {
075: this .serviceFactory = serviceFactory;
076: }
077:
078: /**
079: * Return the specified ServiceFactory instance, if any.
080: */
081: public ServiceFactory getServiceFactory() {
082: return this .serviceFactory;
083: }
084:
085: /**
086: * Set the ServiceFactory class to use, for example
087: * "org.apache.axis.client.ServiceFactory".
088: * <p>Does not need to be set if the JAX-RPC implementation has registered
089: * itself with the JAX-RPC system property "SERVICEFACTORY_PROPERTY".
090: * @see javax.xml.rpc.ServiceFactory
091: */
092: public void setServiceFactoryClass(Class serviceFactoryClass) {
093: if (serviceFactoryClass != null
094: && !ServiceFactory.class
095: .isAssignableFrom(serviceFactoryClass)) {
096: throw new IllegalArgumentException(
097: "'serviceFactoryClass' must implement [javax.xml.rpc.ServiceFactory]");
098: }
099: this .serviceFactoryClass = serviceFactoryClass;
100: }
101:
102: /**
103: * Return the ServiceFactory class to use, or <code>null</code> if default.
104: */
105: public Class getServiceFactoryClass() {
106: return this .serviceFactoryClass;
107: }
108:
109: /**
110: * Set the URL of the WSDL document that describes the service.
111: */
112: public void setWsdlDocumentUrl(URL wsdlDocumentUrl) {
113: this .wsdlDocumentUrl = wsdlDocumentUrl;
114: }
115:
116: /**
117: * Return the URL of the WSDL document that describes the service.
118: */
119: public URL getWsdlDocumentUrl() {
120: return this .wsdlDocumentUrl;
121: }
122:
123: /**
124: * Set the namespace URI of the service.
125: * Corresponds to the WSDL "targetNamespace".
126: */
127: public void setNamespaceUri(String namespaceUri) {
128: this .namespaceUri = (namespaceUri != null ? namespaceUri.trim()
129: : null);
130: }
131:
132: /**
133: * Return the namespace URI of the service.
134: */
135: public String getNamespaceUri() {
136: return this .namespaceUri;
137: }
138:
139: /**
140: * Set the name of the service to look up.
141: * Corresponds to the "wsdl:service" name.
142: * @see javax.xml.rpc.ServiceFactory#createService(javax.xml.namespace.QName)
143: * @see javax.xml.rpc.ServiceFactory#createService(java.net.URL, javax.xml.namespace.QName)
144: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, javax.xml.namespace.QName, java.util.Properties)
145: */
146: public void setServiceName(String serviceName) {
147: this .serviceName = serviceName;
148: }
149:
150: /**
151: * Return the name of the service.
152: */
153: public String getServiceName() {
154: return this .serviceName;
155: }
156:
157: /**
158: * Set the JAX-RPC service interface to use for looking up the service.
159: * If specified, this will override a "serviceName" setting.
160: * <p>The specified interface will usually be a generated JAX-RPC service
161: * interface that directly corresponds to the WSDL service declaration.
162: * Note that this is not a port interface or the application-level service
163: * interface to be exposed by a port proxy!
164: * <p>Only supported by JAX-RPC 1.1 providers.
165: * @see #setServiceName
166: * @see javax.xml.rpc.ServiceFactory#loadService(Class)
167: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, Class, java.util.Properties)
168: */
169: public void setJaxRpcServiceInterface(Class jaxRpcServiceInterface) {
170: this .jaxRpcServiceInterface = jaxRpcServiceInterface;
171: }
172:
173: /**
174: * Return the JAX-RPC service interface to use for looking up the service.
175: */
176: public Class getJaxRpcServiceInterface() {
177: return this .jaxRpcServiceInterface;
178: }
179:
180: /**
181: * Set JAX-RPC service properties to be passed to the ServiceFactory, if any.
182: * <p>Only supported by JAX-RPC 1.1 providers.
183: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, javax.xml.namespace.QName, java.util.Properties)
184: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, Class, java.util.Properties)
185: */
186: public void setJaxRpcServiceProperties(
187: Properties jaxRpcServiceProperties) {
188: this .jaxRpcServiceProperties = jaxRpcServiceProperties;
189: }
190:
191: /**
192: * Return JAX-RPC service properties to be passed to the ServiceFactory, if any.
193: */
194: public Properties getJaxRpcServiceProperties() {
195: return this .jaxRpcServiceProperties;
196: }
197:
198: /**
199: * Set the JaxRpcServicePostProcessors to be applied to JAX-RPC Service
200: * instances created by this factory.
201: * <p>Such post-processors can, for example, register custom type mappings.
202: * They are reusable across all pre-built subclasses of this factory:
203: * LocalJaxRpcServiceFactoryBean, JaxRpcPortClientInterceptor,
204: * JaxRpcPortProxyFactoryBean.
205: * @see LocalJaxRpcServiceFactoryBean
206: * @see JaxRpcPortClientInterceptor
207: * @see JaxRpcPortProxyFactoryBean
208: */
209: public void setServicePostProcessors(
210: JaxRpcServicePostProcessor[] servicePostProcessors) {
211: this .servicePostProcessors = servicePostProcessors;
212: }
213:
214: /**
215: * Return the JaxRpcServicePostProcessors to be applied to JAX-RPC Service
216: * instances created by this factory.
217: */
218: public JaxRpcServicePostProcessor[] getServicePostProcessors() {
219: return this .servicePostProcessors;
220: }
221:
222: /**
223: * Create a JAX-RPC Service according to the parameters of this factory.
224: * @see #setServiceName
225: * @see #setWsdlDocumentUrl
226: * @see #postProcessJaxRpcService
227: */
228: public Service createJaxRpcService() throws ServiceException {
229: ServiceFactory serviceFactory = getServiceFactory();
230: if (serviceFactory == null) {
231: serviceFactory = createServiceFactory();
232: }
233:
234: // Create service based on this factory's settings.
235: Service service = createService(serviceFactory);
236:
237: // Allow for custom post-processing in subclasses.
238: postProcessJaxRpcService(service);
239:
240: return service;
241: }
242:
243: /**
244: * Return a QName for the given name, relative to the namespace URI
245: * of this factory, if given.
246: * @see #setNamespaceUri
247: */
248: protected QName getQName(String name) {
249: return (getNamespaceUri() != null ? new QName(
250: getNamespaceUri(), name) : new QName(name));
251: }
252:
253: /**
254: * Create a JAX-RPC ServiceFactory, either of the specified class
255: * or the default.
256: * @throws ServiceException if thrown by JAX-RPC methods
257: * @see #setServiceFactoryClass
258: * @see javax.xml.rpc.ServiceFactory#newInstance()
259: */
260: protected ServiceFactory createServiceFactory()
261: throws ServiceException {
262: if (getServiceFactoryClass() != null) {
263: return (ServiceFactory) BeanUtils
264: .instantiateClass(getServiceFactoryClass());
265: } else {
266: return ServiceFactory.newInstance();
267: }
268: }
269:
270: /**
271: * Actually create the JAX-RPC Service instance,
272: * based on this factory's settings.
273: * @param serviceFactory the JAX-RPC ServiceFactory to use
274: * @return the newly created JAX-RPC Service
275: * @throws ServiceException if thrown by JAX-RPC methods
276: * @see javax.xml.rpc.ServiceFactory#createService
277: * @see javax.xml.rpc.ServiceFactory#loadService
278: */
279: protected Service createService(ServiceFactory serviceFactory)
280: throws ServiceException {
281: if (getServiceName() == null
282: && getJaxRpcServiceInterface() == null) {
283: throw new IllegalArgumentException(
284: "Either 'serviceName' or 'jaxRpcServiceInterface' is required");
285: }
286:
287: if (getJaxRpcServiceInterface() != null) {
288: // Create service via generated JAX-RPC service interface.
289: // Only supported on JAX-RPC 1.1
290: if (getWsdlDocumentUrl() != null
291: || getJaxRpcServiceProperties() != null) {
292: return serviceFactory.loadService(getWsdlDocumentUrl(),
293: getJaxRpcServiceInterface(),
294: getJaxRpcServiceProperties());
295: }
296: return serviceFactory
297: .loadService(getJaxRpcServiceInterface());
298: }
299:
300: // Create service via specified JAX-RPC service name.
301: QName serviceQName = getQName(getServiceName());
302: if (getJaxRpcServiceProperties() != null) {
303: // Only supported on JAX-RPC 1.1
304: return serviceFactory.loadService(getWsdlDocumentUrl(),
305: serviceQName, getJaxRpcServiceProperties());
306: }
307: if (getWsdlDocumentUrl() != null) {
308: return serviceFactory.createService(getWsdlDocumentUrl(),
309: serviceQName);
310: }
311: return serviceFactory.createService(serviceQName);
312: }
313:
314: /**
315: * Post-process the given JAX-RPC Service. Called by {@link #createJaxRpcService}.
316: * Useful, for example, to register custom type mappings.
317: * <p>The default implementation delegates to all registered
318: * {@link JaxRpcServicePostProcessor JaxRpcServicePostProcessors}.
319: * It is usually preferable to implement custom type mappings etc there rather
320: * than in a subclass of this factory, to allow for reuse of the post-processors.
321: * @param service the current JAX-RPC Service
322: * (can be cast to an implementation-specific class if necessary)
323: * @see #setServicePostProcessors
324: * @see javax.xml.rpc.Service#getTypeMappingRegistry()
325: */
326: protected void postProcessJaxRpcService(Service service) {
327: JaxRpcServicePostProcessor[] postProcessors = getServicePostProcessors();
328: if (postProcessors != null) {
329: for (int i = 0; i < postProcessors.length; i++) {
330: postProcessors[i].postProcessJaxRpcService(service);
331: }
332: }
333: }
334:
335: }
|