Source code: org/apache/axis/client/ServiceFactory.java
1 /*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.axis.client;
18
19 import org.apache.axis.EngineConfiguration;
20 import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
21 import org.apache.axis.utils.ClassUtils;
22 import org.apache.axis.utils.Messages;
23
24 import javax.naming.Context;
25 import javax.naming.InitialContext;
26 import javax.naming.Name;
27 import javax.naming.NamingException;
28 import javax.naming.RefAddr;
29 import javax.naming.Reference;
30 import javax.naming.spi.ObjectFactory;
31 import javax.xml.namespace.QName;
32 import javax.xml.rpc.ServiceException;
33 import java.lang.reflect.Constructor;
34 import java.net.URL;
35 import java.util.Hashtable;
36 import java.util.Map;
37 import java.util.Properties;
38
39 /**
40 * Helper class for obtaining Services from JNDI.
41 *
42 * !!! WORK IN PROGRESS
43 *
44 * @author Glen Daniels (gdaniels@apache.org)
45 */
46
47 public class ServiceFactory extends javax.xml.rpc.ServiceFactory
48 implements ObjectFactory
49 {
50 // Constants for RefAddrs in the Reference.
51 public static final String SERVICE_CLASSNAME = "service classname";
52 public static final String WSDL_LOCATION = "WSDL location";
53 public static final String MAINTAIN_SESSION = "maintain session";
54 public static final String SERVICE_NAMESPACE = "service namespace";
55 public static final String SERVICE_LOCAL_PART = "service local part";
56 public static final String SERVICE_IMPLEMENTATION_NAME_PROPERTY = "serviceImplementationName";
57
58 private static final String SERVICE_IMPLEMENTATION_SUFFIX = "Locator";
59
60 private static EngineConfiguration _defaultEngineConfig = null;
61
62 private static ThreadLocal threadDefaultConfig = new ThreadLocal();
63
64 public static void setThreadDefaultConfig(EngineConfiguration config)
65 {
66 threadDefaultConfig.set(config);
67 }
68
69 private static EngineConfiguration getDefaultEngineConfig() {
70 if (_defaultEngineConfig == null) {
71 _defaultEngineConfig =
72 EngineConfigurationFactoryFinder.newFactory().getClientEngineConfig();
73 }
74 return _defaultEngineConfig;
75 }
76
77 /**
78 * Obtain an AxisClient reference, using JNDI if possible, otherwise
79 * creating one using the standard Axis configuration pattern. If we
80 * end up creating one and do have JNDI access, bind it to the passed
81 * name so we find it next time.
82 *
83 * @param environment
84 * @return a service
85 */
86 public static Service getService(Map environment)
87 {
88 Service service = null;
89 InitialContext context = null;
90
91 EngineConfiguration configProvider =
92 (EngineConfiguration)environment.get(EngineConfiguration.PROPERTY_NAME);
93
94 if (configProvider == null)
95 configProvider = (EngineConfiguration)threadDefaultConfig.get();
96
97 if (configProvider == null)
98 configProvider = getDefaultEngineConfig();
99
100 // First check to see if JNDI works
101 // !!! Might we need to set up context parameters here?
102 try {
103 context = new InitialContext();
104 } catch (NamingException e) {
105 }
106
107 if (context != null) {
108 String name = (String)environment.get("jndiName");
109 if (name == null) {
110 name = "axisServiceName";
111 }
112
113 // We've got JNDI, so try to find an AxisClient at the
114 // specified name.
115 try {
116 service = (Service)context.lookup(name);
117 } catch (NamingException e) {
118 service = new Service(configProvider);
119 try {
120 context.bind(name, service);
121 } catch (NamingException e1) {
122 // !!! Couldn't do it, what should we do here?
123 }
124 }
125 } else {
126 service = new Service(configProvider);
127 }
128
129 return service;
130 }
131
132 public Object getObjectInstance(Object refObject, Name name,
133 Context nameCtx, Hashtable environment) throws Exception
134 {
135 Object instance = null;
136 if (refObject instanceof Reference) {
137 Reference ref = (Reference) refObject;
138
139 RefAddr addr = ref.get(SERVICE_CLASSNAME);
140 Object obj = null;
141 // If an explicit service classname is provided, then this is a
142 // generated Service class. Just use its default constructor.
143 if (addr != null && (obj = addr.getContent()) instanceof String) {
144 instance = ClassUtils.forName((String) obj).newInstance();
145 }
146 // else this is an instance of the Service class, so grab the
147 // reference data...
148 else {
149 // Get the WSDL location...
150 addr = ref.get(WSDL_LOCATION);
151 if (addr != null && (obj = addr.getContent()) instanceof String) {
152 URL wsdlLocation = new URL((String) obj);
153
154 // Build the service qname...
155 addr = ref.get(SERVICE_NAMESPACE);
156 if (addr != null
157 && (obj = addr.getContent()) instanceof String) {
158 String namespace = (String) obj;
159 addr = ref.get(SERVICE_LOCAL_PART);
160 if (addr != null
161 && (obj = addr.getContent()) instanceof String) {
162 String localPart = (String) obj;
163 QName serviceName = new QName(namespace, localPart);
164
165 // Construct an instance of the service
166 Class[] formalArgs = new Class[]
167 {URL.class, QName.class};
168 Object[] actualArgs = new Object[]
169 {wsdlLocation, serviceName};
170 Constructor ctor =
171 Service.class.getDeclaredConstructor(
172 formalArgs);
173 instance = ctor.newInstance(actualArgs);
174 }
175 }
176 }
177 }
178 // If maintainSession should be set to true, there will be an
179 // addr for it.
180 addr = ref.get(MAINTAIN_SESSION);
181 if (addr != null && instance instanceof Service) {
182 ((Service) instance).setMaintainSession(true);
183 }
184 }
185 return instance;
186 } // getObjectInstance
187
188 /**
189 * Create a Service instance.
190 * @param wsdlDocumentLocation URL for the WSDL document location
191 for the service
192 * @param serviceName QName for the service.
193 * @return Service.
194 * @throws ServiceException If any error in creation of the specified service
195 */
196 public javax.xml.rpc.Service createService(URL wsdlDocumentLocation,
197 QName serviceName) throws ServiceException {
198 return new Service(wsdlDocumentLocation, serviceName);
199 } // createService
200
201 /**
202 * Create a Service instance. Since the WSDL file is not provided
203 * here, the Service object returned is quite simpleminded.
204 * Likewise, the Call object that service.createCall will return
205 * will also be simpleminded. The caller must explicitly fill in
206 * all the info on the Call object (ie., endpoint address, etc.).
207 *
208 * @param serviceName QName for the service
209 * @return Service.
210 * @throws ServiceException If any error in creation of the specified service
211 */
212 public javax.xml.rpc.Service createService(QName serviceName)
213 throws ServiceException {
214 return new Service(serviceName);
215 } // createService
216
217 /**
218 * Create an instance of the generated service implementation class
219 * for a given service interface, if available.
220 *
221 * @param serviceInterface Service interface
222 * @return Service.
223 * @throws ServiceException If there is any error while creating the specified service,
224 * including the case where a generated service implementation class cannot be located
225 */
226 public javax.xml.rpc.Service loadService(Class serviceInterface) throws ServiceException {
227 if (serviceInterface == null) {
228 throw new IllegalArgumentException(
229 Messages.getMessage("serviceFactoryIllegalServiceInterface"));
230 }
231 if (!(javax.xml.rpc.Service.class).isAssignableFrom(serviceInterface))
232 {
233 throw new ServiceException(
234 Messages.getMessage("serviceFactoryServiceInterfaceRequirement", serviceInterface.getName()));
235 } else {
236 String serviceImplementationName = serviceInterface.getName() + SERVICE_IMPLEMENTATION_SUFFIX;
237 Service service = createService(serviceImplementationName);
238 return service;
239 }
240 }
241
242 /**
243 * Create an instance of the generated service implementation class
244 * for a given service interface, if available.
245 * An implementation may use the provided wsdlDocumentLocation and properties
246 * to help locate the generated implementation class.
247 * If no such class is present, a ServiceException will be thrown.
248 *
249 * @param wsdlDocumentLocation URL for the WSDL document location for the service or null
250 * @param serviceInterface Service interface
251 * @param properties A set of implementation-specific properties
252 * to help locate the generated service implementation class
253 * @return Service.
254 * @throws ServiceException If there is any error while creating the specified service,
255 * including the case where a generated service implementation class cannot be located
256 */
257 public javax.xml.rpc.Service loadService(URL wsdlDocumentLocation,
258 Class serviceInterface, Properties properties) throws ServiceException {
259 if (serviceInterface == null) {
260 throw new IllegalArgumentException(
261 Messages.getMessage("serviceFactoryIllegalServiceInterface"));
262 }
263 if (!(javax.xml.rpc.Service.class).isAssignableFrom(serviceInterface))
264 {
265 throw new ServiceException(
266 Messages.getMessage("serviceFactoryServiceInterfaceRequirement", serviceInterface.getName()));
267 } else {
268 String serviceImplementationName = serviceInterface.getName() + SERVICE_IMPLEMENTATION_SUFFIX;
269 Service service = createService(serviceImplementationName);
270 return service;
271 }
272 }
273
274 /**
275 * Create an instance of the generated service implementation class
276 * for a given service, if available.
277 * The service is uniquely identified by the wsdlDocumentLocation and serviceName arguments.
278 * An implementation may use the provided properties to help locate the generated implementation class.
279 * If no such class is present, a ServiceException will be thrown.
280 *
281 * @param wsdlDocumentLocation URL for the WSDL document location for the service or null
282 * @param serviceName Qualified name for the service
283 * @param properties A set of implementation-specific properties
284 * to help locate the generated service implementation class
285 * @return Service.
286 * @throws ServiceException If there is any error while creating the specified service,
287 * including the case where a generated service implementation class cannot be located
288 */
289 public javax.xml.rpc.Service loadService(URL wsdlDocumentLocation,
290 QName serviceName, Properties properties) throws ServiceException {
291 String serviceImplementationName = properties.getProperty(SERVICE_IMPLEMENTATION_NAME_PROPERTY);
292 javax.xml.rpc.Service service = createService(serviceImplementationName);
293 if (service.getServiceName().equals(serviceName)) {
294 return service;
295 } else {
296 throw new ServiceException(
297 Messages.getMessage("serviceFactoryServiceImplementationNotFound", serviceImplementationName));
298 }
299 }
300
301 private Service createService(String serviceImplementationName) throws ServiceException {
302 if(serviceImplementationName == null) {
303 throw new IllegalArgumentException(Messages.getMessage("serviceFactoryInvalidServiceName"));
304 }
305 try {
306 Class serviceImplementationClass;
307 serviceImplementationClass = Thread.currentThread().getContextClassLoader().loadClass(serviceImplementationName);
308 if (!(org.apache.axis.client.Service.class).isAssignableFrom(serviceImplementationClass)) {
309 throw new ServiceException(
310 Messages.getMessage("serviceFactoryServiceImplementationRequirement", serviceImplementationName));
311 }
312 Service service = (Service) serviceImplementationClass.newInstance();
313 if (service.getServiceName() != null) {
314 return service;
315 } else {
316 throw new ServiceException(Messages.getMessage("serviceFactoryInvalidServiceName"));
317 }
318 } catch (ServiceException e) {
319 throw e;
320 } catch (Exception e){
321 throw new ServiceException(e);
322 }
323
324 }
325 }