/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.rest.services;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.nio.charset.Charset;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.io.UnsupportedEncodingException;
import java.sql.SQLXML;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.xml.ws.WebServiceContext;
import org.teiid.core.types.BlobType;
import org.teiid.core.types.XMLType;
import org.teiid.core.util.ReaderInputStream;
import org.teiid.designer.runtime.version.spi.ITeiidServerVersion;
import org.teiid.designer.runtime.version.spi.TeiidServerVersion;
import org.teiid.query.parser.QueryParser;
import org.teiid.query.parser.TeiidNodeFactory;
import org.teiid.query.parser.TeiidParser;
import org.teiid.query.parser.TeiidNodeFactory.ASTNodes;
import org.teiid.query.sql.symbol.XMLSerialize;
import org.teiid.query.function.source.XMLSystemFunctions;
import org.teiid.rest.RestPlugin;
public class TeiidRSProviderPost {
protected WebServiceContext webServiceContext;
private static Logger logger = Logger.getLogger("org.teiid.rest"); //$NON-NLS-1$
@javax.annotation.Resource
protected void setWebServiceContext( WebServiceContext wsc ) {
webServiceContext = wsc;
}
public DataSource getDataSource(String jndiName) throws NamingException {
InitialContext ctx;
DataSource ds = null;
ctx = new InitialContext();
ds = (DataSource)ctx.lookup(jndiName); //$NON-NLS-1$
return ds;
}
public InputStream execute( String procedureName,
Map<String, String> parameterMap, String charSet, Properties properties) throws WebApplicationException {
Connection conn = null;
PreparedStatement statement = null;
Object result = null;
InputStream resultStream = null;
String responseString = null;
try {
DataSource ds = getDataSource(properties.getProperty("jndiName"));
conn = ds.getConnection();
boolean noParm = false;
if (parameterMap.isEmpty()) {
noParm = true;
}
final String executeStatement = "call " + procedureName + (noParm ? "()" : createParmString(parameterMap)) + ";"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
statement = conn.prepareStatement(executeStatement);
if (!noParm) {
int i = 1;
for (Object value : parameterMap.values()) {
statement.setString(i++, (String)value);
}
}
final boolean hasResultSet = statement.execute();
if (hasResultSet) {
ResultSet rs = statement.getResultSet();
if (rs.next()) {
result = rs.getObject(1);
} else {
logger.log(Level.WARNING, RestPlugin.Util.getString("TeiidRSProvider.8") //$NON-NLS-1$
+ procedureName);
createWebApplicationException(new Exception(RestPlugin.Util.getString("TeiidRSProvider.2")), //$NON-NLS-1$
RestPlugin.Util.getString("TeiidRSProvider.2")); //$NON-NLS-1$
}
rs.close();
}
statement.close();
resultStream = handleResult(charSet, result, properties);
} catch (SQLException e) {
String msg = RestPlugin.Util.getString("TeiidRSProvider.1"); //$NON-NLS-1$
logger.logrb(Level.SEVERE, "TeiidRSProvider", "execute", RestPlugin.PLUGIN_ID, msg, new Throwable(e)); //$NON-NLS-1$ //$NON-NLS-2$
createWebApplicationException(e, e.getMessage());
} catch (Exception e) {
String msg = RestPlugin.Util.getString("TeiidRSProvider.1"); //$NON-NLS-1$
logger.logrb(Level.SEVERE, "TeiidRSProvider", "execute", RestPlugin.PLUGIN_ID, msg, new Throwable(e)); //$NON-NLS-1$ //$NON-NLS-2$
createWebApplicationException(e, e.getMessage());
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
/*
* In this case, we do not return an exception to the
* customer. We simply log this problem. If we do
* a return from the finally block, we will override the
* return in the try/catch that will either return the
* 'true' error or return a valid result document. Either
* way we do not want to return an exception just because
* closing the connection failed.
*/
String msg = RestPlugin.Util.getString("TeiidRSProvider.1"); //$NON-NLS-1$
logger.logrb(Level.SEVERE, "TeiidRSProvider", "execute", RestPlugin.PLUGIN_ID, msg, new Throwable(e)); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
return resultStream;
}
private InputStream handleResult(String charSet, Object result, Properties properties) throws SQLException, UnsupportedEncodingException {
if (result == null) {
return null;
}
String teiidVersion = properties.getProperty("teiidVersion");
ITeiidServerVersion version = new TeiidServerVersion(teiidVersion);
QueryParser queryParser = new QueryParser(version);
TeiidParser parser = queryParser.getTeiidParser();
if (result instanceof SQLXML) {
if (charSet != null) {
XMLSerialize serialize = (XMLSerialize)TeiidNodeFactory.getInstance().create(parser, ASTNodes.XML_SERIALIZE);
serialize.setTypeString("blob"); //$NON-NLS-1$
serialize.setDeclaration(true);
serialize.setEncoding(charSet);
serialize.setDocument(true);
try {
return ((BlobType)XMLSystemFunctions.serialize(serialize, new XMLType((SQLXML)result))).getBinaryStream();
} catch (Exception e) {
throw new SQLException(e);
}
}
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(charSet));
}
protected String createParmString( Map<String, String> parameterMap ) {
StringBuilder sb = new StringBuilder();
sb.append("(?"); //$NON-NLS-1$
for (int i = 1; i < parameterMap.size(); i++) {
sb.append(","); //$NON-NLS-1$
sb.append("?"); //$NON-NLS-1$
}
sb.append(")"); //$NON-NLS-1$
return sb.toString();
}
protected void createWebApplicationException( final Exception e,
final String faultSoapPluginString ) throws WebApplicationException {
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}