[teiid-commits] teiid SVN: r4359 - in trunk: build/kits/jboss-as7/docs/teiid and 12 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Thu Aug 23 10:07:39 EDT 2012
Author: rareddy
Date: 2012-08-23 10:07:39 -0400 (Thu, 23 Aug 2012)
New Revision: 4359
Added:
trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/
trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/RestASMBasedWebArchiveBuilder.java
trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/ResteasyEnabler.java
trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/TeiidRSProvider.java
trunk/jboss-integration/src/main/resources/rest-war/
trunk/jboss-integration/src/main/resources/rest-war/MANIFEST.MF
trunk/jboss-integration/src/main/resources/rest-war/jboss-web.xml
trunk/jboss-integration/src/main/resources/rest-war/web.xml
trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/
trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java
trunk/jboss-integration/src/test/resources/sample-vdb.xml
trunk/test-integration/common/src/test/java/org/teiid/arquillian/IntegrationTestRestWebserviceGeneration.java
trunk/test-integration/common/src/test/resources/sample-vdb.xml
Modified:
trunk/admin/src/main/java/org/teiid/adminapi/AdminFactory.java
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/build/kits/jboss-as7/modules/org/jboss/teiid/main/module.xml
trunk/jboss-integration/pom.xml
trunk/jboss-integration/src/main/java/org/teiid/jboss/IntegrationPlugin.java
trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java
trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBService.java
trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties
Log:
TEIID-2158 - Initial implementation of generating REST based services based on a extension metadata provided on the virtual procedures.
Modified: trunk/admin/src/main/java/org/teiid/adminapi/AdminFactory.java
===================================================================
--- trunk/admin/src/main/java/org/teiid/adminapi/AdminFactory.java 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/admin/src/main/java/org/teiid/adminapi/AdminFactory.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -148,7 +148,7 @@
}
- private class AdminImpl implements Admin{
+ public class AdminImpl implements Admin{
private static final String CLASS_NAME = "class-name";
private static final String JAVA_CONTEXT = "java:/";
private ModelControllerClient connection;
@@ -750,6 +750,10 @@
}
return templates;
}
+
+ public List<String> getDeployments(){
+ return Util.getDeployments(this.connection);
+ }
@Override
public Set<String> getDataSourceTemplateNames() throws AdminProcessingException {
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-23 14:07:39 UTC (rev 4359)
@@ -27,8 +27,9 @@
<H2><A NAME="Highlights"></A>Highlights</H2>
<ul>
<li>TEIID-2150 <b>Positional procedure defaults</b> - a procedure now may be called positionally with just the leading input parameters as long as all trailing parameters are out or defaultable.
- <li>TEIID-2148 <b>Streaming Improvements</b> - the ws translator invoke/invokeHttp procedures now execpt a stream parameter to indicate that the result should be streamed directly without an intermediate copy being created.
+ <li>TEIID-2148 <b>Streaming Improvements</b> - the ws translator invoke/invokeHttp procedures now accept a "stream"" parameter to indicate that the result should be streamed directly without an intermediate copy being created.
Also intermediate document/blob copies are made concurrently with reading to reduce latency.
+ <li>TEIID-2158 <b>Rest Services</b> - when required extension metadata defined on the virtual procedure, a REST based service on that procedure is automatically generated and deployed upon VDB deployment.
</ul>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
Modified: trunk/build/kits/jboss-as7/modules/org/jboss/teiid/main/module.xml
===================================================================
--- trunk/build/kits/jboss-as7/modules/org/jboss/teiid/main/module.xml 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/build/kits/jboss-as7/modules/org/jboss/teiid/main/module.xml 2012-08-23 14:07:39 UTC (rev 4359)
@@ -37,6 +37,7 @@
<module name="javax.activation.api"/>
<module name="org.jboss.as.clustering.jgroups"/>
<module name="org.infinispan"/>
+ <module name="asm.asm"/>
<!-- These dependencies here for ra.xml description -->
<module name="org.jboss.as.connector"/>
<module name="org.jboss.ironjacamar.api"/>
Modified: trunk/jboss-integration/pom.xml
===================================================================
--- trunk/jboss-integration/pom.xml 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/jboss-integration/pom.xml 2012-08-23 14:07:39 UTC (rev 4359)
@@ -69,6 +69,13 @@
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ <version>3.3.1</version>
+ <scope>provided</scope>
+ </dependency>
+
<!-- This dependency is to read the ra.xml file details -->
<dependency>
<groupId>org.jboss.as</groupId>
@@ -105,6 +112,13 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.jboss.teiid</groupId>
+ <artifactId>teiid-engine</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.jboss.teiid.connectors</groupId>
Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/IntegrationPlugin.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/IntegrationPlugin.java 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/IntegrationPlugin.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -98,5 +98,7 @@
TEIID50088,
TEIID50089,
TEIID50090, //Missing context
+ TEIID50091, // rest different # of param count
+ TEIID50092, // rest procedure execution
}
}
Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -29,22 +29,16 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import org.jboss.as.controller.ModelController;
import org.jboss.as.naming.deployment.ContextNames;
+import org.jboss.as.server.Services;
import org.jboss.as.server.deployment.Attachments;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
import org.jboss.modules.Module;
-import org.jboss.msc.service.AbstractServiceListener;
-import org.jboss.msc.service.Service;
-import org.jboss.msc.service.ServiceBuilder;
-import org.jboss.msc.service.ServiceController;
-import org.jboss.msc.service.ServiceName;
-import org.jboss.msc.service.ServiceTarget;
-import org.jboss.msc.service.StartContext;
-import org.jboss.msc.service.StartException;
-import org.jboss.msc.service.StopContext;
+import org.jboss.msc.service.*;
import org.jboss.msc.service.ServiceBuilder.DependencyType;
import org.jboss.msc.service.ServiceController.Mode;
import org.jboss.msc.service.ServiceController.State;
@@ -187,6 +181,9 @@
vdbService.addDependency(vdbSwitchServiceName, CountDownLatch.class, new InjectedValue<CountDownLatch>());
vdbService.addDependency(DependencyType.OPTIONAL, TeiidServiceNames.OBJECT_REPLICATOR, ObjectReplicator.class, vdb.objectReplicatorInjector);
+ // REST dependencies
+ vdbService.addDependency(Services.JBOSS_SERVER_CONTROLLER, ModelController.class, vdb.controllerValue);
+
// VDB restart switch, control the vdbservice by adding removing the switch service. If you
// remove the service by setting status remove, there is no way start it back up if vdbservice used alone
installVDBSwitchService(context.getServiceTarget(), vdbSwitchServiceName);
Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBService.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBService.java 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBService.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -37,6 +37,7 @@
import javax.xml.stream.XMLStreamException;
+import org.jboss.as.controller.ModelController;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
@@ -52,10 +53,10 @@
import org.teiid.adminapi.AdminProcessingException;
import org.teiid.adminapi.Translator;
import org.teiid.adminapi.impl.ModelMetaData;
+import org.teiid.adminapi.impl.ModelMetaData.Message.Severity;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.adminapi.impl.VDBMetadataParser;
import org.teiid.adminapi.impl.VDBTranslatorMetaData;
-import org.teiid.adminapi.impl.ModelMetaData.Message.Severity;
import org.teiid.common.buffer.BufferManager;
import org.teiid.core.TeiidException;
import org.teiid.deployers.CompositeVDB;
@@ -68,8 +69,9 @@
import org.teiid.deployers.VirtualDatabaseException;
import org.teiid.dqp.internal.datamgr.ConnectorManager;
import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository;
+import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository.ConnectorManagerException;
import org.teiid.dqp.internal.datamgr.TranslatorRepository;
-import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository.ConnectorManagerException;
+import org.teiid.jboss.rest.ResteasyEnabler;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.metadata.Datatype;
@@ -97,6 +99,9 @@
protected final InjectedValue<ObjectReplicator> objectReplicatorInjector = new InjectedValue<ObjectReplicator>();
protected final InjectedValue<VDBStatusChecker> vdbStatusCheckInjector = new InjectedValue<VDBStatusChecker>();
+ // for REST deployment
+ protected final InjectedValue<ModelController> controllerValue = new InjectedValue<ModelController>();
+
private VDBLifeCycleListener vdbListener;
private LinkedHashMap<String, Resource> visibilityMap;
@@ -166,6 +171,7 @@
};
getVDBRepository().addListener(this.vdbListener);
+ getVDBRepository().addListener(new ResteasyEnabler(controllerValue.getValue(), executorInjector.getValue()));
MetadataStore store = new MetadataStore();
Added: trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/RestASMBasedWebArchiveBuilder.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/RestASMBasedWebArchiveBuilder.java (rev 0)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/RestASMBasedWebArchiveBuilder.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,410 @@
+/*
+ * 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.jboss.rest;
+
+import static org.objectweb.asm.Opcodes.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Properties;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.teiid.adminapi.impl.ModelMetaData;
+import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.FileUtils;
+import org.teiid.core.util.ObjectConverterUtil;
+import org.teiid.core.util.StringUtil;
+import org.teiid.jboss.IntegrationPlugin;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.ColumnSet;
+import org.teiid.metadata.MetadataStore;
+import org.teiid.metadata.Procedure;
+import org.teiid.metadata.ProcedureParameter;
+import org.teiid.metadata.Schema;
+import org.teiid.query.metadata.TransformationMetadata;
+
+
+
+ at SuppressWarnings("nls")
+public class RestASMBasedWebArchiveBuilder {
+
+
+ public byte[] createRestArchive(VDBMetaData vdb) throws FileNotFoundException, IOException {
+ MetadataStore metadataStore = vdb.getAttachment(TransformationMetadata.class).getMetadataStore();
+
+ Properties props = new Properties();
+ props.setProperty("${context-name}", vdb.getName() + "_" + vdb.getVersion());
+ props.setProperty("${vdb-name}", vdb.getName());
+ props.setProperty("${vdb-version}", String.valueOf(vdb.getVersion()));
+
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ ZipOutputStream out = new ZipOutputStream(byteStream);
+ writeEntry("WEB-INF/web.xml", out, replaceTemplates(getFileContents("rest-war/web.xml"), props).getBytes());
+ writeEntry("WEB-INF/jboss-web.xml", out, replaceTemplates(getFileContents("rest-war/jboss-web.xml"), props).getBytes());
+
+ ArrayList<String> applicationViews = new ArrayList<String>();
+ for (ModelMetaData model:vdb.getModelMetaDatas().values()) {
+ Schema schema = metadataStore.getSchema(model.getName());
+ byte[] viewContents = getViewClass(vdb.getName(), vdb.getVersion(), model.getName(), schema);
+ if (viewContents != null) {
+ writeEntry("WEB-INF/classes/org/teiid/jboss/rest/"+model.getName()+".class", out, viewContents);
+ applicationViews.add(schema.getName());
+ }
+ }
+ writeEntry("WEB-INF/classes/org/teiid/jboss/rest/TeiidRestApplication.class", out, getApplicationClass(applicationViews));
+ writeEntry("META-INF/MANIFEST.MF", out, getFileContents("rest-war/MANIFEST.MF").getBytes());
+
+ out.close();
+ return byteStream.toByteArray();
+ }
+
+ private void writeEntry(String name, ZipOutputStream out, byte[] contents) throws IOException {
+ ZipEntry e = new ZipEntry(name);
+ out.putNextEntry(e);
+ FileUtils.write(new ByteArrayInputStream(contents), out, 1024);
+ out.closeEntry();
+ }
+
+ private String getFileContents(String file) throws IOException {
+ InputStream in = this.getClass().getClassLoader().getResourceAsStream(file);
+ Reader reader = new InputStreamReader(in);
+ String webXML = ObjectConverterUtil.convertToString(reader);
+ return webXML;
+ }
+
+ private String replaceTemplates(String orig, Properties replacements) {
+ for (String key:replacements.stringPropertyNames()) {
+ orig = StringUtil.replace(orig, key, replacements.getProperty(key));
+ }
+ return orig;
+ }
+
+ private static ArrayList<String> getPathParameters(String uri ) {
+ ArrayList pathParams = new ArrayList();
+ String param;
+ if (uri.contains("{")) {
+ while (uri.indexOf("}") > -1) {
+ int start = uri.indexOf("{");
+ int end = uri.indexOf("}");
+ param = uri.substring(start + 1, end);
+ uri = uri.substring(end + 1);
+ pathParams.add(param);
+ }
+ }
+ return pathParams;
+ }
+
+ public byte[] getApplicationClass(ArrayList<String> models) {
+ ClassWriter cw = new ClassWriter(0);
+ FieldVisitor fv;
+ MethodVisitor mv;
+
+ cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "org/teiid/jboss/rest/TeiidRestApplication", null, "javax/ws/rs/core/Application", null);
+
+ {
+ fv = cw.visitField(ACC_PRIVATE, "singletons", "Ljava/util/Set;", "Ljava/util/Set<Ljava/lang/Object;>;", null);
+ fv.visitEnd();
+ }
+
+ {
+ fv = cw.visitField(ACC_PRIVATE, "empty", "Ljava/util/Set;", "Ljava/util/Set<Ljava/lang/Class<*>;>;", null);
+ fv.visitEnd();
+ }
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "javax/ws/rs/core/Application", "<init>", "()V");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitTypeInsn(NEW, "java/util/HashSet");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashSet", "<init>", "()V");
+ mv.visitFieldInsn(PUTFIELD, "org/teiid/jboss/rest/TeiidRestApplication", "singletons", "Ljava/util/Set;");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitTypeInsn(NEW, "java/util/HashSet");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashSet", "<init>", "()V");
+ mv.visitFieldInsn(PUTFIELD, "org/teiid/jboss/rest/TeiidRestApplication", "empty", "Ljava/util/Set;");
+ mv.visitVarInsn(ALOAD, 0);
+
+ for (int i = 0; i < models.size(); i++) {
+ mv.visitFieldInsn(GETFIELD, "org/teiid/jboss/rest/TeiidRestApplication", "singletons", "Ljava/util/Set;");
+ mv.visitTypeInsn(NEW, "org/teiid/jboss/rest/"+models.get(i));
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "org/teiid/jboss/rest/"+models.get(i), "<init>", "()V");
+ mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "add", "(Ljava/lang/Object;)Z");
+ mv.visitInsn(POP);
+ if (i < models.size()-1) {
+ mv.visitVarInsn(ALOAD, 0);
+ }
+ }
+
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(3, 1);
+ mv.visitEnd();
+ }
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "getClasses", "()Ljava/util/Set;", "()Ljava/util/Set<Ljava/lang/Class<*>;>;", null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, "org/teiid/jboss/rest/TeiidRestApplication", "empty", "Ljava/util/Set;");
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "getSingletons", "()Ljava/util/Set;", "()Ljava/util/Set<Ljava/lang/Object;>;", null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, "org/teiid/jboss/rest/TeiidRestApplication", "singletons", "Ljava/util/Set;");
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ private byte[] getViewClass(String vdbName, int vdbVersion, String modelName, Schema schema) {
+ ClassWriter cw = new ClassWriter(0);
+ FieldVisitor fv;
+ MethodVisitor mv;
+ AnnotationVisitor av0;
+ boolean hasValidProcedures = false;
+
+ cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "org/teiid/jboss/rest/"+modelName, null, "org/teiid/jboss/rest/TeiidRSProvider", null);
+
+ {
+ av0 = cw.visitAnnotation("Ljavax/ws/rs/Path;", true);
+ av0.visit("value", "/"+modelName.toLowerCase());
+ av0.visitEnd();
+ }
+ cw.visitInnerClass("javax/ws/rs/core/Response$Status", "javax/ws/rs/core/Response", "Status", ACC_PUBLIC + ACC_FINAL + ACC_STATIC + ACC_ENUM);
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "org/teiid/jboss/rest/TeiidRSProvider", "<init>", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ Collection<Procedure> procedures = schema.getProcedures().values();
+ for (Procedure procedure:procedures) {
+ String uri = procedure.getProperty(ResteasyEnabler.REST_NAMESPACE+"URI", false);
+ String method = procedure.getProperty(ResteasyEnabler.REST_NAMESPACE+"METHOD", false);
+ String contentType = procedure.getProperty(ResteasyEnabler.REST_NAMESPACE+"PRODUCES", false);
+ String charSet = procedure.getProperty(ResteasyEnabler.REST_NAMESPACE+"CHARSET", false);
+ if (getPathParameters(uri).size() != procedure.getParameters().size()) {
+ LogManager.logWarning(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.gs(IntegrationPlugin.Event.TEIID50091, procedure.getFullName()));
+ continue;
+ }
+ if (uri != null && method != null) {
+ if (contentType == null) {
+ contentType = findContentType(procedure);
+ }
+
+ if (contentType != null) {
+ contentType = contentType.toLowerCase();
+ if (contentType.equals("xml")) {
+ contentType = "application/xml";
+ }
+ else if (contentType.equals("json")) {
+ contentType = "application/json";
+ }
+ else if (contentType.equals("plain")) {
+ contentType = "text/plain";
+ }
+ buildRestService(modelName, procedure, method, uri, cw, contentType, charSet==null?"US-ASCII":charSet);
+ hasValidProcedures = true;
+ }
+ }
+ }
+
+ // getConnection method
+ {
+ mv = cw.visitMethod(ACC_PROTECTED, "getConnection", "()Ljava/sql/Connection;", null, new String[] { "java/sql/SQLException" });
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, "org/teiid/jdbc/TeiidDriver");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "org/teiid/jdbc/TeiidDriver", "<init>", "()V");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitLdcInsn("jdbc:teiid:"+vdbName+"."+vdbVersion);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/teiid/jdbc/TeiidDriver", "connect", "(Ljava/lang/String;Ljava/util/Properties;)Lorg/teiid/jdbc/ConnectionImpl;");
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(3, 2);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ if (!hasValidProcedures) {
+ return null;
+ }
+ return cw.toByteArray();
+ }
+
+ private String findContentType(Procedure procedure) {
+ String contentType = "plain";
+ ColumnSet<Procedure> rs = procedure.getResultSet();
+ if (rs != null) {
+ Column returnColumn = rs.getColumns().get(0);
+ if (returnColumn.getDatatype().getRuntimeTypeName().equals(DataTypeManager.DefaultDataTypes.XML)) {
+ contentType = "xml"; //$NON-NLS-1$
+ }
+ else if (returnColumn.getDatatype().getRuntimeTypeName().equals(DataTypeManager.DefaultDataTypes.CLOB)) {
+ contentType = "json";
+ }
+ }
+ else {
+ for (ProcedureParameter pp:procedure.getParameters()) {
+ if (pp.getType().equals(ProcedureParameter.Type.ReturnValue)) {
+ if (pp.getDatatype().getRuntimeTypeName().equals(DataTypeManager.DefaultDataTypes.XML)) {
+ contentType = "xml"; //$NON-NLS-1$
+ }
+ else if (pp.getDatatype().getRuntimeTypeName().equals(DataTypeManager.DefaultDataTypes.CLOB)) {
+ contentType = "json"; //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ return contentType;
+ }
+
+ private void buildRestService(String modelName, Procedure procedure,
+ String method, String uri, ClassWriter cw, String contentType,
+ String charSet) {
+
+ int paramsSize = procedure.getParameters().size();
+ MethodVisitor mv;
+
+ AnnotationVisitor av0;
+ {
+ StringBuilder paramSignature = new StringBuilder();
+ paramSignature.append("(");
+ for (int i = 0; i < paramsSize; i++) {
+ paramSignature.append("Ljava/lang/String;");
+ }
+ paramSignature.append(")");
+
+ mv = cw.visitMethod(ACC_PUBLIC, procedure.getName()+contentType, paramSignature+"Ljava/io/InputStream;", null, new String[] { "javax/ws/rs/WebApplicationException" });
+ {
+ av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
+ {
+ AnnotationVisitor av1 = av0.visitArray("value");
+ av1.visit(null, contentType);
+ av1.visitEnd();
+ }
+ av0.visitEnd();
+ }
+ {
+ av0 = mv.visitAnnotation("Ljavax/ws/rs/"+method.toUpperCase()+";", true);
+ av0.visitEnd();
+ }
+ {
+ av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true);
+ av0.visit("value", uri);
+ av0.visitEnd();
+ }
+ {
+ av0 = mv.visitAnnotation("Ljavax/annotation/security/PermitAll;", true);
+ av0.visitEnd();
+ }
+
+ for (int i = 0; i < paramsSize; i++)
+ {
+ av0 = mv.visitParameterAnnotation(i, "Ljavax/ws/rs/PathParam;", true);
+ av0.visit("value", procedure.getParameters().get(i).getName());
+ av0.visitEnd();
+ }
+
+ mv.visitCode();
+ Label l0 = new Label();
+ Label l1 = new Label();
+ Label l2 = new Label();
+ mv.visitTryCatchBlock(l0, l1, l2, "java/sql/SQLException");
+ mv.visitLabel(l0);
+ mv.visitTypeInsn(NEW, "java/util/LinkedHashMap");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/util/LinkedHashMap", "<init>", "()V");
+
+ mv.visitVarInsn(ASTORE, paramsSize+1);
+ for (int i = 0; i < paramsSize; i++) {
+ mv.visitVarInsn(ALOAD, paramsSize+1);
+ mv.visitLdcInsn(procedure.getParameters().get(i).getName());
+ mv.visitVarInsn(ALOAD, i+1);
+ mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ mv.visitInsn(POP);
+ }
+
+ mv.visitVarInsn(ALOAD, 0);
+
+ // send parametr type information the procedure name
+ StringBuilder sb = new StringBuilder();
+ sb.append(procedure.getFullName()).append("(");
+ for (ProcedureParameter pp:procedure.getParameters()) {
+ sb.append(pp.getRuntimeType()).append(",");
+ }
+ sb.append(")");
+ mv.visitLdcInsn(sb.toString());
+
+ mv.visitVarInsn(ALOAD, paramsSize+1);
+ mv.visitLdcInsn(charSet);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/teiid/jboss/rest/"+modelName, "execute", "(Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;)Ljava/io/InputStream;");
+ mv.visitLabel(l1);
+ mv.visitInsn(ARETURN);
+ mv.visitLabel(l2);
+ mv.visitFrame(F_SAME1, 0, null, 1, new Object[] {"java/sql/SQLException"});
+ mv.visitVarInsn(ASTORE, paramsSize+1);
+ mv.visitTypeInsn(NEW, "javax/ws/rs/WebApplicationException");
+ mv.visitInsn(DUP);
+ mv.visitVarInsn(ALOAD, paramsSize+1);
+ mv.visitFieldInsn(GETSTATIC, "javax/ws/rs/core/Response$Status", "INTERNAL_SERVER_ERROR", "Ljavax/ws/rs/core/Response$Status;");
+ mv.visitMethodInsn(INVOKESPECIAL, "javax/ws/rs/WebApplicationException", "<init>", "(Ljava/lang/Throwable;Ljavax/ws/rs/core/Response$Status;)V");
+ mv.visitInsn(ATHROW);
+ mv.visitMaxs(4, paramsSize+2);
+ mv.visitEnd();
+ }
+ }
+}
Property changes on: trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/RestASMBasedWebArchiveBuilder.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/ResteasyEnabler.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/ResteasyEnabler.java (rev 0)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/ResteasyEnabler.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,130 @@
+/*
+ * 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.jboss.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.concurrent.Executor;
+
+import org.jboss.as.controller.ModelController;
+import org.teiid.adminapi.Admin;
+import org.teiid.adminapi.AdminException;
+import org.teiid.adminapi.AdminFactory;
+import org.teiid.adminapi.AdminFactory.AdminImpl;
+import org.teiid.adminapi.impl.ModelMetaData;
+import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.deployers.CompositeVDB;
+import org.teiid.deployers.VDBLifeCycleListener;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.metadata.MetadataStore;
+import org.teiid.metadata.Procedure;
+import org.teiid.metadata.Schema;
+import org.teiid.query.metadata.TransformationMetadata;
+
+public class ResteasyEnabler implements VDBLifeCycleListener {
+ static final String REST_NAMESPACE = "{http://teiid.org/rest}"; //$NON-NLS-1$
+ private Admin admin;
+ private Executor executor;
+
+ public ResteasyEnabler(ModelController deployer, Executor executor) {
+ this.admin = AdminFactory.getInstance().createAdmin(deployer.createClient(executor));
+ this.executor = executor;
+ }
+
+ @Override
+ public void added(String name, int version, CompositeVDB vdb) {
+ }
+
+ @Override
+ public void finishedDeployment(String name, int version, CompositeVDB cvdb) {
+ final VDBMetaData vdb = cvdb.getVDB();
+
+ String generate = vdb.getPropertyValue("auto-generate-rest-war"); //$NON-NLS-1$
+
+ final String warName = buildName(vdb);
+ if (generate != null && Boolean.parseBoolean(generate)
+ && hasRestMetadata(vdb)
+ && !((AdminImpl) this.admin).getDeployments().contains(warName)) {
+ // this must be executing the async thread to avoid any lock-up from management operations
+ this.executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ RestASMBasedWebArchiveBuilder builder = new RestASMBasedWebArchiveBuilder();
+ byte[] warContents = builder.createRestArchive(vdb);
+ admin.deploy(warName, new ByteArrayInputStream(warContents));
+ } catch (FileNotFoundException e) {
+ LogManager.logWarning(LogConstants.CTX_RUNTIME, e);
+ } catch (IOException e) {
+ LogManager.logWarning(LogConstants.CTX_RUNTIME, e);
+ } catch (AdminException e) {
+ LogManager.logWarning(LogConstants.CTX_RUNTIME, e);
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ public void removed(String name, int version, CompositeVDB cvdb) {
+ VDBMetaData vdb = cvdb.getVDB();
+ String generate = vdb.getPropertyValue("auto-generate-rest-war"); //$NON-NLS-1$
+ final String warName = buildName(vdb);
+ if (generate != null && Boolean.parseBoolean(generate)
+ && ((AdminImpl) this.admin).getDeployments().contains(warName)) {
+ this.executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ admin.undeploy(warName);
+ } catch (AdminException e) {
+ LogManager.logWarning(LogConstants.CTX_RUNTIME, e);
+ }
+ }
+ });
+ }
+ }
+
+ private String buildName(VDBMetaData vdb) {
+ return vdb.getName().toLowerCase()+"_"+vdb.getVersion()+".war"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private boolean hasRestMetadata(VDBMetaData vdb) {
+ MetadataStore metadataStore = vdb.getAttachment(TransformationMetadata.class).getMetadataStore();
+ for (ModelMetaData model: vdb.getModelMetaDatas().values()) {
+ Schema schema = metadataStore.getSchema(model.getName());
+ Collection<Procedure> procedures = schema.getProcedures().values();
+ for (Procedure procedure:procedures) {
+ String uri = procedure.getProperty(REST_NAMESPACE+"URI", false); //$NON-NLS-1$
+ String method = procedure.getProperty(REST_NAMESPACE+"METHOD", false); //$NON-NLS-1$
+ if (uri != null && method != null) {
+ return true;
+ }
+ }
+
+ }
+ return false;
+ }
+}
Property changes on: trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/ResteasyEnabler.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/TeiidRSProvider.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/TeiidRSProvider.java (rev 0)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/TeiidRSProvider.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.teiid.jboss.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLXML;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.types.Transform;
+import org.teiid.core.types.TransformationException;
+import org.teiid.core.util.ReaderInputStream;
+import org.teiid.jboss.IntegrationPlugin;
+
+public abstract class TeiidRSProvider {
+
+ public InputStream execute(String procedureSignature, Map<String, String> parameters, String charSet) throws SQLException {
+ Object result = null;
+ Connection conn = getConnection();
+ try {
+ List<String> paramTypes = getPathTypes(procedureSignature);
+ final String executeStatement = "call " + procedureSignature.substring(0, procedureSignature.indexOf('(')) + (parameters.isEmpty() ? "()" : createParmString(parameters.size())) + ";"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ PreparedStatement statement = conn.prepareStatement(executeStatement);
+ if (!parameters.isEmpty()) {
+ int i = 1;
+ for (Object value : parameters.values()) {
+ try {
+ Transform t = DataTypeManager.getTransform(DataTypeManager.DefaultDataTypes.STRING, paramTypes.get(i-1));
+ if (t != null) {
+ statement.setObject(i++, t.transform(value));
+ }
+ else {
+ statement.setString(i++, (String)value);
+ }
+ } catch (TransformationException e) {
+ throw new SQLException(e);
+ }
+ }
+ }
+
+ final boolean hasResultSet = statement.execute();
+ if (hasResultSet) {
+ ResultSet rs = statement.getResultSet();
+ if (rs.next()) {
+ result = rs.getObject(1);
+ } else {
+ throw new SQLException(IntegrationPlugin.Util.gs(IntegrationPlugin.Event.TEIID50092));
+ }
+ rs.close();
+ }
+ else {
+ throw new SQLException(IntegrationPlugin.Util.gs(IntegrationPlugin.Event.TEIID50092));
+ }
+
+ statement.close();
+
+ if (result instanceof SQLXML) {
+ return ((SQLXML)result).getBinaryStream();
+ }
+ else if (result instanceof Blob) {
+ return ((Blob)result).getBinaryStream();
+ }
+ else if (result instanceof Clob) {
+ return new ReaderInputStream(((Clob)result).getCharacterStream(), Charset.forName(charSet));
+ }
+ return new ByteArrayInputStream(result.toString().getBytes());
+ } finally {
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+ }
+
+ protected String createParmString(int paramCount ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("(?"); //$NON-NLS-1$
+ for (int i = 1; i < paramCount; i++) {
+ sb.append(","); //$NON-NLS-1$
+ sb.append("?"); //$NON-NLS-1$
+ }
+ sb.append(")"); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+ private ArrayList<String> getPathTypes(String pathStr ) {
+ ArrayList pathParams = new ArrayList();
+
+ String parms = pathStr.substring(pathStr.indexOf('(')+1, pathStr.indexOf(')'));
+ StringTokenizer st = new StringTokenizer(parms, ","); //$NON-NLS-1$
+ while (st.hasMoreTokens()) {
+ pathParams.add(st.nextToken());
+ }
+ return pathParams;
+ }
+
+ protected abstract Connection getConnection() throws SQLException;
+
+}
Property changes on: trunk/jboss-integration/src/main/java/org/teiid/jboss/rest/TeiidRSProvider.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties
===================================================================
--- trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties 2012-08-22 22:50:26 UTC (rev 4358)
+++ trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties 2012-08-23 14:07:39 UTC (rev 4359)
@@ -68,6 +68,8 @@
TEIID50076=For {0}.{1} VDB, recursive delegation {2} found.
TEIID50077=The translator type "{0}" was not found in configuration; VDB {1}.{2} will not be started until translator is available.
TEIID50090=No context associated. More than likely either pass-through authentication should not be used or there are no security domains defined on the embedded transport.
+TEIID50091=The URI parameters defined on procedure {0}, do not match to number of parameters defined on procedure. Correct and reploy VDB to expose this procedure through REST.
+TEIID50092=Only result produceing procedures are allowed
wrong_vdb= Wrong VDB name and/or version supplied, or VDB is not active, or not available.
# subsystem description
Added: trunk/jboss-integration/src/main/resources/rest-war/MANIFEST.MF
===================================================================
--- trunk/jboss-integration/src/main/resources/rest-war/MANIFEST.MF (rev 0)
+++ trunk/jboss-integration/src/main/resources/rest-war/MANIFEST.MF 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Dependencies: org.jboss.teiid, org.jboss.teiid.client, org.jboss.resteasy.resteasy-jaxrs
Property changes on: trunk/jboss-integration/src/main/resources/rest-war/MANIFEST.MF
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/jboss-integration/src/main/resources/rest-war/jboss-web.xml
===================================================================
--- trunk/jboss-integration/src/main/resources/rest-war/jboss-web.xml (rev 0)
+++ trunk/jboss-integration/src/main/resources/rest-war/jboss-web.xml 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jboss-web>
+ <security-domain>java:/jaas/teiid-security</security-domain>
+</jboss-web>
\ No newline at end of file
Property changes on: trunk/jboss-integration/src/main/resources/rest-war/jboss-web.xml
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/jboss-integration/src/main/resources/rest-war/web.xml
===================================================================
--- trunk/jboss-integration/src/main/resources/rest-war/web.xml (rev 0)
+++ trunk/jboss-integration/src/main/resources/rest-war/web.xml 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
+ <display-name>${context-name}</display-name>
+ <context-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.teiid.jboss.rest.TeiidRestApplication</param-value>
+ </context-param>
+ <listener>
+ <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
+ </listener>
+ <servlet>
+ <servlet-name>RestDataservice</servlet-name>
+ <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>RestDataservice</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+ <!--
+ <security-role>
+ <description>security role</description>
+ <role-name>example-role</role-name>
+ </security-role>
+
+ <security-constraint>
+ <display-name>require valid user</display-name>
+ <web-resource-collection>
+ <web-resource-name>Teiid rest application</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>example-role</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>yourdomain.com</realm-name>
+ </login-config>
+ -->
+</web-app>
\ No newline at end of file
Property changes on: trunk/jboss-integration/src/main/resources/rest-war/web.xml
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java
===================================================================
--- trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java (rev 0)
+++ trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,93 @@
+/*
+ * 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.jboss.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Properties;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.teiid.adminapi.impl.ModelMetaData;
+import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.adminapi.impl.VDBMetadataParser;
+import org.teiid.core.util.UnitTestUtil;
+import org.teiid.metadata.Datatype;
+import org.teiid.metadata.MetadataFactory;
+import org.teiid.metadata.MetadataStore;
+import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.SystemMetadata;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.parser.ParseException;
+import org.teiid.query.parser.QueryParser;
+import org.teiid.query.unittest.RealMetadataFactory;
+
+ at SuppressWarnings("nls")
+public class TestRestWebArchiveBuilder {
+
+ @Test
+ public void testBuildArchive() throws Exception {
+ VDBMetaData vdb = VDBMetadataParser.unmarshell(new FileInputStream(UnitTestUtil.getTestDataFile("sample-vdb.xml")));
+ MetadataStore ms = new MetadataStore();
+ for (ModelMetaData model: vdb.getModelMetaDatas().values()) {
+ MetadataFactory mf = buildMetadataFactory(model.getSchemaText(), model.getName());
+ ms.addSchema(mf.getSchema());
+ }
+
+ TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(ms, "Rest");
+ vdb.addAttchment(QueryMetadataInterface.class, metadata);
+ vdb.addAttchment(TransformationMetadata.class, metadata);
+ vdb.addAttchment(MetadataStore.class, ms);
+
+ RestASMBasedWebArchiveBuilder builder = new RestASMBasedWebArchiveBuilder();
+ byte[] contents = builder.createRestArchive(vdb);
+
+ ArrayList<String> files = new ArrayList<String>();
+ files.add("WEB-INF/web.xml");
+ files.add("WEB-INF/jboss-web.xml");
+ files.add("WEB-INF/classes/org/teiid/jboss/rest/View.class");
+ files.add("WEB-INF/classes/org/teiid/jboss/rest/TeiidRestApplication.class");
+ files.add("META-INF/MANIFEST.MF");
+
+ ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(contents));
+ ZipEntry ze;
+ while ((ze = zipIn.getNextEntry()) != null) {
+ assertTrue(files.contains(ze.getName()));
+ zipIn.closeEntry();
+ }
+ }
+
+
+ public MetadataFactory buildMetadataFactory(String ddl, String model) throws ParseException {
+ MetadataFactory mf = new MetadataFactory(null, 1, model, getDataTypes(), new Properties(), null);
+ new QueryParser().parseDDL(mf, ddl);
+ return mf;
+ }
+
+ static Map<String, Datatype> getDataTypes() {
+ return SystemMetadata.getInstance().getRuntimeTypeMap();
+ }
+}
Property changes on: trunk/jboss-integration/src/test/java/org/teiid/jboss/rest/TestRestWebArchiveBuilder.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/jboss-integration/src/test/resources/sample-vdb.xml
===================================================================
--- trunk/jboss-integration/src/test/resources/sample-vdb.xml (rev 0)
+++ trunk/jboss-integration/src/test/resources/sample-vdb.xml 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<vdb name="sample" version="1">
+ <property name="UseConnectorMetadata" value="true" />
+ <property name="auto-generate-rest-war" value="true"/>
+
+ <model name="Txns">
+ <source name="text-connector" translator-name="loopback" />
+ <metadata type="DDL"><![CDATA[
+ CREATE FOREIGN TABLE G1 (e1 string, e2 integer);
+ CREATE FOREIGN TABLE G2 (e1 string, e2 integer);
+ ]]> </metadata>
+ </model>
+ <model name="View" type ="VIRTUAL">
+ <metadata type="DDL"><![CDATA[
+ SET NAMESPACE 'http://teiid.org/rest' AS REST;
+ CREATE VIRTUAL PROCEDURE g1Table(IN p1 integer) RETURNS TABLE (xml_out xml) OPTIONS (UPDATECOUNT 0, "REST:METHOD" 'GET', "REST:URI" 'g1/{p1}')
+ AS
+ BEGIN
+ SELECT XMLELEMENT(NAME sample.g1Table.p1, XMLATTRIBUTES (g1Table.p1 as p1), XMLAGG(XMLELEMENT(NAME "row", XMLFOREST(e1, e2)))) AS xml_out FROM Txns.G1;
+ END
+ CREATE VIRTUAL PROCEDURE g2Table() RETURNS TABLE (xml_out string) OPTIONS (UPDATECOUNT 0, "REST:METHOD" 'GET', "REST:URI" 'g2')
+ AS
+ BEGIN
+ SELECT '{ "age":100, "name":test,messages:["msg1","msg2","msg3"]}' as xml_out;
+ END
+ ]]> </metadata>
+ </model>
+
+</vdb>
\ No newline at end of file
Property changes on: trunk/jboss-integration/src/test/resources/sample-vdb.xml
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/test-integration/common/src/test/java/org/teiid/arquillian/IntegrationTestRestWebserviceGeneration.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/arquillian/IntegrationTestRestWebserviceGeneration.java (rev 0)
+++ trunk/test-integration/common/src/test/java/org/teiid/arquillian/IntegrationTestRestWebserviceGeneration.java 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,92 @@
+/*
+ * 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.arquillian;
+
+import static org.junit.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.jboss.arquillian.junit.Arquillian;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.teiid.adminapi.Admin;
+import org.teiid.adminapi.AdminException;
+import org.teiid.adminapi.AdminFactory;
+import org.teiid.adminapi.AdminFactory.AdminImpl;
+import org.teiid.core.util.UnitTestUtil;
+import org.teiid.jdbc.AbstractMMQueryTestCase;
+import org.teiid.jdbc.TeiidDriver;
+
+ at RunWith(Arquillian.class)
+ at SuppressWarnings("nls")
+public class IntegrationTestRestWebserviceGeneration extends AbstractMMQueryTestCase {
+
+ private Admin admin;
+
+ @Before
+ public void setup() throws Exception {
+ admin = AdminFactory.getInstance().createAdmin("localhost", 9999, "admin", "admin".toCharArray());
+ }
+
+ @After
+ public void teardown() throws AdminException {
+ AdminUtil.cleanUp(admin);
+ admin.close();
+ }
+
+ @Test
+ public void testReuse() throws Exception {
+ admin.deploy("sample-vdb.xml",new FileInputStream(UnitTestUtil.getTestDataFile("sample-vdb.xml")));
+
+ assertTrue(AdminUtil.waitForVDBLoad(admin, "sample", 1, 3));
+
+ this.internalConnection = TeiidDriver.getInstance().connect("jdbc:teiid:sample at mm://localhost:31000;user=user;password=user", null);
+
+ execute("SELECT * FROM Txns.G1"); //$NON-NLS-1$
+ this.internalResultSet.next();
+
+ assertTrue(((AdminImpl)admin).getDeployments().contains("sample_1.war"));
+
+ String response = httpCall("http://localhost:8080/sample_1/view/g1/123", "GET");
+ assertEquals("<sample.g1Table.p1 p1=\"123\"><row><e1>ABCDEFGHIJ</e1><e2>0</e2></row></sample.g1Table.p1>", response);
+ }
+
+ private String httpCall(String url, String method) throws Exception {
+ StringBuffer buff = new StringBuffer();
+ HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+ connection.setRequestMethod(method);
+ connection.setDoOutput(true);
+ BufferedReader serverResponse = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ String line;
+ while ((line = serverResponse.readLine()) != null) {
+ buff.append(line);
+ }
+ return buff.toString();
+ }
+}
Property changes on: trunk/test-integration/common/src/test/java/org/teiid/arquillian/IntegrationTestRestWebserviceGeneration.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/test-integration/common/src/test/resources/sample-vdb.xml
===================================================================
--- trunk/test-integration/common/src/test/resources/sample-vdb.xml (rev 0)
+++ trunk/test-integration/common/src/test/resources/sample-vdb.xml 2012-08-23 14:07:39 UTC (rev 4359)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<vdb name="sample" version="1">
+ <property name="UseConnectorMetadata" value="true" />
+ <property name="auto-generate-rest-war" value="true"/>
+
+ <model name="Txns">
+ <source name="text-connector" translator-name="loopback" />
+ <metadata type="DDL"><![CDATA[
+ CREATE FOREIGN TABLE G1 (e1 string, e2 integer);
+ CREATE FOREIGN TABLE G2 (e1 string, e2 integer);
+ ]]> </metadata>
+ </model>
+ <model name="View" type ="VIRTUAL">
+ <metadata type="DDL"><![CDATA[
+ SET NAMESPACE 'http://teiid.org/rest' AS REST;
+ CREATE VIRTUAL PROCEDURE g1Table(IN p1 integer) RETURNS TABLE (xml_out xml) OPTIONS (UPDATECOUNT 0, "REST:METHOD" 'GET', "REST:URI" 'g1/{p1}')
+ AS
+ BEGIN
+ SELECT XMLELEMENT(NAME sample.g1Table.p1, XMLATTRIBUTES (g1Table.p1 as p1), XMLAGG(XMLELEMENT(NAME "row", XMLFOREST(e1, e2)))) AS xml_out FROM Txns.G1;
+ END
+ CREATE VIRTUAL PROCEDURE g2Table() RETURNS TABLE (xml_out string) OPTIONS (UPDATECOUNT 0, "REST:METHOD" 'GET', "REST:URI" 'g2')
+ AS
+ BEGIN
+ SELECT '{ "age":100, "name":test,messages:["msg1","msg2","msg3"]}' as xml_out;
+ END
+ ]]> </metadata>
+ </model>
+
+</vdb>
Property changes on: trunk/test-integration/common/src/test/resources/sample-vdb.xml
___________________________________________________________________
Added: svn:mime-type
+ text/plain
More information about the teiid-commits
mailing list