/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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.wso2.carbon.dataservices.core;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.deployment.*;
import org.apache.axis2.deployment.repository.util.DeploymentFileData;
import org.apache.axis2.deployment.util.Utils;
import org.apache.axis2.description.*;
import org.apache.axis2.description.java2wsdl.Java2WSDLConstants;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.axis2.wsdl.WSDLUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.core.multitenancy.SuperTenantCarbonContext;
import org.wso2.carbon.dataservices.common.DBConstants;
import org.wso2.carbon.dataservices.common.DBConstants.DBSFields;
import org.wso2.carbon.dataservices.core.description.operation.Operation;
import org.wso2.carbon.dataservices.core.description.query.Query;
import org.wso2.carbon.dataservices.core.description.resource.Resource;
import org.wso2.carbon.dataservices.core.description.resource.Resource.ResourceID;
import org.wso2.carbon.dataservices.core.engine.*;
import org.wso2.carbon.dataservices.core.engine.CallQuery.WithParam;
import org.wso2.carbon.dataservices.core.internal.DataServicesDSComponent;
import org.wso2.carbon.dataservices.core.jmx.DataServiceInstance;
import org.wso2.carbon.dataservices.core.jmx.DataServiceInstanceMBean;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.CarbonUtils;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
/**
* Represents the custom Axis2 deployer used in deploying data-services .dbs files.
*/
public class DBDeployer extends AbstractDeployer {
public static final String HTTP_TRANSPORT = "http";
public static final String HTTPS_TRANSPORT = "https";
private static final Log log = LogFactory.getLog(DBDeployer.class);
/**
* Data Services directory name to be used in Axis2 service deployment
*/
public static final String DEPLOYMENT_FOLDER_NAME = "dataservices";
/**
* Current Axis2 AxisConfiguration
*/
private AxisConfiguration axisConfig;
/**
* Current Axis2 ConfigurationContext
*/
private ConfigurationContext configCtx;
/**
* Data Services repository directory
*/
private String repoDir;
/**
* Data Services file directory (i.e. '.dbs')
*/
private String extension;
/**
* used for REST processing
*/
private Map<String, AxisOperation> httpLocationTable;
public ConfigurationContext getConfigContext() {
return configCtx;
}
/**
* Deploys a data service with the given deployment data.
*/
public void deploy(DeploymentFileData deploymentFileData)
throws DeploymentException {
/* set the thread local variable to hold the tenant id */
try {
int tenantId = SuperTenantCarbonContext.getCurrentContext(this.configCtx).getTenantId();
SuperTenantCarbonContext.getCurrentContext().setTenantId(tenantId);
RealmService realmService = DataServicesDSComponent.getRealmService();
if (realmService != null) {
try {
SuperTenantCarbonContext.getCurrentContext().setUserRealm(realmService.getBootstrapRealm());
} catch (UserStoreException e) {
throw new DeploymentException(e);
}
}
SuperTenantCarbonContext.getCurrentContext().setUsername(CarbonConstants.REGISTRY_SYSTEM_USERNAME);
DBUtils.setDeploymentTimeTenantId(tenantId);
} catch (Error e) {
/* during unit tests, this may occur */
log.warn("Init error at DBDeployer.deploy()", e);
}
String serviceHierarchy = Utils.getServiceHierarchy(
deploymentFileData.getAbsolutePath(), this.repoDir);
if (serviceHierarchy == null){
serviceHierarchy = "";
}
/* state variable kept to check if the service was successfully deployed at the end */
boolean successfullyDeployed = false;
/* used to store the error message if there is a problem in deploying */
String errorMessage = null;
/* Axis2 service to be deployed */
AxisService service = null;
try {
String serviceGroupName = serviceHierarchy + this.getServiceGroupFromDSContents(
deploymentFileData.getFile());
AxisServiceGroup serviceGroup = this.axisConfig.getServiceGroup(serviceGroupName);
/* service active property */
boolean serviceActive = false;
if (serviceGroup != null) {
service = processService(deploymentFileData, serviceGroup, this.configCtx);
service.setName(serviceHierarchy + service.getName());
/* save original value */
serviceActive = service.isActive();
this.axisConfig.addServiceToExistingServiceGroup(service, serviceGroupName);
} else {
serviceGroup = new AxisServiceGroup();
serviceGroup.setServiceGroupName(serviceGroupName);
service = processService(deploymentFileData, serviceGroup, this.configCtx);
service.setName(serviceHierarchy + service.getName());
/* save original value */
serviceActive = service.isActive();
serviceGroup.addService(service);
this.axisConfig.addServiceGroup(serviceGroup);
}
/* restore original service active value */
service.setActive(serviceActive);
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage(DeploymentErrorMsgs.DEPLOYING_WS,
deploymentFileData.getName(), deploymentFileData.getAbsolutePath()));
}
/* finished deploying successfully */
successfullyDeployed = true;
/* the following section is to remove a faulty service, if there's one already registered */
String faultyServiceFilePath = deploymentFileData.getFile().getAbsolutePath();
AxisService faultyService = CarbonUtils.getFaultyService(faultyServiceFilePath, this.configCtx);
if (faultyService != null) {
this.axisConfig.removeFaultyService(faultyServiceFilePath);
}
super.deploy(deploymentFileData);
} catch (DataServiceFault e) {
errorMessage = DBUtils.getStacktraceFromException(e);
log.error(Messages.getMessage(DeploymentErrorMsgs.INVALID_SERVICE,
deploymentFileData.getName()), e);
/* if there is a request to re-schedule in the exception, do it .. */
if (DBConstants.FaultCodes.CONNECTION_UNAVAILABLE_ERROR.equals(e.getCode())) {
this.sheduleRedeploy(deploymentFileData, service);
}
DataService ds = e.getSourceDataService();
try {
ds.cleanup();
} catch (DataServiceFault e2) {
log.warn("Error in data service cleanup: " + e2.getMessage(), e2);
}
throw new DeploymentException(Messages.getMessage(
DeploymentErrorMsgs.INVALID_SERVICE,
deploymentFileData.getName()), e);
} catch (Throwable e) {
errorMessage = DBUtils.getStacktraceFromException(e);
log.error(Messages.getMessage(DeploymentErrorMsgs.INVALID_SERVICE,
deploymentFileData.getName()), e);
throw new DeploymentException(Messages.getMessage(
DeploymentErrorMsgs.INVALID_SERVICE,
deploymentFileData.getName()), e);
} finally {
if (!successfullyDeployed) {
String deploymentFilePath = deploymentFileData.getFile().getAbsolutePath();
/* Register the faulty service */
this.axisConfig.getFaultyServices().put(deploymentFilePath, errorMessage);
try {
CarbonUtils.registerFaultyService(deploymentFilePath,
DBConstants.DB_SERVICE_TYPE, configCtx);
} catch (Exception e) {
log.error("Cannot register faulty service with Carbon", e);
}
}
}
}
/**
* Creates a timer with a one minute delay, for re-deploying a data service.
*/
private void sheduleRedeploy(DeploymentFileData deploymentFileData, AxisService service) {
Runnable faultyServiceRectifier = new FaultyServiceRectifier(service,
deploymentFileData, configCtx);
/* Retry in one minute */
long retryIn = 1000 * 60;
DBUtils.scheduleTask(faultyServiceRectifier, retryIn);
}
/**
* Initializes the deployer.
*/
public void init(ConfigurationContext configCtx) {
this.configCtx = configCtx;
this.axisConfig = this.configCtx.getAxisConfiguration();
/* init is called after the setDirectory is called so setting the
* repoDir and the extension here. */
configCtx.setProperty(DBConstants.DB_SERVICE_REPO, this.repoDir);
configCtx.setProperty(DBConstants.DB_SERVICE_EXTENSION, this.extension);
configCtx.setProperty(DBConstants.DB_SERVICE_DEPLOYER, this);
}
public void setDirectory(String repoDir) {
this.repoDir = repoDir;
}
public String getRepoDir() {
return repoDir;
}
public void setExtension(String extension) {
this.extension = extension;
}
private DataService getDataServiceByServicePath(String servicePath) throws Exception {
Parameter tmpParam;
DataService tmpDS;
String canonicalServicePath = new File(servicePath).getCanonicalPath();
for (AxisService axisService : this.axisConfig.getServices().values()) {
tmpParam = axisService.getParameter(DBConstants.DATA_SERVICE_OBJECT);
if (tmpParam != null) {
tmpDS = (DataService) tmpParam.getValue();
if (new File(tmpDS.getDsLocation()).getCanonicalPath().equals(
canonicalServicePath)) {
return tmpDS;
}
}
}
//throw new DataServiceFault("Data service at '" + servicePath + "' cannot be found");
return null;
}
/**
* Undeploys a service.
*/
public void undeploy(String servicePath) throws DeploymentException {
try {
//set the thread local variable to hold the tenant id
int tenantId = SuperTenantCarbonContext.getCurrentContext(this.configCtx).getTenantId();
SuperTenantCarbonContext.getCurrentContext().setTenantId(tenantId);
DBUtils.setDeploymentTimeTenantId(tenantId);
DataService dataService = this.getDataServiceByServicePath(servicePath);
if (dataService == null) {
/* must be a faulty service */
return;
}
String serviceHierarchy = Utils.getServiceHierarchy(servicePath, this.repoDir);
if (serviceHierarchy == null){
serviceHierarchy = "";
}
String serviceGroupName = serviceHierarchy + dataService.getServiceGroup();
String serviceName = serviceHierarchy + dataService.getName();
AxisServiceGroup serviceGroup = this.axisConfig.getServiceGroup(serviceGroupName);
if (serviceGroup == null) { /* must be a faulty service */
this.axisConfig.removeFaultyService(servicePath);
} else {
/* cleanup data service */
dataService.cleanup();
this.axisConfig.removeService(serviceName);
/* if the service group is now empty, remove it as well */
if (!serviceGroup.getServices().hasNext()) {
/* when the service group is removed re-deployment causes problems */
this.axisConfig.removeServiceGroup(serviceGroup.getServiceGroupName());
}
}
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage(DeploymentErrorMsgs.SERVICE_REMOVED, serviceGroupName));
}
super.undeploy(servicePath);
} catch (Exception e) {
String msg = "Error in undeploying service";
log.error(msg, e);
throw new DeploymentException(msg, e);
}
}
private String getServiceGroupFromDSContents(File file) throws Exception {
StAXOMBuilder builder = new StAXOMBuilder(new FileInputStream(file.getAbsoluteFile()));
OMElement serviceEl = builder.getDocumentElement();
String serviceGroup = serviceEl.getAttributeValue(new QName(DBSFields.SERVICE_GROUP));
if (DBUtils.isEmptyString(serviceGroup)) {
serviceGroup = serviceEl.getAttributeValue(new QName(DBSFields.NAME));
}
builder.close();
if (DBUtils.isEmptyString(serviceGroup)) {
throw new DataServiceFault("Service group cannot be determined for the data service at '"
+ file.getAbsolutePath() + "'");
}
return serviceGroup;
}
/**
* Configuration files prior to multiple data source support did not have id attribute
* for config element. Adding that & saving.
*/
@SuppressWarnings("unchecked")
private void convertConfigToMultipleDSFormat(String configFilePath)
throws DataServiceFault {
FileInputStream fis = null;
boolean changed = false;
try {
fis = new FileInputStream(configFilePath);
OMElement configElement = (new StAXOMBuilder(fis)).getDocumentElement();
configElement.build();
Iterator<OMElement> configElements = configElement.getChildrenWithName(
new QName(DBSFields.CONFIG));
int emptyConfigs = 0;
while (configElements.hasNext()) {
OMElement config = configElements.next();
String configId = config.getAttributeValue(new QName(DBSFields.ID));
if (configId == null || configId.trim().length() == 0) {
config.addAttribute(DBSFields.ID, DBConstants.DEFAULT_CONFIG_ID, null);
changed = true;
emptyConfigs++;
if (emptyConfigs > 1) {
throw new DataServiceFault("More than one config elements found in " +
configFilePath);
}
}
}
Iterator<OMElement> queryElements = configElement.getChildrenWithName(new QName(DBSFields.QUERY));
while (queryElements.hasNext()) {
OMElement query = queryElements.next();
String useConfig = query.getAttributeValue(new QName(
DBSFields.USE_CONFIG));
if (useConfig == null || useConfig.trim().length() == 0) {
query.addAttribute(DBSFields.USE_CONFIG, DBConstants.DEFAULT_CONFIG_ID, null);
changed = true;
}
}
if (changed) {
if (log.isDebugEnabled()) {
log.debug("Converting " + configFilePath +
" to support multiple data sources.");
}
BufferedWriter out = new BufferedWriter(new FileWriter(configFilePath));
configElement.serialize(out);
out.close();
DBUtils.prettifyXMLFile(configFilePath);
}
} catch (Exception e) {
throw new DataServiceFault(e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
log.error("Error in closing data service configuration file", e);
}
}
}
}
/**
* Creates an AxisOperation with the given data service operation object.
* @see Operation
* @see AxisOperation
*/
private AxisOperation createAxisOperationFromDSOperation(Operation operation,
AxisBinding soap11Binding, AxisBinding soap12Binding,
AxisBinding httpBinding) throws AxisFault {
String opName = operation.getName();
String requestName = operation.getRequestName();
int index = opName.indexOf(":");
if (index > -1) {
opName = opName.substring(index + 1);
}
boolean hasResult = operation.getCallQueryGroup().isHasResult()
|| operation.isReturnRequestStatus();
String description = operation.getDescription();
return createAxisOperation(requestName, opName, HTTPConstants.HTTP_METHOD_POST, hasResult,
soap11Binding, soap12Binding, httpBinding, description);
}
/**
* Creates an AxisOperation with the given data service resource object.
* @see Operation
* @see AxisOperation
*/
private AxisOperation createAxisOperationFromDSResource(Resource resource,
AxisBinding soap11Binding, AxisBinding soap12Binding,
AxisBinding httpBinding) {
ResourceID resourceId = resource.getResourceId();
String method = resourceId.getMethod();
String path = resourceId.getPath();
String requestName = resource.getRequestName();
String description = resource.getDescription();
boolean hasResult = resource.getCallQueryGroup().isHasResult()
|| resource.isReturnRequestStatus();
return createAxisOperation(requestName, path, method, hasResult, soap11Binding,
soap12Binding, httpBinding, description);
}
/**
* Utility method for creating AxisOperation objects.
*/
private AxisOperation createAxisOperation(String operationName, String httpLocation,
String method, boolean hasResult,
AxisBinding soap11Binding, AxisBinding soap12Binding, AxisBinding httpBinding,
String description) {
AxisOperation axisOperation = null;
if (hasResult) {
axisOperation = new InOutAxisOperation(new QName(operationName));
DBInOutMessageReceiver inoutMsgReceiver = new DBInOutMessageReceiver();
axisOperation.setMessageReceiver(inoutMsgReceiver);
axisOperation.setMessageExchangePattern(WSDL2Constants.MEP_URI_IN_OUT);
} else {
axisOperation = new InOnlyAxisOperation(new QName(operationName));
DBInOnlyMessageReceiver inonlyMsgReceiver = new DBInOnlyMessageReceiver();
axisOperation.setMessageReceiver(inonlyMsgReceiver);
axisOperation.setMessageExchangePattern(WSDL2Constants.MEP_URI_ROBUST_IN_ONLY);
}
axisOperation.setStyle(WSDLConstants.STYLE_DOC);
String opName = axisOperation.getName().getLocalPart();
// Create a default SOAP 1.1 Binding operation
AxisBindingOperation soap11BindingOperation = createDefaultSOAP11BindingOperation(
axisOperation, httpLocation, "urn:" + opName, soap11Binding);
// Create a default SOAP 1.2 Binding operation
AxisBindingOperation soap12BindingOperation = createDefaultSOAP12BindingOperation(
axisOperation, httpLocation, "urn:" + opName, soap12Binding);
// Create a default HTTP Binding operation
AxisBindingOperation httpBindingOperation = createDefaultHTTPBindingOperation(
axisOperation, httpLocation, method, httpBinding);
String httpLocationString = WSDLUtil.getConstantFromHTTPLocation(httpLocation, method);
this.httpLocationTable.put(httpLocationString, axisOperation);
// Create the in and out axis messages for this operation
AxisMessage inMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if (inMessage != null) {
inMessage.setName(operationName + Java2WSDLConstants.MESSAGE_SUFFIX);
createAxisBindingMessage(soap11BindingOperation, inMessage, WSDLConstants.MESSAGE_LABEL_IN_VALUE, false);
createAxisBindingMessage(soap12BindingOperation, inMessage, WSDLConstants.MESSAGE_LABEL_IN_VALUE, false);
createAxisBindingMessage(httpBindingOperation, inMessage, WSDLConstants.MESSAGE_LABEL_IN_VALUE, false);
}
if (axisOperation instanceof InOutAxisOperation) {
AxisMessage outMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
if (outMessage != null) {
outMessage.setName(operationName + Java2WSDLConstants.RESPONSE_MESSAGE);
createAxisBindingMessage(soap11BindingOperation, outMessage, WSDLConstants.MESSAGE_LABEL_OUT_VALUE, false);
createAxisBindingMessage(soap12BindingOperation, outMessage, WSDLConstants.MESSAGE_LABEL_OUT_VALUE, false);
createAxisBindingMessage(httpBindingOperation, outMessage, WSDLConstants.MESSAGE_LABEL_OUT_VALUE, false);
}
}
AxisMessage faultMessage = new AxisMessage();
faultMessage.setName(DBConstants.DS_FAULT_ELEMENT);
faultMessage.setElementQName(new QName(DBConstants.WSO2_DS_NAMESPACE, DBConstants.DS_FAULT_ELEMENT));
axisOperation.setFaultMessages(faultMessage);
createAxisBindingMessage(soap11BindingOperation, faultMessage, WSDLConstants.MESSAGE_LABEL_FAULT_VALUE, true);
createAxisBindingMessage(soap12BindingOperation, faultMessage, WSDLConstants.MESSAGE_LABEL_FAULT_VALUE, true);
createAxisBindingMessage(httpBindingOperation, faultMessage, WSDLConstants.MESSAGE_LABEL_FAULT_VALUE, true);
axisOperation.setDocumentation(description);
return axisOperation;
}
/**
* Creates a schema from a DataService object, to be used later in WSDL generation.
*/
@SuppressWarnings ("unchecked")
private void createDSSchema(AxisService axisService, DataService dataService)
throws DataServiceFault {
NamespaceMap map = new NamespaceMap();
map.put(Java2WSDLConstants.DEFAULT_SCHEMA_NAMESPACE_PREFIX,
Java2WSDLConstants.URI_2001_SCHEMA_XSD);
axisService.setNamespaceMap(map);
DataServiceDocLitWrappedSchemaGenerator.populateServiceSchema(axisService);
}
/**
* Validate the data service to see if the data service is invalid.
*/
private void validateDataService(DataService dataService) throws DataServiceFault {
this.validateRequestCallQuery(dataService);
this.validateRequestQueryParams(dataService);
this.validateRequestQueryResults(dataService);
}
/**
* Check call-queries of callable requests (i.e. operations, resources) to see if the queries
* exists.
*/
private void validateRequestCallQuery(DataService dataService) throws DataServiceFault {
for (CallableRequest cr : dataService.getCallableRequests().values()) {
for (CallQuery callQuery : cr.getCallQueryGroup().getCallQueries()) {
if (callQuery.getQuery() == null) {
DataServiceFault dsf = new DataServiceFault("Invalid DBS",
"Call query with id: " + callQuery.getQueryId() +
" doesn't exist as referenced by the operation/resource: " +
cr.getRequestName());
dsf.setSourceDataService(dataService);
throw dsf;
}
}
}
}
/**
* Check query-params if they exist in the query as mentioned in the 'with-params' in
* operation/resource, the computational complexity of this code is not an issue, since this is
* deployment time.
*/
private void validateRequestQueryParams(DataService dataService) throws DataServiceFault {
for (CallableRequest cr : dataService.getCallableRequests().values()) {
for (CallQuery callQuery : cr.getCallQueryGroup().getCallQueries()) {
Query query = callQuery.getQuery();
for (WithParam withParam : callQuery.getWithParams().values()) {
boolean found = false;
for (QueryParam queryParam : query.getQueryParams()) {
if (withParam.getName().equals(queryParam.getName())) {
found = true;
break;
}
}
if (found) {
/* param found, move onto next 'with-param' */
continue;
} else {
/* the param is not found in the query, throw an exception */
DataServiceFault dsf = new DataServiceFault("Invalid DBS",
"with-param with name: " + withParam.getName()
+ " doesn't exist in query with id: " + query.getQueryId()
+ " as referenced by the operation/resource: "
+ cr.getRequestName());
dsf.setSourceDataService(dataService);
throw dsf;
}
}
}
}
}
/**
* Check if an request's query has a result, and if that result contain an element wrapper.
*/
private void validateRequestQueryResults(DataService dataService) throws DataServiceFault {
for (CallableRequest request : dataService.getCallableRequests().values()) {
CallQueryGroup cqGroup = request.getCallQueryGroup();
if (cqGroup == null) {
/* we are not validating these here */
continue;
}
CallQuery callQuery = cqGroup.getDefaultCallQuery();
if (callQuery == null) {
continue;
}
Query query = callQuery.getQuery();
if (query == null) {
continue;
}
if (query.getResult() != null) {
if (DBUtils.isEmptyString(query.getResult().getElementName())) {
throw new DataServiceFault("The request '" + request.getRequestName()
+ "' contains the query with id '" + query.getQueryId()
+ "' contains a result with no element wrapper.");
}
}
}
}
/**
* Creates AxisService from DBS.
*/
private AxisService createDBService(String configFilePath,
AxisConfiguration axisConfiguration) throws DataServiceFault {
FileInputStream fis = null;
try {
/* convert to multiple config format */
convertConfigToMultipleDSFormat(configFilePath);
fis = new FileInputStream(configFilePath);
OMElement dbsElement = (new StAXOMBuilder(fis)).getDocumentElement();
dbsElement.build();
/* create the data service object from dbs */
DataService dataService = DataServiceFactory.createDataService(
dbsElement, configFilePath);
/* validate the data service */
this.validateDataService(dataService);
String serviceName = dataService.getName();
String interfaceName = serviceName + WSDL2Constants.INTERFACE_PREFIX;
AxisService axisService = new AxisService(serviceName);
try {
axisService.setFileName(new URL("file://" + configFilePath));
} catch (MalformedURLException e) {
throw new DataServiceFault(e);
}
/* set service target namespace */
axisService.setTargetNamespace(dataService.getServiceNamespace());
/* Used by the container to find out what kind of a service this is. */
axisService.addParameter(new Parameter(DBConstants.AXIS2_SERVICE_TYPE,
DBConstants.DB_SERVICE_TYPE));
/* save the data service object in the AxisService */
axisService.addParameter(DBConstants.DATA_SERVICE_OBJECT, dataService);
/* set service description */
axisService.setDocumentation(dataService.getDescription());
this.httpLocationTable = new TreeMap<String, AxisOperation>(
new Comparator<String>() {
public int compare(String o1, String o2) {
return (-1 * o1.compareTo(o2));
}
});
AxisBinding soap11Binding = createDefaultSOAP11Binding(
serviceName, interfaceName);
AxisBinding soap12Binding = createDefaultSOAP12Binding(
serviceName, interfaceName);
AxisBinding httpBinding = createDefaultHTTPBinding(serviceName,
interfaceName);
/* REST processing - adding DS resources to AxisService */
Set<ResourceID> resourceIds = dataService.getResourceIds();
for (ResourceID resourceId : resourceIds) {
Resource resource = dataService.getResource(resourceId);
AxisOperation axisOperation = createAxisOperationFromDSResource(
resource, soap11Binding, soap12Binding, httpBinding);
axisService.addOperation(axisOperation);
axisConfig.getPhasesInfo().setOperationPhases(axisOperation);
}
/* add operations */
Iterator<String> opPathItr = dataService.getOperationNames()
.iterator();
while (opPathItr.hasNext()) {
Operation operation = dataService
.getOperation(opPathItr.next());
AxisOperation axisOperation = createAxisOperationFromDSOperation(
operation, soap11Binding, soap12Binding, httpBinding);
axisService.addOperation(axisOperation);
axisConfig.getPhasesInfo().setOperationPhases(axisOperation);
}
createDefaultEndpoints(axisService, soap11Binding, soap12Binding,
httpBinding);
/* create schema */
createDSSchema(axisService, dataService);
/* set session scope type for boxcarring */
if (dataService.isBoxcarringEnabled()) {
axisService.setScope(Constants.SCOPE_TRANSPORT_SESSION);
}
/* register JMX MBean */
this.registerMBean(dataService);
/* set service status */
axisService.setActive(!dataService.isServiceInactive());
return axisService;
} catch (FileNotFoundException e) {
throw new DataServiceFault(e, "Error reading service configuration file.");
} catch (XMLStreamException e) {
throw new DataServiceFault(e, "Error while parsing the service configuration file.");
} catch (AxisFault e) {
throw new DataServiceFault(e);
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
log.error("Error in closing data services configuration file", e);
}
}
}
/**
* Registers an MBean representing the given data service.
*/
private void registerMBean(DataService dataService) {
DataServiceInstanceMBean dsMBean = new DataServiceInstance(dataService);
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
if (server != null) {
try {
ObjectName objectName = new ObjectName(DBConstants.DATA_SERVICES_JMX_DOMAIN +
":section=Services,service=" +
dsMBean.getServiceName());
try {
server.unregisterMBean(objectName);
} catch (Exception ignore) {
/* ignore if it doesn't exist */
}
server.registerMBean(dsMBean, objectName);
} catch (Exception e) {
log.error("Error in Registering Data Services MBean", e);
}
}
}
/**
* Creates AxisBindingMessage and populates it.
*/
private void createAxisBindingMessage(
AxisBindingOperation bindingOperation, AxisMessage inMessage, String label, boolean isFault) {
AxisBindingMessage soap11InBindingMessage = new AxisBindingMessage();
soap11InBindingMessage.setName(inMessage.getName());
soap11InBindingMessage.setAxisMessage(inMessage);
soap11InBindingMessage.setParent(bindingOperation);
if (isFault) {
soap11InBindingMessage.setFault(true);
bindingOperation.addFault(soap11InBindingMessage);
} else {
soap11InBindingMessage.setFault(false);
bindingOperation.addChild(label, soap11InBindingMessage);
}
}
/**
* Creates AxisBindingOperation and populates it with HTTP properties
*/
private AxisBindingOperation createDefaultHTTPBindingOperation(
AxisOperation axisOp, String httpLocation, String httpMethod,
AxisBinding httpBinding) {
AxisBindingOperation httpBindingOperation = new AxisBindingOperation();
httpBindingOperation.setAxisOperation(axisOp);
httpBindingOperation.setName(axisOp.getName());
httpBindingOperation.setParent(httpBinding);
httpBindingOperation.setProperty(WSDL2Constants.ATTR_WHTTP_LOCATION, httpLocation);
httpBindingOperation.setProperty(WSDL2Constants.ATTR_WHTTP_METHOD, httpMethod);
httpBinding.addChild(httpBindingOperation.getName(), httpBindingOperation);
return httpBindingOperation;
}
/**
* Creates AxisBindingOperation and populates it with SOAP 1.2 properties
*/
private AxisBindingOperation createDefaultSOAP12BindingOperation(
AxisOperation axisOp, String httpLocation, String inputAction,
AxisBinding soap12Binding) {
AxisBindingOperation soap12BindingOperation = new AxisBindingOperation();
soap12BindingOperation.setAxisOperation(axisOp);
soap12BindingOperation.setName(axisOp.getName());
soap12BindingOperation.setParent(soap12Binding);
soap12BindingOperation.setProperty(WSDL2Constants.ATTR_WHTTP_LOCATION,
httpLocation);
soap12Binding.addChild(soap12BindingOperation.getName(),
soap12BindingOperation);
soap12BindingOperation.setProperty(WSDL2Constants.ATTR_WSOAP_ACTION,
inputAction);
return soap12BindingOperation;
}
/**
* Creates AxisBindingOperation and populates it with SOAP 1.1 properties
*/
private AxisBindingOperation createDefaultSOAP11BindingOperation(
AxisOperation axisOp, String httpLocation, String inputAction,
AxisBinding soap11Binding) {
AxisBindingOperation soap11BindingOperation = new AxisBindingOperation();
soap11BindingOperation.setAxisOperation(axisOp);
soap11BindingOperation.setName(axisOp.getName());
soap11BindingOperation.setParent(soap11Binding);
soap11BindingOperation.setProperty(WSDL2Constants.ATTR_WHTTP_LOCATION,
httpLocation);
soap11Binding.addChild(soap11BindingOperation.getName(),
soap11BindingOperation);
soap11BindingOperation.setProperty(WSDL2Constants.ATTR_WSOAP_ACTION,
inputAction);
return soap11BindingOperation;
}
/**
* Creates a AxisBinding and populates it with default SOAP 1.1 properties
*/
private AxisBinding createDefaultSOAP11Binding(String name, String interfaceName) {
AxisBinding soap11Binding = new AxisBinding();
soap11Binding.setName(new QName(name + Java2WSDLConstants.BINDING_NAME_SUFFIX));
soap11Binding.setType(WSDL2Constants.URI_WSDL2_SOAP);
soap11Binding.setProperty(WSDL2Constants.ATTR_WSOAP_PROTOCOL,
WSDL2Constants.HTTP_PROTOCAL);
soap11Binding.setProperty(WSDL2Constants.ATTR_WSOAP_VERSION,
SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
soap11Binding.setProperty(WSDL2Constants.INTERFACE_LOCAL_NAME, interfaceName);
soap11Binding.setProperty(WSDL2Constants.HTTP_LOCATION_TABLE, httpLocationTable);
return soap11Binding;
}
/**
* Creates a AxisBinding and populates it with default HTTP properties
*/
private AxisBinding createDefaultHTTPBinding(String name, String interfaceName) {
AxisBinding httpBinding = new AxisBinding();
httpBinding.setName(new QName(name + Java2WSDLConstants.HTTP_BINDING));
httpBinding.setType(WSDL2Constants.URI_WSDL2_HTTP);
httpBinding.setProperty(WSDL2Constants.INTERFACE_LOCAL_NAME, interfaceName);
httpBinding.setProperty(WSDL2Constants.HTTP_LOCATION_TABLE, httpLocationTable);
return httpBinding;
}
/**
* Creates a AxisBinding and populates it with default SOAP 1.2 properties
*/
private AxisBinding createDefaultSOAP12Binding(String name, String interfaceName) {
AxisBinding soap12Binding = new AxisBinding();
soap12Binding.setName(new QName(name + Java2WSDLConstants.SOAP12BINDING_NAME_SUFFIX));
soap12Binding.setType(WSDL2Constants.URI_WSDL2_SOAP);
soap12Binding.setProperty(WSDL2Constants.ATTR_WSOAP_PROTOCOL,
WSDL2Constants.HTTP_PROTOCAL);
soap12Binding.setProperty(WSDL2Constants.ATTR_WSOAP_VERSION,
SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
soap12Binding.setProperty(WSDL2Constants.INTERFACE_LOCAL_NAME, interfaceName);
soap12Binding.setProperty(WSDL2Constants.HTTP_LOCATION_TABLE, httpLocationTable);
return soap12Binding;
}
/**
* Creates a set of default endpoints for this service
*/
private void createDefaultEndpoints(AxisService axisService, AxisBinding soap11Binding,
AxisBinding soap12Binding, AxisBinding httpBinding) {
Map<String, TransportInDescription> transportsIn = axisConfig.getTransportsIn();
Iterator<TransportInDescription> iterator = transportsIn.values().iterator();
while (iterator.hasNext()) {
/*
* Used to indicate whether a HTTPEndpoint is needed. Http endpoint
* is needed only for http and https transports
*/
boolean needHttp = false;
/* The prefix is used to generate endpoint names */
String prefix = "";
TransportInDescription transportIn = iterator.next();
String transportInName = transportIn.getName();
if (HTTP_TRANSPORT.equalsIgnoreCase(transportInName)) {
needHttp = true;
} else if (HTTPS_TRANSPORT.equalsIgnoreCase(transportInName)) {
needHttp = true;
prefix = WSDL2Constants.DEFAULT_HTTPS_PREFIX;
} else if (transportInName != null) {
prefix = transportInName.toUpperCase();
}
/* Creates a default SOAP 1.1 endpoint */
AxisEndpoint soap11Endpoint = new AxisEndpoint();
String soap11EndpointName = prefix
+ WSDL2Constants.DEFAULT_SOAP11_ENDPOINT_NAME;
soap11Endpoint.setName(soap11EndpointName);
soap11Endpoint.setBinding(soap11Binding);
soap11Endpoint.setParent(axisService);
soap11Endpoint.setTransportInDescription(transportInName);
soap11Endpoint.setProperty(WSDL2Constants.HTTP_LOCATION_TABLE, httpLocationTable);
axisService.addEndpoint(soap11EndpointName, soap11Endpoint);
/* setting soap11 endpoint as the default endpoint */
axisService.setEndpointName(soap11EndpointName);
/* Creates a default SOAP 1.2 endpoint */
AxisEndpoint soap12Endpoint = new AxisEndpoint();
String soap12EndpointName = prefix
+ WSDL2Constants.DEFAULT_SOAP12_ENDPOINT_NAME;
soap12Endpoint.setName(soap12EndpointName);
soap12Endpoint.setBinding(soap12Binding);
soap12Endpoint.setParent(axisService);
soap12Endpoint.setTransportInDescription(transportInName);
soap12Endpoint.setProperty(WSDL2Constants.HTTP_LOCATION_TABLE, httpLocationTable);
axisService.addEndpoint(soap12EndpointName, soap12Endpoint);
/* Creates a HTTP endpoint if its http or https transport is used */
if (needHttp) {
AxisEndpoint httpEndpoint = new AxisEndpoint();
String httpEndpointName = prefix
+ WSDL2Constants.DEFAULT_HTTP_ENDPOINT_NAME;
httpEndpoint.setName(httpEndpointName);
httpEndpoint.setBinding(httpBinding);
httpEndpoint.setParent(axisService);
httpEndpoint.setTransportInDescription(transportInName);
httpEndpoint.setProperty(WSDL2Constants.HTTP_LOCATION_TABLE, httpLocationTable);
axisService.addEndpoint(httpEndpointName, httpEndpoint);
}
}
}
/**
* This method checks if the given data service has a corresponding "services.xml" is available,
* if so, the AxisService representing the data service is applied the instructions from its
* "services.xml".
*/
private AxisService handleServicesXML(String dbsPath, AxisServiceGroup axisServiceGroup,
AxisService axisService) throws DataServiceFault {
try {
String serviceXMLPath = dbsPath.substring(0, dbsPath.length() - 4) +
DBConstants.DBS_SERVICES_XML_SUFFIX;
File servicesXMLFile = new File(serviceXMLPath);
if (servicesXMLFile.exists()) {
XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(
new FileInputStream(servicesXMLFile));
StAXOMBuilder builder = new StAXOMBuilder(parser);
OMElement documentElement = builder.getDocumentElement();
if (documentElement.getLocalName().equals(DBConstants.AXIS2_SERVICE_GROUP)) {
HashMap<String, AxisService> wsdlServices = new HashMap<String, AxisService>();
wsdlServices.put(axisService.getName(), axisService);
ServiceGroupBuilder sgb = new ServiceGroupBuilder(documentElement,
wsdlServices, this.getConfigContext());
axisService = sgb.populateServiceGroup(axisServiceGroup).get(0);
} else if (documentElement.getLocalName().equals(DBConstants.AXIS2_SERVICE)) {
ServiceBuilder sb = new ServiceBuilder(this.getConfigContext(),
axisService);
axisService = sb.populateService(documentElement);
} else {
throw new DataServiceFault("services xml file: " + serviceXMLPath +
" is not valid, cannot find the 'service' or 'serviceGroup' element");
}
}
} catch (Exception e) {
throw new DataServiceFault(e, "Error in processing services.xml");
}
return axisService;
}
/**
* Creates AxisService with the given deployment information.
*/
private AxisService processService(DeploymentFileData currentFile,
AxisServiceGroup axisServiceGroup, ConfigurationContext configCtx)
throws DataServiceFault {
AxisService axisService = createDBService(currentFile.getAbsolutePath(),
configCtx.getAxisConfiguration());
axisService.setParent(axisServiceGroup);
axisService.setClassLoader(axisConfig.getServiceClassLoader());
/* handle services.xml, if exists */
this.handleServicesXML(currentFile.getAbsolutePath(), axisServiceGroup, axisService);
return axisService;
}
}