/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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.apache.tuscany.sca.implementation.widget.dojo; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import javax.xml.namespace.QName; import org.apache.tuscany.sca.assembly.Binding; import org.apache.tuscany.sca.assembly.ComponentProperty; import org.apache.tuscany.sca.assembly.ComponentReference; import org.apache.tuscany.sca.assembly.Endpoint; import org.apache.tuscany.sca.assembly.EndpointReference; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.runtime.RuntimeComponent; import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; import org.apache.tuscany.sca.web.javascript.ComponentJavaScriptGenerator; import org.apache.tuscany.sca.web.javascript.JavascriptProxyFactory; import org.apache.tuscany.sca.web.javascript.JavascriptProxyFactoryExtensionPoint; import org.w3c.dom.Document; import org.w3c.dom.Element; public class DojoJavaScriptComponentGeneratorImpl implements ComponentJavaScriptGenerator { private static final QName NAME = new QName("http://tuscany.apache.org/xmlns/sca/1.1", "component.script.generator.dojo"); private ExtensionPointRegistry extensionPoints; private JavascriptProxyFactoryExtensionPoint javascriptProxyFactories; public DojoJavaScriptComponentGeneratorImpl(ExtensionPointRegistry extensionPoints) { this.extensionPoints = extensionPoints; this.javascriptProxyFactories = extensionPoints.getExtensionPoint(JavascriptProxyFactoryExtensionPoint.class); } public QName getQName() { return NAME; } public void generateJavaScriptCode(RuntimeComponent component, PrintWriter pw) throws IOException { pw.println(); pw.println("/* Apache Tuscany SCA Widget header */"); pw.println(); Map<String, Boolean> bindingClientProcessed = new HashMap<String, Boolean>(); for(ComponentReference reference : component.getReferences()) { for(EndpointReference epr : reference.getEndpointReferences()) { Endpoint targetEndpoint = epr.getTargetEndpoint(); if (targetEndpoint.isUnresolved()) { //force resolution and targetEndpoint binding calculations //by calling the getInvocationChain ((RuntimeEndpointReference) epr).getInvocationChains(); targetEndpoint = epr.getTargetEndpoint(); } Binding binding = targetEndpoint.getBinding(); if (binding != null) { JavascriptProxyFactory jsProxyFactory = javascriptProxyFactories.getProxyFactory(binding.getClass()); String bindingProxyName = jsProxyFactory.getJavascriptProxyFile(); //check if binding client code was already processed and inject to the generated script if(bindingProxyName != null) { Boolean processedFlag = bindingClientProcessed.get(bindingProxyName); if( processedFlag == null || processedFlag.booleanValue() == false) { generateJavaScriptBindingProxy(jsProxyFactory, pw); bindingClientProcessed.put(bindingProxyName, Boolean.TRUE); } } } } } pw.println(); pw.println("/* Tuscany Reference/Property injection code */"); pw.println(); generateJavaScriptHeader(component, javascriptProxyFactories,pw); pw.println(); //define tuscany.sca namespace generateJavaScriptNamespace(pw); pw.println(); //process properties generateJavaScriptPropertyFunction(component, pw); pw.println(); //process references generateJavaScriptReferenceFunction(component, javascriptProxyFactories,pw); pw.println(); pw.println("/** End of Apache Tuscany SCA Widget */"); pw.println(); pw.flush(); pw.close(); } /** * Retrieve the binding proxy based on the bind name * and embedded the JavaScript into this js */ private static void generateJavaScriptBindingProxy(JavascriptProxyFactory javascriptProxyFactory, PrintWriter pw) throws IOException { InputStream is = javascriptProxyFactory.getJavascriptProxyFileAsStream(); if (is != null) { int i; while ((i = is.read()) != -1) { pw.write(i); } } pw.println(); pw.println(); } /** * * @param pw * @throws IOException */ private static void generateJavaScriptHeader(RuntimeComponent component, JavascriptProxyFactoryExtensionPoint javascriptProxyFactories, PrintWriter pw) throws IOException { Map<String, Boolean> bindingHeaderProcessed = new HashMap<String, Boolean>(); for(ComponentReference reference : component.getReferences()) { for(EndpointReference epr : reference.getEndpointReferences()) { Endpoint targetEndpoint = epr.getTargetEndpoint(); if (targetEndpoint.isUnresolved()) { //force resolution and targetEndpoint binding calculations //by calling the getInvocationChain ((RuntimeEndpointReference) epr).getInvocationChains(); targetEndpoint = epr.getTargetEndpoint(); } Binding binding = targetEndpoint.getBinding(); if (binding != null) { JavascriptProxyFactory jsProxyFactory = javascriptProxyFactories.getProxyFactory(binding.getClass()); String bindingKey = binding.getClass().getName(); Boolean processedFlag = bindingHeaderProcessed.get(bindingKey); //check if binding client code was already processed and inject to the generated script if( processedFlag == null || processedFlag.booleanValue() == false) { pw.println(jsProxyFactory.createJavascriptHeader(reference)); bindingHeaderProcessed.put(bindingKey, Boolean.TRUE); } } } } } /** * Generate the tuscany.sca namespace if not yet available * @param pw * @throws IOException */ private static void generateJavaScriptNamespace(PrintWriter pw) throws IOException { pw.println("if (!window.tuscany) { \n" + "window.tuscany = {}; \n" + "}"); pw.println("var __tuscany = window.tuscany;"); pw.println("if (!__tuscany.sca) { \n" + "__tuscany.sca = {}; \n" + "}"); } /** * Generate JavaScript code to inject SCA Properties * @param pw * @throws IOException */ private static void generateJavaScriptPropertyFunction(RuntimeComponent component, PrintWriter pw) throws IOException { pw.println("__tuscany.sca.propertyMap = {};"); for(ComponentProperty property : component.getProperties()) { String propertyName = property.getName(); pw.println("__tuscany.sca.propertyMap." + propertyName + " = new String(\"" + getPropertyValue(property) + "\");"); } pw.println("tuscany.sca.Property = function (name) {"); pw.println(" return __tuscany.sca.propertyMap[name];"); pw.println("}"); } /** * Convert property value to String * @param property * @return */ private static String getPropertyValue(ComponentProperty property) { Document doc = (Document)property.getValue(); Element rootElement = doc.getDocumentElement(); String value = null; //FIXME : Provide support for isMany and other property types if (rootElement.getChildNodes().getLength() > 0) { value = rootElement.getChildNodes().item(0).getTextContent(); } return value; } /** * Generate JavaScript code to inject SCA References * @param pw * @throws IOException */ private static void generateJavaScriptReferenceFunction (RuntimeComponent component, JavascriptProxyFactoryExtensionPoint javascriptProxyFactories, PrintWriter pw) throws IOException { pw.println("__tuscany.sca.referenceMap = {};"); for(ComponentReference reference : component.getReferences()) { for(EndpointReference epr : reference.getEndpointReferences()) { Endpoint targetEndpoint = epr.getTargetEndpoint(); if (targetEndpoint.isUnresolved()) { //force resolution and targetEndpoint binding calculations //by calling the getInvocationChain ((RuntimeEndpointReference) epr).getInvocationChains(); targetEndpoint = epr.getTargetEndpoint(); } Binding binding = targetEndpoint.getBinding(); if (binding != null) { String referenceName = reference.getName(); JavascriptProxyFactory jsProxyFactory = javascriptProxyFactories.getProxyFactory(binding.getClass()); pw.println("__tuscany.sca.referenceMap." + referenceName + " = new " + jsProxyFactory.createJavascriptReference(reference) + ";"); } } } pw.println("tuscany.sca.Reference = function (name) {"); pw.println(" return __tuscany.sca.referenceMap[name];"); pw.println("}"); } }