/* * 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.AASTORE; import static org.objectweb.asm.Opcodes.ACC_ENUM; import static org.objectweb.asm.Opcodes.ACC_FINAL; import static org.objectweb.asm.Opcodes.ACC_PRIVATE; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; import static org.objectweb.asm.Opcodes.ACC_SUPER; import static org.objectweb.asm.Opcodes.ALOAD; import static org.objectweb.asm.Opcodes.ANEWARRAY; import static org.objectweb.asm.Opcodes.ARETURN; import static org.objectweb.asm.Opcodes.ASTORE; import static org.objectweb.asm.Opcodes.ATHROW; import static org.objectweb.asm.Opcodes.DUP; import static org.objectweb.asm.Opcodes.F_SAME1; import static org.objectweb.asm.Opcodes.GETFIELD; import static org.objectweb.asm.Opcodes.GETSTATIC; import static org.objectweb.asm.Opcodes.ICONST_0; import static org.objectweb.asm.Opcodes.ICONST_1; import static org.objectweb.asm.Opcodes.ICONST_2; import static org.objectweb.asm.Opcodes.ICONST_3; import static org.objectweb.asm.Opcodes.ICONST_4; import static org.objectweb.asm.Opcodes.ICONST_5; import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; import static org.objectweb.asm.Opcodes.INVOKESPECIAL; import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; import static org.objectweb.asm.Opcodes.NEW; import static org.objectweb.asm.Opcodes.POP; import static org.objectweb.asm.Opcodes.PUTFIELD; import static org.objectweb.asm.Opcodes.RETURN; import static org.objectweb.asm.Opcodes.V1_5; import static org.objectweb.asm.Opcodes.V1_6; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; 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.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import org.apache.commons.io.IOUtils; 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.objectweb.asm.Opcodes; 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.deployers.RestWarGenerator; 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.ProcedureParameter.Type; import org.teiid.metadata.Schema; import org.teiid.query.metadata.TransformationMetadata; import org.teiid.vdb.runtime.VDBKey; import io.swagger.annotations.ApiResponse; @SuppressWarnings("nls") public class RestASMBasedWebArchiveBuilder implements RestWarGenerator { @Override public boolean hasRestMetadata(VDBMetaData vdb) { String generate = vdb.getPropertyValue(REST_NAMESPACE+"auto-generate"); //$NON-NLS-1$ if (generate == null || !Boolean.parseBoolean(generate)) { return false; } String securityType = vdb.getPropertyValue(REST_NAMESPACE+"security-type"); //$NON-NLS-1$ if (securityType != null && !securityType.equalsIgnoreCase("none") && !securityType.equalsIgnoreCase("httpbasic")) { //$NON-NLS-1$ //$NON-NLS-2$ return false; } MetadataStore metadataStore = vdb.getAttachment(TransformationMetadata.class).getMetadataStore(); for (ModelMetaData model: vdb.getModelMetaDatas().values()) { Schema schema = metadataStore.getSchema(model.getName()); if (schema == null) { continue; //OTHER type, which does not have a corresponding Teiid schema } 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; } @Override public byte[] getContent(VDBMetaData vdb) throws IOException { MetadataStore metadataStore = vdb.getAttachment(TransformationMetadata.class).getMetadataStore(); Properties props = new Properties(); String fullName = vdb.getName() + "_" + vdb.getVersion(); props.setProperty("${context-name}", fullName); props.setProperty("${vdb-name}", vdb.getName()); props.setProperty("${vdb-version}", String.valueOf(vdb.getVersion())); props.setProperty("${api-page-title}", fullName + " API"); String securityType = vdb.getPropertyValue(REST_NAMESPACE+"security-type"); String securityDomain = vdb.getPropertyValue(REST_NAMESPACE+"security-domain"); String securityRole = vdb.getPropertyValue(REST_NAMESPACE+"security-role"); props.setProperty("${security-role}", ((securityRole == null)?"rest":securityRole)); props.setProperty("${security-domain}", ((securityDomain == null)?"teiid-security":securityDomain)); if (securityType == null) { securityType = "httpbasic"; } if (securityType.equalsIgnoreCase("none")) { props.setProperty("${security-content}", ""); } else if (securityType.equalsIgnoreCase("httpbasic")) { props.setProperty("${security-content}", replaceTemplates(getFileContents("rest-war/httpbasic.xml"), props)); } 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()); writeEntry("api.html", out, replaceTemplates(getFileContents("rest-war/api.html"), props).getBytes()); writeDirectoryEntry(out, "swagger-ui-2.1.1.zip"); String version = vdb.getVersion(); VDBKey vdbKey = new VDBKey(vdb.getName(), vdb.getVersion()); ArrayList<String> applicationViews = new ArrayList<String>(); for (ModelMetaData model:vdb.getModelMetaDatas().values()) { Schema schema = metadataStore.getSchema(model.getName()); if (schema == null) { continue; //OTHER type, which does not have a corresponding Teiid schema } byte[] viewContents = getViewClass(vdb.getName(), version, model.getName(), schema, true); 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()); byte[] bytes = getBootstrapServletClass(vdb.getName(), vdb.getDescription() == null ? vdb.getName() : vdb.getDescription(), vdbKey.getSemanticVersion(), new String[]{"http"}, File.separator + props.getProperty("${context-name}"), "org.teiid.jboss.rest", true); writeEntry("WEB-INF/classes/org/teiid/jboss/rest/Bootstrap.class", out, bytes); writeEntry("images/teiid_logo_450px.png", out, getBinaryFileContents("rest-war/teiid_logo_450px.png")); out.close(); return byteStream.toByteArray(); } protected byte[] getBootstrapServletClass(String vdbName, String desc, String version, String[] schamas, String baseUrl, String packages, Boolean scan) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); MethodVisitor mv; AnnotationVisitor av0; cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "org/teiid/jboss/rest/Bootstrap", null, "org/teiid/jboss/rest/BootstrapServlet", null); { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "org/teiid/jboss/rest/BootstrapServlet", "<init>", "()V"); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } //init method { mv = cw.visitMethod(ACC_PUBLIC, "init", "(Lio/swagger/jaxrs/config/BeanConfig;)V", null, null); av0 = mv.visitAnnotation("Ljava/lang/Override;", true); av0.visitEnd(); mv.visitCode(); mv.visitVarInsn(ALOAD, 1); mv.visitLdcInsn(vdbName); mv.visitMethodInsn(INVOKEVIRTUAL, "io/swagger/jaxrs/config/BeanConfig", "setTitle", "(Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, 1); mv.visitLdcInsn(desc); mv.visitMethodInsn(INVOKEVIRTUAL, "io/swagger/jaxrs/config/BeanConfig", "setDescription", "(Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, 1); mv.visitLdcInsn(version); mv.visitMethodInsn(INVOKEVIRTUAL, "io/swagger/jaxrs/config/BeanConfig", "setVersion", "(Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, 1); mv.visitInsn(ICONST_1); mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); Integer[] array = new Integer[]{ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5}; for(int i = 0 ; i < schamas.length ; i ++) { mv.visitInsn(DUP); mv.visitInsn(array[i]); mv.visitLdcInsn(schamas[i]); mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKEVIRTUAL, "io/swagger/jaxrs/config/BeanConfig", "setSchemes", "([Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, 1); mv.visitLdcInsn(baseUrl); mv.visitMethodInsn(INVOKEVIRTUAL, "io/swagger/jaxrs/config/BeanConfig", "setBasePath", "(Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, 1); mv.visitLdcInsn(packages); mv.visitMethodInsn(INVOKEVIRTUAL, "io/swagger/jaxrs/config/BeanConfig", "setResourcePackage", "(Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, 1); mv.visitInsn(scan?ICONST_1:ICONST_0); mv.visitMethodInsn(INVOKEVIRTUAL, "io/swagger/jaxrs/config/BeanConfig", "setScan", "(Z)V"); mv.visitInsn(RETURN); mv.visitMaxs(2, 1); mv.visitEnd(); } cw.visitEnd(); return cw.toByteArray(); } private void writeDirectoryEntry(ZipOutputStream out, String name) throws IOException { ZipFile zipFile = getZipFile(name); Enumeration<?> en = zipFile.entries(); while(en.hasMoreElements()) { ZipEntry entry = (ZipEntry) en.nextElement(); if(!entry.isDirectory()) { writeEntry(entry.getName(), out, IOUtils.toByteArray(zipFile.getInputStream(entry))); } } FileUtils.remove(new File(zipFile.getName())); } private ZipFile getZipFile(String name) throws IOException { InputStream in = this.getClass().getClassLoader().getResourceAsStream(name); File file = new File(System.getProperty("java.io.tmpdir") + File.separator + System.currentTimeMillis() + ".zip"); FileOutputStream fos = new FileOutputStream(file); byte[] buff = new byte[1024 * 4]; int read; while((read = in.read(buff, 0, buff.length)) != -1) { fos.write(buff, 0, read); } fos.flush(); fos.close(); return new ZipFile(file); } 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 byte[] getBinaryFileContents(String file) throws IOException { InputStream in = this.getClass().getClassLoader().getResourceAsStream(file); return IOUtils.toByteArray(in); } private String replaceTemplates(String orig, Properties replacements) { for (String key:replacements.stringPropertyNames()) { orig = StringUtil.replace(orig, key, replacements.getProperty(key)); } return orig; } private static HashSet<String> getPathParameters(String uri ) { HashSet<String> pathParams = new HashSet<String>(); 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); mv.visitFieldInsn(GETFIELD, "org/teiid/jboss/rest/TeiidRestApplication", "singletons", "Ljava/util/Set;"); mv.visitTypeInsn(NEW, "io/swagger/jaxrs/listing/ApiListingResource"); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, "io/swagger/jaxrs/listing/ApiListingResource", "<init>", "()V"); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "add", "(Ljava/lang/Object;)Z"); mv.visitInsn(POP); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, "org/teiid/jboss/rest/TeiidRestApplication", "singletons", "Ljava/util/Set;"); mv.visitTypeInsn(NEW, "io/swagger/jaxrs/listing/SwaggerSerializers"); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, "io/swagger/jaxrs/listing/SwaggerSerializers", "<init>", "()V"); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "add", "(Ljava/lang/Object;)Z"); mv.visitInsn(POP); 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(); } protected byte[] getViewClass(String vdbName, String vdbVersion, String modelName, Schema schema, boolean passthroughAuth) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 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); av0.visitEnd(); } { av0 = cw.visitAnnotation("Lio/swagger/annotations/Api;", true); av0.visit("value", "/" + modelName); 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(REST_NAMESPACE+"URI", false); String method = procedure.getProperty(REST_NAMESPACE+"METHOD", false); String contentType = procedure.getProperty(REST_NAMESPACE+"PRODUCES", false); String charSet = procedure.getProperty(REST_NAMESPACE+"CHARSET", false); 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(vdbName, vdbVersion, modelName, procedure, method, uri, cw, contentType, charSet, passthroughAuth); hasValidProcedures = true; } } } buildQueryProcedure(vdbName, vdbVersion, modelName, "xml", cw, passthroughAuth); buildQueryProcedure(vdbName, vdbVersion, modelName, "json", cw, passthroughAuth); 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 vdbName, String vdbVersion, String modelName, Procedure procedure, String method, String uri, ClassWriter cw, String contentType, String charSet, boolean passthroughAuth) { List<ProcedureParameter> params = new ArrayList<ProcedureParameter>(procedure.getParameters().size()); boolean usingReturn = false; boolean hasLobInput = false; for (ProcedureParameter p : procedure.getParameters()) { if (p.getType() == Type.In || p.getType() == Type.InOut) { params.add(p); } else if (p.getType() == Type.ReturnValue && procedure.getResultSet() == null) { usingReturn = true; } if (!hasLobInput) { String runtimeType = p.getRuntimeType(); hasLobInput = DataTypeManager.isLOB(runtimeType); } } int paramsSize = params.size(); MethodVisitor mv; boolean useMultipart = false; if (method.toUpperCase().equals("POST") && hasLobInput) { useMultipart = true; } AnnotationVisitor av0; { StringBuilder paramSignature = new StringBuilder(); paramSignature.append("("); for (int i = 0; i < paramsSize; i++) { paramSignature.append("Ljava/lang/String;"); } paramSignature.append(")"); if (useMultipart) { mv = cw.visitMethod(ACC_PUBLIC, procedure.getName()+contentType.replace('/', '_'), "(Lorg/jboss/resteasy/plugins/providers/multipart/MultipartFormDataInput;)Ljavax/ws/rs/core/StreamingOutput;", null, new String[] { "javax/ws/rs/WebApplicationException" }); } else { mv = cw.visitMethod(ACC_PUBLIC, procedure.getName()+contentType.replace('/', '_'), paramSignature+"Ljavax/ws/rs/core/StreamingOutput;", 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(); } { av0 = mv.visitAnnotation("Lio/swagger/annotations/ApiOperation;", true); av0.visit("value", procedure.getName()); av0.visitEnd(); } { av0 = mv.visitAnnotation("Lio/swagger/annotations/ApiResponses;", true); ApiResponse[] array = new ApiResponse[]{}; AnnotationVisitor av1 = av0.visitArray("value"); for(int i = 0 ; i < array.length ; i ++) { av1.visit("value", array[i]); } av1.visitEnd(); av0.visitEnd(); } if(useMultipart) { av0 = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true); { AnnotationVisitor av1 = av0.visitArray("value"); av1.visit(null, "multipart/form-data"); av1.visitEnd(); } av0.visitEnd(); } if(!useMultipart) { // post only accepts Form inputs, not path params HashSet<String> pathParms = getPathParameters(uri); for (int i = 0; i < paramsSize; i++) { String paramType = "Ljavax/ws/rs/FormParam;"; if (method.toUpperCase().equals("GET")) { paramType = "Ljavax/ws/rs/QueryParam;"; } if (pathParms.contains(params.get(i).getName())){ paramType = "Ljavax/ws/rs/PathParam;"; } av0 = mv.visitParameterAnnotation(i, paramType, true); av0.visit("value", params.get(i).getName()); av0.visitEnd(); av0 = mv.visitParameterAnnotation(i, "Lio/swagger/annotations/ApiParam;", true); av0.visit("value", params.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); if (!useMultipart) { 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(params.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); mv.visitLdcInsn(vdbName); mv.visitLdcInsn(vdbVersion); mv.visitLdcInsn(procedure.getSQLString()); mv.visitVarInsn(ALOAD, paramsSize+1); mv.visitLdcInsn(charSet==null?"":charSet); mv.visitInsn(passthroughAuth?ICONST_1:ICONST_0); mv.visitInsn(usingReturn?ICONST_1:ICONST_0); mv.visitMethodInsn(INVOKEVIRTUAL, "org/teiid/jboss/rest/"+modelName, "execute", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/LinkedHashMap;Ljava/lang/String;ZZ)Ljavax/ws/rs/core/StreamingOutput;"); 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(7, paramsSize+2); mv.visitEnd(); } else { mv.visitVarInsn(ALOAD, 0); mv.visitLdcInsn(vdbName); mv.visitLdcInsn(vdbVersion); mv.visitLdcInsn(procedure.getSQLString()); mv.visitVarInsn(ALOAD, 1); mv.visitLdcInsn(charSet==null?"":charSet); mv.visitInsn(passthroughAuth?ICONST_1:ICONST_0); mv.visitInsn(usingReturn?ICONST_1:ICONST_0); mv.visitMethodInsn(INVOKEVIRTUAL, "org/teiid/jboss/rest/"+modelName, "executePost", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/jboss/resteasy/plugins/providers/multipart/MultipartFormDataInput;Ljava/lang/String;ZZ)Ljavax/ws/rs/core/StreamingOutput;"); mv.visitLabel(l1); mv.visitInsn(ARETURN); mv.visitLabel(l2); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/sql/SQLException"}); mv.visitVarInsn(ASTORE, 2); mv.visitTypeInsn(NEW, "javax/ws/rs/WebApplicationException"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 2); 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(8, 3); mv.visitEnd(); } } } private void buildQueryProcedure(String vdbName, String vdbVersion, String modelName, String context, ClassWriter cw, boolean passthroughAuth) { MethodVisitor mv; { AnnotationVisitor av0; mv = cw.visitMethod(ACC_PUBLIC, "sqlQuery"+context, "(Ljava/lang/String;)Ljavax/ws/rs/core/StreamingOutput;", null, null); { av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true); { AnnotationVisitor av1 = av0.visitArray("value"); av1.visit(null, "application/"+context); av1.visitEnd(); } av0.visitEnd(); } { av0 = mv.visitAnnotation("Ljavax/ws/rs/POST;", true); av0.visitEnd(); } { av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true); av0.visit("value", "/query"); av0.visitEnd(); } { av0 = mv.visitAnnotation("Lio/swagger/annotations/ApiOperation;", true); av0.visit("value", context); av0.visitEnd(); } { av0 = mv.visitAnnotation("Lio/swagger/annotations/ApiResponses;", true); ApiResponse[] array = new ApiResponse[]{}; AnnotationVisitor av1 = av0.visitArray("value"); for(int i = 0 ; i < array.length ; i ++) { av1.visit("value", array[i]); } av1.visitEnd(); av0.visitEnd(); } { av0 = mv.visitParameterAnnotation(0, "Lio/swagger/annotations/ApiParam;", true); av0.visit("value", context); av0.visitEnd(); } { av0 = mv.visitParameterAnnotation(0, "Ljavax/ws/rs/FormParam;", true); av0.visit("value", "sql"); 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.visitVarInsn(ALOAD, 0); mv.visitLdcInsn(vdbName); mv.visitLdcInsn(vdbVersion); mv.visitVarInsn(ALOAD, 1); mv.visitInsn(context.equals("xml")?ICONST_0:ICONST_1); mv.visitInsn(passthroughAuth?ICONST_1:ICONST_0); mv.visitMethodInsn(INVOKEVIRTUAL, "org/teiid/jboss/rest/"+modelName, "executeQuery", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)Ljavax/ws/rs/core/StreamingOutput;"); mv.visitLabel(l1); mv.visitInsn(ARETURN); mv.visitLabel(l2); mv.visitFrame(F_SAME1, 0, null, 1, new Object[] {"java/sql/SQLException"}); mv.visitVarInsn(ASTORE, 2); mv.visitTypeInsn(NEW, "javax/ws/rs/WebApplicationException"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 2); 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(6, 3); mv.visitEnd(); } } }