/*
Service level java script annotations processing. We create a
JavaScriptEngine and load the scripts and the associated host
objects.
*/
JavaScriptEngine engine = new JavaScriptEngine(jsFileNameShort);
/*
We inject the AxisService & ConfigContext as a workaround for not
having the MessageContext injected in the deployment time. Some host objects need
data from them at the initialize time.
*/
engine.getCx().putThreadLocal(MashupConstants.AXIS2_SERVICE, axisService);
engine.getCx().putThreadLocal(MashupConstants.AXIS2_CONFIGURATION_CONTEXT, configCtx);
/*
Load the JavaScriptHostObjects that are specified using the OSGI header
JavaScript-HostObject
*/
JavaScriptEngineUtils.loadHostObjects(engine, jsFileNameShort);
FileInputStream fileInputStream = new FileInputStream(jsFile);
// load the service java script file
engine.evaluate(new BufferedReader(new InputStreamReader(fileInputStream)));
// Use the JavaScriptServiceAnnotationParser to extract serviceLevel annotations
JavaScriptServiceAnnotationParser serviceAnnotationParser =
new JavaScriptServiceAnnotationParser(engine, jsFileNameShort);
axisService.setParent(axisServiceGroup);
axisService.setClassLoader(deploymentFileData.getClassLoader());
String serviceName = serviceAnnotationParser.getServiceName();
// Setting Axis Parameters given in serviceParameters annotation
Object serviceParametersObject = serviceAnnotationParser.getServiceParameters();
if (serviceParametersObject instanceof NativeObject) {
NativeObject nativeObject = (NativeObject) serviceParametersObject;
Object[] propertyNames = nativeObject.getIds();
for (Object propertyNameObject : propertyNames) {
if (propertyNameObject instanceof String) {
String propertyName = (String) propertyNameObject;
Object propertyValueObject = nativeObject.get(propertyName, nativeObject);
if (propertyValueObject instanceof String) {
try {
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement parameterElement = factory.createOMElement("parameter", null);
parameterElement.addAttribute("name", propertyName, null);
parameterElement.setText((String) propertyValueObject);
Parameter param = new Parameter(propertyName, propertyValueObject);
param.setParameterElement(parameterElement);
axisService.addParameter(param);
} catch (AxisFault axisFault) {
throw new DeploymentException(
"Error adding service parameter : " + propertyName,
axisFault);
}
} else if (propertyValueObject instanceof XML) {
XML xml = (XML) propertyValueObject;
OMNode axiom = xml.getAxiomFromXML();
try {
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement parameterElement = factory.createOMElement("parameter", null);
parameterElement.addAttribute("name", propertyName, null);
parameterElement.addChild(axiom);
Parameter param = new Parameter(propertyName, axiom);
param.setParameterElement(parameterElement);
axisService.addParameter(param);
} catch (AxisFault axisFault) {
throw new DeploymentException(
"Error adding service parameter : " + propertyName,
axisFault);
}
} else if (propertyValueObject instanceof XMLList) {
XMLList list = (XMLList) propertyValueObject;
OMNode[] omNodes = list.getAxiomFromXML();
try {
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement parameterElement = factory.createOMElement("parameter", null);
parameterElement.addAttribute("name", propertyName, null);
for (OMNode node : omNodes) {
parameterElement.addChild(node);
}
Parameter param = new Parameter(propertyName, omNodes);
param.setParameterElement(parameterElement);
axisService.addParameter(param);
} catch (AxisFault axisFault) {
throw new DeploymentException(
"Error adding service parameter : " + propertyName,
axisFault);
}
} else {
throw new DeploymentException("Invalid property value specified for " +
"\"serviceProperties\" annotation : " + propertyName +
". You should provide a string for property value.");
}
} else {
throw new DeploymentException("Invalid property name specified for " +
"\"serviceProperties\" annotation : " + propertyNameObject);
}
}
}
/*
Checks the validity of the serviceName. If the serviceName is invalid an exception is
thrown
*/
JSUtils.validateName(serviceName, SERVICE_NAME);
/*
Although Mashup Server supports only one service per *.js file at the moment, we set
the service group name as a combination of author name and *.js file name. If the
mashup was created manually on the file system, then the parent directory of the
mashup will be used as the prefix.
*/
axisServiceGroup.setServiceGroupName(
username + MashupConstants.SEPARATOR_CHAR + jsFileNameShort);
/*
All mashup services are deployed under the authors name with the help of Axis2's
hierarchical service deployment model. So each service name is prefixed
by author name.
*/
axisService.setName(username + MashupConstants.SEPARATOR_CHAR + serviceName);
// Sets the namespace map which is defined using this.targetNamespace
String targetNamespace = serviceAnnotationParser.getTargetNamespace();
axisService.setTargetNamespace(targetNamespace);
/*
Sets the scope of the service, this is defined as a service level annotation in the mashup i.e.
this.scope = "application | soapsession | transportsession | request"
*/
axisService.setScope(serviceAnnotationParser.getServiceScope());
// Sets service documentation which is defined using this.documentation annotation
axisService.setDocumentation(serviceAnnotationParser.getServiceDocumentation());
// Sets the namespace map which is defined using this.schemaTargetNamespace
SchemaGenerator schemaGenerator =
new SchemaGenerator(serviceAnnotationParser.getSchemaTargetNamespace());
axisService.setNamespaceMap(schemaGenerator.getNamespaceMap());
/*
The interfaceName is used by org.apache.axis2.description.AxisService2WSDL20 to
set the interface during ?wsdl2
*/
String interfaceName = serviceName + WSDL2Constants.INTERFACE_PREFIX;
axisService.addParameter(WSDL2Constants.INTERFACE_LOCAL_NAME, interfaceName);
/*
Set a comparator so tha httpLocations are stored in descending order. We want the
HTTPLocationBasedDiapatcher to make the best match hence we need them in descending
order
*/
httpLocationTable = new TreeMap<String, AxisOperation>(new Comparator() {
public int compare(Object o1, Object o2) {
return (-1 * ((Comparable) o1).compareTo(o2));
}
});
/*
We create the AxisBinding Hierarchy in here. In the Mashup Server we take complete
control of the Axis2 binding hierarchy cause we need to specify some HTTPBinding
properties such as httpMethod and httpLocation
*/
String bindingPrefix = username.replace('/', '-') + "-" + serviceName + "-";
// Create a default SOAP 1.1 Binding
createDefaultSOAP11Binding(bindingPrefix, interfaceName);
// Create a default SOAP 1.2 Binding
createDefaultSOAP12Binding(bindingPrefix, interfaceName);
// Create a default HTTP Binding
createDefaultHTTPBinding(bindingPrefix, interfaceName);
/*
We need to get all transports from the axis2 engine and create endpoints for each of
those in here
*/
createDefaultEndpoints(axisService);
// Obtain the list of functions in the java script service and process each one of them.
Object[] ids = engine.getIds();
for (Object id : ids) {
String method = (String) id;
Object object = engine.get(method, engine);
// some id's are not functions
if (object instanceof Function) {
processOperation(engine, axisService, method, (Function) object,
schemaGenerator, targetNamespace);
}
}
axisService.addSchema(schemaGenerator.getSchema());
Function init = serviceAnnotationParser.getInit();
Function destroy = serviceAnnotationParser.getDestroy();
/*
this.init and this.destroy correspond to service lifecycle functions.
this.init is called upon service deployment and this.destroy is called on
undeployment.
*/
if (init != null) {
JavaScriptEngineUtils.loadHostObjects(engine, serviceName);
init.call(engine.getCx(), engine, engine, new Object[0]);
}
if (destroy != null) {
axisService.addParameter(JSConstants.MASHUP_DESTROY_FUNCTION, destroy);
}