summaryrefslogtreecommitdiffstats
path: root/tags/java/sca/1.5.1-RC3/modules/implementation-xquery/src/main/java/org/apache/tuscany/sca/implementation/xquery/xml/XQueryIntrospector.java
diff options
context:
space:
mode:
Diffstat (limited to 'tags/java/sca/1.5.1-RC3/modules/implementation-xquery/src/main/java/org/apache/tuscany/sca/implementation/xquery/xml/XQueryIntrospector.java')
-rw-r--r--tags/java/sca/1.5.1-RC3/modules/implementation-xquery/src/main/java/org/apache/tuscany/sca/implementation/xquery/xml/XQueryIntrospector.java328
1 files changed, 328 insertions, 0 deletions
diff --git a/tags/java/sca/1.5.1-RC3/modules/implementation-xquery/src/main/java/org/apache/tuscany/sca/implementation/xquery/xml/XQueryIntrospector.java b/tags/java/sca/1.5.1-RC3/modules/implementation-xquery/src/main/java/org/apache/tuscany/sca/implementation/xquery/xml/XQueryIntrospector.java
new file mode 100644
index 0000000000..d1e74dd40d
--- /dev/null
+++ b/tags/java/sca/1.5.1-RC3/modules/implementation-xquery/src/main/java/org/apache/tuscany/sca/implementation/xquery/xml/XQueryIntrospector.java
@@ -0,0 +1,328 @@
+/*
+ * 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.xquery.xml;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Iterator;
+
+import javax.xml.namespace.QName;
+
+import net.sf.saxon.Configuration;
+import net.sf.saxon.om.NamespaceResolver;
+import net.sf.saxon.query.StaticQueryContext;
+import net.sf.saxon.query.XQueryExpression;
+import net.sf.saxon.trans.XPathException;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.implementation.xquery.XQueryImplementation;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
+
+/**
+ * This class introspects an XQuery file and extracts out of it
+ * all implemented service, references and properties
+ * It also creates expression extensions for each operation
+ * in the implemented services
+ * @version $Rev$ $Date$
+ */
+public class XQueryIntrospector {
+
+ private static final String SCA_SERVICE_PREFIX = "scaservice:java/";
+ private static final String SCA_REFERENCE_PREFIX = "scareference:java/";
+ private static final String SCA_PROPERTY_JAVA_PREFIX = "scaproperty:java/";
+ private static final String SCA_PROPERTY_XML_PREFIX = "scaproperty:xml/";
+
+ private AssemblyFactory assemblyFactory;
+ private JavaInterfaceFactory javaFactory;
+
+ public XQueryIntrospector(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory) {
+ super();
+ this.assemblyFactory = assemblyFactory;
+ this.javaFactory = javaFactory;
+ }
+
+ public boolean introspect(XQueryImplementation xqueryImplementation, ModelResolver resolver) throws ContributionResolveException {
+
+ String xqExpression = null;
+ try {
+ URL url = new URL(xqueryImplementation.getLocationURL());
+ xqExpression = loadXQExpression(url);
+ } catch (FileNotFoundException e) {
+ throw new ContributionResolveException(e);
+ } catch (IOException e) {
+ throw new ContributionResolveException(e);
+ }
+
+ if (xqExpression == null) {
+ return false;
+ }
+
+ xqueryImplementation.setXqExpression(xqExpression);
+
+ xqExpression += "\r\n<dummy></dummy>";
+
+ Configuration config = new Configuration();
+ StaticQueryContext sqc = new StaticQueryContext(config);
+ XQueryExpression exp = null;
+ try {
+ exp = sqc.compileQuery(xqExpression);
+ } catch (XPathException e) {
+ throw new ContributionResolveException(e);
+ }
+
+ if (exp == null) {
+ return false;
+ }
+ xqueryImplementation.getCompiledExpressionsCache().put(xqExpression, exp);
+
+ try {
+ introspectServicesAndReferences(xqueryImplementation, exp, resolver);
+ } catch (ClassNotFoundException e) {
+ throw new ContributionResolveException(e);
+ } catch (InvalidInterfaceException e) {
+ throw new ContributionResolveException(e);
+ }
+
+ fillExpressionExtensions(xqueryImplementation);
+
+ return true;
+ }
+
+ /**
+ * Loads the XQuery expression from the location that is provided with the implementation
+ */
+ private String loadXQExpression(URL locationURL) throws FileNotFoundException, IOException {
+
+ InputStream xqResourceStream = locationURL.openStream();
+
+ if (xqResourceStream == null) {
+ return null;
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int i = 0;
+ while ((i = xqResourceStream.read()) >= 0) {
+ baos.write(i);
+ }
+ xqResourceStream.close();
+ baos.flush();
+ baos.close();
+
+ String xqExpression = baos.toString();
+
+ return xqExpression;
+ }
+
+ private Class<?> resolveClass(ModelResolver resolver, String className) throws ClassNotFoundException {
+ ClassReference classReference = new ClassReference(className);
+ classReference = resolver.resolveModel(ClassReference.class, classReference);
+ Class<?> javaClass = classReference.getJavaClass();
+ if (javaClass == null) {
+ throw new ClassNotFoundException(className);
+ } else {
+ return javaClass;
+ }
+ }
+
+ /**
+ * From the compiled XQuery expression get all namespaces and see if they
+ * are services, references or properties declarations
+ */
+ private void introspectServicesAndReferences(XQueryImplementation xqueryImplementation, XQueryExpression exp, ModelResolver resolver)
+ throws ClassNotFoundException, InvalidInterfaceException {
+ NamespaceResolver namespaceResolver = exp.getStaticContext().getNamespaceResolver();
+ Iterator declaredPrefixesIterator = namespaceResolver.iteratePrefixes();
+ while (declaredPrefixesIterator.hasNext()) {
+ String prefix = (String)declaredPrefixesIterator.next();
+ String uri = namespaceResolver.getURIForPrefix(prefix, false);
+ if (uri.startsWith(SCA_SERVICE_PREFIX)) {
+ String serviceName = prefix;
+ String className = uri.substring(SCA_SERVICE_PREFIX.length());
+ Class<?> interfaze = resolveClass(resolver, className);
+ Service theService = createService(interfaze, serviceName);
+ xqueryImplementation.getServices().add(theService);
+ } else if (uri.startsWith(SCA_REFERENCE_PREFIX)) {
+ String referenceName = prefix;
+ String className = uri.substring(SCA_REFERENCE_PREFIX.length());
+ Class<?> interfaze = resolveClass(resolver, className);
+ Reference theReference = createReference(interfaze, referenceName);
+ xqueryImplementation.getReferences().add(theReference);
+ } else if (uri.startsWith(SCA_PROPERTY_JAVA_PREFIX)) {
+ String propertyName = prefix;
+ String className = uri.substring(SCA_PROPERTY_JAVA_PREFIX.length());
+ Class<?> clazz = resolveClass(resolver, className);
+ QName xmlType = JavaXMLMapper.getXMLType(clazz);
+ Property theProperty = createProperty(xmlType, propertyName);
+ xqueryImplementation.getProperties().add(theProperty);
+ } else if (uri.startsWith(SCA_PROPERTY_XML_PREFIX)) {
+ String propertyName = prefix;
+ String namespaceAndLocalname = uri.substring(SCA_PROPERTY_XML_PREFIX.length());
+ int localNameDelimiterPostition = namespaceAndLocalname.lastIndexOf(':');
+ String localName = null;
+ String namespace = null;
+ if (localNameDelimiterPostition < 0) {
+ localName = namespaceAndLocalname;
+ namespace = "";
+ } else {
+ namespace = namespaceAndLocalname.substring(0, localNameDelimiterPostition);
+ localName = namespaceAndLocalname.substring(localNameDelimiterPostition + 1);
+ }
+ QName xmlType = new QName(namespace, localName);
+ Property theProperty = createProperty(xmlType, propertyName);
+ xqueryImplementation.getProperties().add(theProperty);
+ }
+ }
+ }
+
+ /**
+ * Creates a Service for the component type based on its name and Java interface
+ */
+ private Service createService(Class<?> interfaze, String name) throws InvalidInterfaceException {
+ Service service = assemblyFactory.createService();
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+ // Set the name for the service
+ service.setName(name);
+
+ // Set the call interface and, if present, the callback interface
+ JavaInterface callInterface = null;
+ try {
+ callInterface = (JavaInterface) javaFactory.createJavaInterface(interfaze).clone();
+ } catch (CloneNotSupportedException e) {
+ // Ignore
+ }
+ //setDataBindingForInterface(callInterface, DataObject.class.getName());
+ service.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = null;
+ try {
+ callbackInterface = (JavaInterface) javaFactory.createJavaInterface(callInterface.getCallbackClass()).clone();
+ } catch (CloneNotSupportedException e) {
+ //Ignore
+ }
+ //setDataBindingForInterface(callbackInterface, DataObject.class.getName());
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ return service;
+ } // end method createService
+
+ protected Property createProperty(QName type, String name) {
+
+ Property property = assemblyFactory.createProperty();
+ property.setName(name);
+ property.setXSDType(type);
+
+ property.setMany(false);
+ return property;
+
+ }
+
+ /**
+ * Creates a Reference for the component type based on its name and Java interface
+ */
+ private Reference createReference(Class<?> interfaze, String name) throws InvalidInterfaceException {
+ Reference reference = assemblyFactory.createReference();
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+
+ // Set the name of the reference to the supplied name and the multiplicity of the reference
+ // to 1..1 - for XQuery implementations, this is the only multiplicity supported
+ reference.setName(name);
+ reference.setMultiplicity(Multiplicity.ONE_ONE);
+
+ // Set the call interface and, if present, the callback interface
+ // Set the call interface and, if present, the callback interface
+ JavaInterface callInterface = null;
+ try {
+ callInterface = (JavaInterface) javaFactory.createJavaInterface(interfaze).clone();
+ } catch (CloneNotSupportedException e) {
+ // Ignore
+ }
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = null;
+ try {
+ callbackInterface = (JavaInterface) javaFactory.createJavaInterface(callInterface.getCallbackClass()).clone();
+ } catch (CloneNotSupportedException e) {
+ //Ignore
+ }
+ reference.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+
+ return reference;
+ }
+
+ /**
+ * For the methods of each implemented service corresponding expression extension
+ * is generated
+ * @param xqueryImplementation
+ */
+ private void fillExpressionExtensions(XQueryImplementation xqueryImplementation) {
+ for (Service service : xqueryImplementation.getServices()) {
+ Class<?> interfaze = ((JavaInterface)service.getInterfaceContract().getInterface()).getJavaClass();
+
+ // For each of the methods
+ for (Method method : interfaze.getMethods()) {
+ String expressionExtension = createExpressionExtension(method, interfaze, service.getName());
+ xqueryImplementation.getXqExpressionExtensionsMap().put(method, expressionExtension);
+ }
+ }
+ }
+
+ private String createExpressionExtension(Method method, Class<?> interfaze, String serviceName) {
+ StringBuffer exprBuf = new StringBuffer();
+
+ exprBuf.append("\r\n");
+
+ String methodName = method.getName();
+
+ // For each of the declared parameters
+ for (int i = 0; i < method.getParameterTypes().length; i++) {
+ exprBuf.append("declare variable $" + methodName + "_" + i + " external;\r\n");
+ }
+
+ exprBuf.append(serviceName + ":" + methodName + "(");
+
+ for (int i = 0; i < method.getParameterTypes().length; i++) {
+ exprBuf.append("$" + methodName + "_" + i);
+ if (i != method.getParameterTypes().length - 1) {
+ exprBuf.append(", ");
+ }
+ }
+ exprBuf.append(")");
+
+ return exprBuf.toString();
+ }
+}