[teiid-commits] teiid SVN: r4378 - in trunk/engine/src: main/java/org/teiid/query/eval and 5 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Tue Aug 28 15:41:34 EDT 2012


Author: shawkins
Date: 2012-08-28 15:41:34 -0400 (Tue, 28 Aug 2012)
New Revision: 4378

Added:
   trunk/engine/src/main/java/org/teiid/query/eval/TeiidScriptEngine.java
Modified:
   trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
   trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java
   trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
Log:
TEIID-2141 adding teiid_script

Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-08-28 18:31:49 UTC (rev 4377)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-08-28 19:41:34 UTC (rev 4378)
@@ -528,5 +528,6 @@
     	TEIID31108, //datasource not available
     	TEIID31109, //invalid scripting language
     	TEIID31110, //invalid script
+    	TEIID31111, //invalid teiid script
 	}
 }

Added: trunk/engine/src/main/java/org/teiid/query/eval/TeiidScriptEngine.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/TeiidScriptEngine.java	                        (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/eval/TeiidScriptEngine.java	2012-08-28 19:41:34 UTC (rev 4378)
@@ -0,0 +1,191 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.eval;
+
+import java.beans.BeanInfo;
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.MethodDescriptor;
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.io.Reader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.regex.Pattern;
+
+import javax.script.AbstractScriptEngine;
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+
+import org.teiid.core.util.LRUCache;
+import org.teiid.core.util.ObjectConverterUtil;
+import org.teiid.query.QueryPlugin;
+
+/**
+ * A simplistic script engine that supports root variable access and 0-ary methods on the subsequent objects.
+ */
+public final class TeiidScriptEngine extends AbstractScriptEngine implements Compilable {
+	private static Map<ClassLoader, Map<Class<?>, Map<String, Method>>> properties = new WeakHashMap<ClassLoader, Map<Class<?>, Map<String, Method>>>(100);
+	private static Pattern splitter = Pattern.compile("\\."); //$NON-NLS-1$
+	
+	@Override
+	public Bindings createBindings() {
+		return new SimpleBindings();
+	}
+
+	@Override
+	public CompiledScript compile(String script) throws ScriptException {
+		final String[] parts = splitter.split(script);
+		for (int i = 1; i < parts.length; i++) {
+			String string = parts[i];
+			for (int j = 0; j < string.length(); j++) {
+				if (!Character.isJavaIdentifierPart(string.charAt(j))) {
+					throw new ScriptException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30431,string, string.charAt(j)));
+				}
+			}
+		}
+		return new CompiledScript() {
+			
+			@Override
+			public ScriptEngine getEngine() {
+				return TeiidScriptEngine.this;
+			}
+			
+			@Override
+			public Object eval(ScriptContext sc) throws ScriptException {
+				if (sc == null) {
+					throw new NullPointerException();
+				}
+				Object obj = null;
+				if (parts.length > 0) {
+					obj = sc.getAttribute(parts[0]);
+				}
+				if (obj == null) {
+					return null;
+				}
+				for (int i = 1; i < parts.length; i++) {
+					String part = parts[i];
+					Map<String, Method> methodMap = getMethodMap(obj.getClass());
+					Method m = methodMap.get(part);
+					if (m == null) {
+						throw new ScriptException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31111, part, obj.getClass()));
+					}
+					try {
+						obj = m.invoke(obj);
+					} catch (IllegalAccessException e) {
+						throw new ScriptException(e);
+					} catch (InvocationTargetException e) {
+						if (e.getCause() instanceof Exception) {
+							throw new ScriptException((Exception) e.getCause());
+						}
+						throw new ScriptException(e);
+					}
+				}
+				return obj;
+			}
+		};
+	}
+	
+	private Map<String, Method> getMethodMap(Class<?> clazz) throws ScriptException {
+		Map<Class<?>, Map<String, Method>> clazzMaps = null;
+		synchronized (properties) {
+			clazzMaps = properties.get(clazz.getClassLoader());
+			if (clazzMaps == null) {
+				clazzMaps = Collections.synchronizedMap(new LRUCache<Class<?>, Map<String, Method>>(100));
+				properties.put(clazz.getClassLoader(), clazzMaps);
+			}
+		}
+		Map<String, Method> methodMap = clazzMaps.get(clazz);
+		if (methodMap == null) {
+			try {
+				BeanInfo info = Introspector.getBeanInfo(clazz);
+				PropertyDescriptor[] pds = info.getPropertyDescriptors();
+				methodMap = new HashMap<String, Method>();
+				if (pds != null) {
+					for (int j = 0; j < pds.length; j++) {
+						PropertyDescriptor pd = pds[j];
+						if (pd.getReadMethod() == null || pd instanceof IndexedPropertyDescriptor) {
+							continue;
+						}
+						String name = pd.getName();
+						Method m = pd.getReadMethod();
+						methodMap.put(name, m);
+					}
+				}
+				MethodDescriptor[] mds = info.getMethodDescriptors();
+				if (pds != null) {
+					for (int j = 0; j < mds.length; j++) {
+						MethodDescriptor md = mds[j];
+						if (md.getMethod() == null || md.getMethod().getParameterTypes().length > 0 || md.getMethod().getReturnType() == Void.class) {
+							continue;
+						}
+						String name = md.getName();
+						Method m = md.getMethod();
+						methodMap.put(name, m);
+					}
+				}
+				clazzMaps.put(clazz, methodMap);
+			} catch (IntrospectionException e) {
+				throw new ScriptException(e);
+			}
+		}
+		return methodMap;
+	}
+
+	@Override
+	public CompiledScript compile(Reader script) throws ScriptException {
+		try {
+			return compile(ObjectConverterUtil.convertToString(script));
+		} catch (IOException e) {
+			throw new ScriptException(e);
+		}
+	}
+	
+	@Override
+	public ScriptEngineFactory getFactory() {
+		throw new UnsupportedOperationException();
+	}
+
+	public Object eval(Reader reader, ScriptContext sc)
+			throws ScriptException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public Object eval(String script, ScriptContext sc)
+			throws ScriptException {
+		throw new UnsupportedOperationException();
+	}
+
+}
\ No newline at end of file


Property changes on: trunk/engine/src/main/java/org/teiid/query/eval/TeiidScriptEngine.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java	2012-08-28 18:31:49 UTC (rev 4377)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java	2012-08-28 19:41:34 UTC (rev 4378)
@@ -60,6 +60,7 @@
 import org.teiid.metadata.Column.SearchType;
 import org.teiid.metadata.ProcedureParameter.Type;
 import org.teiid.query.QueryPlugin;
+import org.teiid.query.eval.TeiidScriptEngine;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.function.FunctionTree;
 import org.teiid.query.mapping.relational.QueryNode;
@@ -1119,8 +1120,8 @@
 		if (this.scriptEngineManager == null) {
 			this.scriptEngineManager = new ScriptEngineManager();
 		}
-		if (language == null) {
-			language = ObjectTable.DEFAULT_LANGUAGE; 
+		if (language == null || ObjectTable.DEFAULT_LANGUAGE.equals(language)) {
+			return new TeiidScriptEngine();
 		}
 		ScriptEngine engine = null;
 		if (allowedLanguages == null || allowedLanguages.contains(language)) {
@@ -1147,6 +1148,7 @@
 			if (allowedLanguages != null) {
 				names.retainAll(allowedLanguages);
 			}
+			names.add(ObjectTable.DEFAULT_LANGUAGE);
 			throw new TeiidProcessingException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31109, language, names));
 		}
 		this.scriptEngineFactories.put(language, engine.getFactory());

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java	2012-08-28 18:31:49 UTC (rev 4377)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java	2012-08-28 19:41:34 UTC (rev 4378)
@@ -22,6 +22,7 @@
 
 package org.teiid.query.processor.relational;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -36,15 +37,18 @@
 
 import org.teiid.api.exception.query.ExpressionEvaluationException;
 import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.BufferManager;
 import org.teiid.common.buffer.TupleBatch;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.eval.Evaluator;
 import org.teiid.query.function.FunctionDescriptor;
+import org.teiid.query.processor.ProcessorDataManager;
 import org.teiid.query.sql.LanguageObject;
 import org.teiid.query.sql.lang.ObjectTable;
 import org.teiid.query.sql.lang.ObjectTable.ObjectColumn;
+import org.teiid.query.util.CommandContext;
 
 /**
  * Handles object table processing.
@@ -69,17 +73,33 @@
 	}
 	
 	@Override
+	public void initialize(CommandContext context, BufferManager bufferManager,
+			ProcessorDataManager dataMgr) {
+		super.initialize(context, bufferManager, dataMgr);
+		this.scriptContext = new SimpleScriptContext();
+	}
+	
+	@Override
 	public void open() throws TeiidComponentException, TeiidProcessingException {
 		super.open();
 		if (table.getScriptEngine() == null) {
 			table.setScriptEngine(getContext().getMetadata().getScriptEngine(table.getScriptingLanguage()));
 		}
-		scriptContext = new SimpleScriptContext();
 		this.scriptContext.setAttribute(TEIID_CONTEXT, this.getContext(), ScriptContext.ENGINE_SCOPE);
 	}
 	
 	@Override
 	public synchronized void closeDirect() {
+		if (this.scriptContext != null) {
+			try {
+				this.scriptContext.getErrorWriter().flush();
+			} catch (IOException e) {
+			}
+			try {
+				this.scriptContext.getWriter().flush();
+			} catch (IOException e) {
+			}
+		}
 		super.closeDirect();
 		reset();
 	}
@@ -90,7 +110,9 @@
 		item = null;
 		result = null;
 		rowCount = 0;
-		this.scriptContext = null;
+		if (this.scriptContext != null) {
+			this.scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).clear();
+		}
 	}
 	
 	public void setTable(ObjectTable table) {

Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java	2012-08-28 18:31:49 UTC (rev 4377)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java	2012-08-28 19:41:34 UTC (rev 4378)
@@ -35,7 +35,7 @@
 
 public class ObjectTable extends TableFunctionReference {
 	
-	public static final String DEFAULT_LANGUAGE = "javascript"; //$NON-NLS-1$
+	public static final String DEFAULT_LANGUAGE = "teiid_script"; //$NON-NLS-1$
 	
 	public static class ObjectColumn extends ProjectedColumn {
 		private String path;

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-28 18:31:49 UTC (rev 4377)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-28 19:41:34 UTC (rev 4378)
@@ -40,7 +40,7 @@
 TEIID30011=The function "{0}" will not be added because a function with the same name and signature already exists.
 TEIID30389=Unexpected exception while loading "{1}.{2}" for UDF "{0}"
 TEIID30387=Could not load UDF "{0}", since its invocation class "{1}" could not be found.
-TEIID30388=UDF "{0}" could not loaded, since no method on class "{1}" with name "{2}" has a matching type signature.
+TEIID30388=UDF "{0}" could not be loaded, since no method on class "{1}" with name "{2}" has a matching type signature.
 TEIID30424=Unable to represent average value from {0} / {1}
 TEIID30425=Unable to compute aggregate function {0} on data of type {1}
 TEIID30429={0} must be non-null.
@@ -1025,7 +1025,8 @@
 TEIID31106=Duplicate parameter {1} defined on {0}
 TEIID31107=Procedure {0} can only have 1 RESULT/return value
 TEIID31109=Invalid language {0}.  Supported and allowed language names are {1}.
-TEIID31110=Invalid script {0}.  Scrpting engine reported: {1}.
+TEIID31110=Invalid script {0}.  Scrpting engine reported: {1}
+TEIID31111=No such accessible property/method {0} on {1}.
 
 SQLParser.proc_type_conflict=Result type {1} conflicts with return type {2} for procedure {0}
 SQLParser.param_out=Procedure {0} RESULT param {1} must be of type OUT.

Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-28 18:31:49 UTC (rev 4377)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-28 19:41:34 UTC (rev 4378)
@@ -1603,7 +1603,7 @@
     }
     
     @Test public void testObjectTableScript() {
-    	helpValidate("select * from objecttable('this is not valid' columns c integer 'row') as x", new String[] {"OBJECTTABLE('this is not valid' COLUMNS c integer 'row') AS x"}, RealMetadataFactory.example1Cached());
+    	helpValidate("select * from objecttable('this. is not valid' columns c integer 'row') as x", new String[] {"OBJECTTABLE('this is not valid' COLUMNS c integer 'row') AS x"}, RealMetadataFactory.example1Cached());
     }
 
     @Test public void testXMLQueryPassingContextType() {



More information about the teiid-commits mailing list