blob: 33054a557fe76345607fdcf54045decd8caacab3 [file] [log] [blame]
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.axis.client;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
import org.apache.axis.utils.ClassUtils;
import org.apache.axis.utils.Messages;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
/**
* Helper class for obtaining Services from JNDI.
*
* !!! WORK IN PROGRESS
*
* @author Glen Daniels (gdaniels@apache.org)
*/
public class ServiceFactory extends javax.xml.rpc.ServiceFactory
implements ObjectFactory
{
// Constants for RefAddrs in the Reference.
public static final String SERVICE_CLASSNAME = "service classname";
public static final String WSDL_LOCATION = "WSDL location";
public static final String MAINTAIN_SESSION = "maintain session";
public static final String SERVICE_NAMESPACE = "service namespace";
public static final String SERVICE_LOCAL_PART = "service local part";
public static final String SERVICE_IMPLEMENTATION_NAME_PROPERTY = "serviceImplementationName";
private static final String SERVICE_IMPLEMENTATION_SUFFIX = "Locator";
private static EngineConfiguration _defaultEngineConfig = null;
private static ThreadLocal threadDefaultConfig = new ThreadLocal();
public static void setThreadDefaultConfig(EngineConfiguration config)
{
threadDefaultConfig.set(config);
}
private static EngineConfiguration getDefaultEngineConfig() {
if (_defaultEngineConfig == null) {
_defaultEngineConfig =
EngineConfigurationFactoryFinder.newFactory().getClientEngineConfig();
}
return _defaultEngineConfig;
}
/**
* Obtain an AxisClient reference, using JNDI if possible, otherwise
* creating one using the standard Axis configuration pattern. If we
* end up creating one and do have JNDI access, bind it to the passed
* name so we find it next time.
*
* @param environment
* @return a service
*/
public static Service getService(Map environment)
{
Service service = null;
InitialContext context = null;
EngineConfiguration configProvider =
(EngineConfiguration)environment.get(EngineConfiguration.PROPERTY_NAME);
if (configProvider == null)
configProvider = (EngineConfiguration)threadDefaultConfig.get();
if (configProvider == null)
configProvider = getDefaultEngineConfig();
// First check to see if JNDI works
// !!! Might we need to set up context parameters here?
try {
context = new InitialContext();
} catch (NamingException e) {
}
if (context != null) {
String name = (String)environment.get("jndiName");
if (name == null) {
name = "axisServiceName";
}
// We've got JNDI, so try to find an AxisClient at the
// specified name.
try {
service = (Service)context.lookup(name);
} catch (NamingException e) {
service = new Service(configProvider);
try {
context.bind(name, service);
} catch (NamingException e1) {
// !!! Couldn't do it, what should we do here?
}
}
} else {
service = new Service(configProvider);
}
return service;
}
public Object getObjectInstance(Object refObject, Name name,
Context nameCtx, Hashtable environment) throws Exception
{
Object instance = null;
if (refObject instanceof Reference) {
Reference ref = (Reference) refObject;
RefAddr addr = ref.get(SERVICE_CLASSNAME);
Object obj = null;
// If an explicit service classname is provided, then this is a
// generated Service class. Just use its default constructor.
if (addr != null && (obj = addr.getContent()) instanceof String) {
instance = ClassUtils.forName((String) obj).newInstance();
}
// else this is an instance of the Service class, so grab the
// reference data...
else {
// Get the WSDL location...
addr = ref.get(WSDL_LOCATION);
if (addr != null && (obj = addr.getContent()) instanceof String) {
URL wsdlLocation = new URL((String) obj);
// Build the service qname...
addr = ref.get(SERVICE_NAMESPACE);
if (addr != null
&& (obj = addr.getContent()) instanceof String) {
String namespace = (String) obj;
addr = ref.get(SERVICE_LOCAL_PART);
if (addr != null
&& (obj = addr.getContent()) instanceof String) {
String localPart = (String) obj;
QName serviceName = new QName(namespace, localPart);
// Construct an instance of the service
Class[] formalArgs = new Class[]
{URL.class, QName.class};
Object[] actualArgs = new Object[]
{wsdlLocation, serviceName};
Constructor ctor =
Service.class.getDeclaredConstructor(
formalArgs);
instance = ctor.newInstance(actualArgs);
}
}
}
}
// If maintainSession should be set to true, there will be an
// addr for it.
addr = ref.get(MAINTAIN_SESSION);
if (addr != null && instance instanceof Service) {
((Service) instance).setMaintainSession(true);
}
}
return instance;
} // getObjectInstance
/**
* Create a Service instance.
* @param wsdlDocumentLocation URL for the WSDL document location
for the service
* @param serviceName QName for the service.
* @return Service.
* @throws ServiceException If any error in creation of the specified service
*/
public javax.xml.rpc.Service createService(URL wsdlDocumentLocation,
QName serviceName) throws ServiceException {
return new Service(wsdlDocumentLocation, serviceName);
} // createService
/**
* Create a Service instance. Since the WSDL file is not provided
* here, the Service object returned is quite simpleminded.
* Likewise, the Call object that service.createCall will return
* will also be simpleminded. The caller must explicitly fill in
* all the info on the Call object (ie., endpoint address, etc.).
*
* @param serviceName QName for the service
* @return Service.
* @throws ServiceException If any error in creation of the specified service
*/
public javax.xml.rpc.Service createService(QName serviceName)
throws ServiceException {
return new Service(serviceName);
} // createService
/**
* Create an instance of the generated service implementation class
* for a given service interface, if available.
*
* @param serviceInterface Service interface
* @return Service.
* @throws ServiceException If there is any error while creating the specified service,
* including the case where a generated service implementation class cannot be located
*/
public javax.xml.rpc.Service loadService(Class serviceInterface) throws ServiceException {
if (serviceInterface == null) {
throw new IllegalArgumentException(
Messages.getMessage("serviceFactoryIllegalServiceInterface"));
}
if (!(javax.xml.rpc.Service.class).isAssignableFrom(serviceInterface))
{
throw new ServiceException(
Messages.getMessage("serviceFactoryServiceInterfaceRequirement", serviceInterface.getName()));
} else {
String serviceImplementationName = serviceInterface.getName() + SERVICE_IMPLEMENTATION_SUFFIX;
Service service = createService(serviceImplementationName);
return service;
}
}
/**
* Create an instance of the generated service implementation class
* for a given service interface, if available.
* An implementation may use the provided wsdlDocumentLocation and properties
* to help locate the generated implementation class.
* If no such class is present, a ServiceException will be thrown.
*
* @param wsdlDocumentLocation URL for the WSDL document location for the service or null
* @param serviceInterface Service interface
* @param properties A set of implementation-specific properties
* to help locate the generated service implementation class
* @return Service.
* @throws ServiceException If there is any error while creating the specified service,
* including the case where a generated service implementation class cannot be located
*/
public javax.xml.rpc.Service loadService(URL wsdlDocumentLocation,
Class serviceInterface, Properties properties) throws ServiceException {
if (serviceInterface == null) {
throw new IllegalArgumentException(
Messages.getMessage("serviceFactoryIllegalServiceInterface"));
}
if (!(javax.xml.rpc.Service.class).isAssignableFrom(serviceInterface))
{
throw new ServiceException(
Messages.getMessage("serviceFactoryServiceInterfaceRequirement", serviceInterface.getName()));
} else {
String serviceImplementationName = serviceInterface.getName() + SERVICE_IMPLEMENTATION_SUFFIX;
Service service = createService(serviceImplementationName);
return service;
}
}
/**
* Create an instance of the generated service implementation class
* for a given service, if available.
* The service is uniquely identified by the wsdlDocumentLocation and serviceName arguments.
* An implementation may use the provided properties to help locate the generated implementation class.
* If no such class is present, a ServiceException will be thrown.
*
* @param wsdlDocumentLocation URL for the WSDL document location for the service or null
* @param serviceName Qualified name for the service
* @param properties A set of implementation-specific properties
* to help locate the generated service implementation class
* @return Service.
* @throws ServiceException If there is any error while creating the specified service,
* including the case where a generated service implementation class cannot be located
*/
public javax.xml.rpc.Service loadService(URL wsdlDocumentLocation,
QName serviceName, Properties properties) throws ServiceException {
String serviceImplementationName = properties.getProperty(SERVICE_IMPLEMENTATION_NAME_PROPERTY);
javax.xml.rpc.Service service = createService(serviceImplementationName);
if (service.getServiceName().equals(serviceName)) {
return service;
} else {
throw new ServiceException(
Messages.getMessage("serviceFactoryServiceImplementationNotFound", serviceImplementationName));
}
}
private Service createService(String serviceImplementationName) throws ServiceException {
if(serviceImplementationName == null) {
throw new IllegalArgumentException(Messages.getMessage("serviceFactoryInvalidServiceName"));
}
try {
Class serviceImplementationClass;
serviceImplementationClass = Thread.currentThread().getContextClassLoader().loadClass(serviceImplementationName);
if (!(org.apache.axis.client.Service.class).isAssignableFrom(serviceImplementationClass)) {
throw new ServiceException(
Messages.getMessage("serviceFactoryServiceImplementationRequirement", serviceImplementationName));
}
Service service = (Service) serviceImplementationClass.newInstance();
if (service.getServiceName() != null) {
return service;
} else {
throw new ServiceException(Messages.getMessage("serviceFactoryInvalidServiceName"));
}
} catch (ServiceException e) {
throw e;
} catch (Exception e){
throw new ServiceException(e);
}
}
}