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 that is 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;
129: }
130:
131: /**
132: * Return the namespace URI of the service.
133: */
134: public String getNamespaceUri() {
135: return this .namespaceUri;
136: }
137:
138: /**
139: * Set the name of the service to look up.
140: * Corresponds to the "wsdl:service" name.
141: * @see javax.xml.rpc.ServiceFactory#createService(javax.xml.namespace.QName)
142: * @see javax.xml.rpc.ServiceFactory#createService(java.net.URL, javax.xml.namespace.QName)
143: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, javax.xml.namespace.QName, java.util.Properties)
144: */
145: public void setServiceName(String serviceName) {
146: this .serviceName = serviceName;
147: }
148:
149: /**
150: * Return the name of the service.
151: */
152: public String getServiceName() {
153: return this .serviceName;
154: }
155:
156: /**
157: * Set the JAX-RPC service interface to use for looking up the service.
158: * If specified, this will override a "serviceName" setting.
159: * <p>The specified interface will usually be a generated JAX-RPC service
160: * interface that directly corresponds to the WSDL service declaration.
161: * Note that this is not a port interface or the application-level service
162: * interface to be exposed by a port proxy!
163: * <p>Only supported by JAX-RPC 1.1 providers.
164: * @see #setServiceName
165: * @see javax.xml.rpc.ServiceFactory#loadService(Class)
166: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, Class, java.util.Properties)
167: */
168: public void setJaxRpcServiceInterface(Class jaxRpcServiceInterface) {
169: this .jaxRpcServiceInterface = jaxRpcServiceInterface;
170: }
171:
172: /**
173: * Return the JAX-RPC service interface to use for looking up the service.
174: */
175: public Class getJaxRpcServiceInterface() {
176: return this .jaxRpcServiceInterface;
177: }
178:
179: /**
180: * Set JAX-RPC service properties to be passed to the ServiceFactory, if any.
181: * <p>Only supported by JAX-RPC 1.1 providers.
182: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, javax.xml.namespace.QName, java.util.Properties)
183: * @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, Class, java.util.Properties)
184: */
185: public void setJaxRpcServiceProperties(
186: Properties jaxRpcServiceProperties) {
187: this .jaxRpcServiceProperties = jaxRpcServiceProperties;
188: }
189:
190: /**
191: * Return JAX-RPC service properties to be passed to the ServiceFactory, if any.
192: */
193: public Properties getJaxRpcServiceProperties() {
194: return this .jaxRpcServiceProperties;
195: }
196:
197: /**
198: * Set the JaxRpcServicePostProcessors to be applied to JAX-RPC Service
199: * instances created by this factory.
200: * <p>Such post-processors can, for example, register custom type mappings.
201: * They are reusable across all pre-built subclasses of this factory:
202: * LocalJaxRpcServiceFactoryBean, JaxRpcPortClientInterceptor,
203: * JaxRpcPortProxyFactoryBean.
204: * @see LocalJaxRpcServiceFactoryBean
205: * @see JaxRpcPortClientInterceptor
206: * @see JaxRpcPortProxyFactoryBean
207: */
208: public void setServicePostProcessors(
209: JaxRpcServicePostProcessor[] servicePostProcessors) {
210: this .servicePostProcessors = servicePostProcessors;
211: }
212:
213: /**
214: * Return the JaxRpcServicePostProcessors to be applied to JAX-RPC Service
215: * instances created by this factory.
216: */
217: public JaxRpcServicePostProcessor[] getServicePostProcessors() {
218: return this .servicePostProcessors;
219: }
220:
221: /**
222: * Create a JAX-RPC Service according to the parameters of this factory.
223: * @see #setServiceName
224: * @see #setWsdlDocumentUrl
225: * @see #postProcessJaxRpcService
226: */
227: public Service createJaxRpcService() throws ServiceException {
228: ServiceFactory serviceFactory = getServiceFactory();
229: if (serviceFactory == null) {
230: serviceFactory = createServiceFactory();
231: }
232:
233: // Create service based on this factory's settings.
234: Service service = createService(serviceFactory);
235:
236: // Allow for custom post-processing in subclasses.
237: postProcessJaxRpcService(service);
238:
239: return service;
240: }
241:
242: /**
243: * Return a QName for the given name, relative to the namespace URI
244: * of this factory, if given.
245: * @see #setNamespaceUri
246: */
247: protected QName getQName(String name) {
248: return (getNamespaceUri() != null ? new QName(
249: getNamespaceUri(), name) : new QName(name));
250: }
251:
252: /**
253: * Create a JAX-RPC ServiceFactory, either of the specified class
254: * or the default.
255: * @throws ServiceException if thrown by JAX-RPC methods
256: * @see #setServiceFactoryClass
257: * @see javax.xml.rpc.ServiceFactory#newInstance()
258: */
259: protected ServiceFactory createServiceFactory()
260: throws ServiceException {
261: if (getServiceFactoryClass() != null) {
262: return (ServiceFactory) BeanUtils
263: .instantiateClass(getServiceFactoryClass());
264: } else {
265: return ServiceFactory.newInstance();
266: }
267: }
268:
269: /**
270: * Actually create the JAX-RPC Service instance,
271: * based on this factory's settings.
272: * @param serviceFactory the JAX-RPC ServiceFactory to use
273: * @return the newly created JAX-RPC Service
274: * @throws ServiceException if thrown by JAX-RPC methods
275: * @see javax.xml.rpc.ServiceFactory#createService
276: * @see javax.xml.rpc.ServiceFactory#loadService
277: */
278: protected Service createService(ServiceFactory serviceFactory)
279: throws ServiceException {
280: if (getServiceName() == null
281: && getJaxRpcServiceInterface() == null) {
282: throw new IllegalArgumentException(
283: "Either 'serviceName' or 'jaxRpcServiceInterface' is required");
284: }
285:
286: if (getJaxRpcServiceInterface() != null) {
287: // Create service via generated JAX-RPC service interface.
288: // Only supported on JAX-RPC 1.1
289: if (getWsdlDocumentUrl() != null
290: || getJaxRpcServiceProperties() != null) {
291: return serviceFactory.loadService(getWsdlDocumentUrl(),
292: getJaxRpcServiceInterface(),
293: getJaxRpcServiceProperties());
294: }
295: return serviceFactory
296: .loadService(getJaxRpcServiceInterface());
297: }
298:
299: // Create service via specified JAX-RPC service name.
300: QName serviceQName = getQName(getServiceName());
301: if (getJaxRpcServiceProperties() != null) {
302: // Only supported on JAX-RPC 1.1
303: return serviceFactory.loadService(getWsdlDocumentUrl(),
304: serviceQName, getJaxRpcServiceProperties());
305: }
306: if (getWsdlDocumentUrl() != null) {
307: return serviceFactory.createService(getWsdlDocumentUrl(),
308: serviceQName);
309: }
310: return serviceFactory.createService(serviceQName);
311: }
312:
313: /**
314: * Post-process the given JAX-RPC Service. Called by {@link #createJaxRpcService}.
315: * Useful, for example, to register custom type mappings.
316: * <p>The default implementation delegates to all registered
317: * {@link JaxRpcServicePostProcessor JaxRpcServicePostProcessors}.
318: * It is usually preferable to implement custom type mappings etc there rather
319: * than in a subclass of this factory, to allow for reuse of the post-processors.
320: * @param service the current JAX-RPC Service
321: * (can be cast to an implementation-specific class if necessary)
322: * @see #setServicePostProcessors
323: * @see javax.xml.rpc.Service#getTypeMappingRegistry()
324: */
325: protected void postProcessJaxRpcService(Service service) {
326: JaxRpcServicePostProcessor[] postProcessors = getServicePostProcessors();
327: if (postProcessors != null) {
328: for (int i = 0; i < postProcessors.length; i++) {
329: postProcessors[i].postProcessJaxRpcService(service);
330: }
331: }
332: }
333:
334: }
|