Java tutorial
/* * Copyright (C) 2000 - 2014 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://openbd.org/ * $Id: cfHttpConnection.java 2526 2015-02-26 15:58:34Z alan $ */ package com.naryx.tagfusion.cfm.http; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.ProxySelector; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.StatusLine; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.CookieStore; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpOptions; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpTrace; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.apache.http.client.protocol.ClientContext; import org.apache.http.client.utils.URIUtils; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.entity.ContentType; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.ContentEncodingHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.ProxySelectorRoutePlanner; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.aw20.io.StreamUtil; import org.aw20.util.StringUtil; import com.nary.net.tagFilterReader; import com.nary.net.http.urlEncoder; import com.nary.net.http.urlResolver; import com.naryx.tagfusion.cfm.engine.cfBinaryData; import com.naryx.tagfusion.cfm.engine.cfBooleanData; import com.naryx.tagfusion.cfm.engine.cfCatchData; import com.naryx.tagfusion.cfm.engine.cfData; import com.naryx.tagfusion.cfm.engine.cfEngine; import com.naryx.tagfusion.cfm.engine.cfJavaObjectData; import com.naryx.tagfusion.cfm.engine.cfNumberData; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfStringData; import com.naryx.tagfusion.cfm.engine.cfStructData; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; import com.naryx.tagfusion.cfm.file.fileDescriptor; /* * Created on each render of a CFHTTP tag */ @SuppressWarnings("deprecation") public class cfHttpConnection implements cfHttpConnectionI { private static Scheme https; private static SchemeRegistry scheme; static { try { X509HostnameVerifier hostVerifier = SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; if (System.getProperty("com.naryx.cfm.http.X509HostnameVerifier") != null) { String hostnameVerifier = System.getProperty("com.naryx.cfm.http.X509HostnameVerifier"); cfEngine.log("-] Using alternative CFHTTP hostname verifier: " + hostnameVerifier); hostVerifier = (X509HostnameVerifier) Class.forName(hostnameVerifier).newInstance(); } SSLContext sslcontext = SSLContext.getDefault(); SSLSocketFactory socketFactory = new SSLSocketFactory(sslcontext, hostVerifier); https = new Scheme("https", 443, socketFactory); scheme = new SchemeRegistry(); scheme.register(https); } catch (Exception e) { cfEngine.log("-] Failed due to " + e.getClass().getName() + ": " + e.getMessage()); } } private DefaultHttpClient client; private HttpUriRequest message; private boolean isMultipart; private MultipartEntityBuilder multipartEntityBuilder = null; public cfHttpConnection(cfSession _session, cfHttpData _httpData) throws cfmRunTimeException { this(_session, _httpData, null, null); } public cfHttpConnection(cfSession _session, cfHttpData _httpData, File _clientCert, String _clientPassword) throws cfmRunTimeException { init(_session, _httpData); if (_clientCert != null) { try { client = getHttpClient(_clientCert, _clientPassword); } catch (Exception e) { throw newRunTimeException("Failed to instantiate http client due to certificate issue. " + e.getClass().getName() + " was thrown: " + e.getMessage()); } } else { client = new ContentEncodingHttpClient(); } client.getParams().setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true); resolveLinks = false; } @Override public void setMethod(String _method, boolean _multipart) throws cfmRunTimeException { message = resolveMethod(_method, _multipart); isMultipart = _multipart; } @Override public void setURL(String _url, int _port) throws cfmRunTimeException { port = _port; url = _url; if (_url.startsWith("/")) { url = "http://" + session.REQ.getServerName() + ":" + session.REQ.getServerPort() + session.REQ.getContextPath() + url; } try { ((HttpRequestBase) message).setURI(new URI(url)); } catch (URISyntaxException ue) { throw newRunTimeException("Failed to set URL:" + ue.getReason()); } int uriPort = message.getURI().getPort(); if (port == -1 && uriPort == -1) { // use default port for http/https } else if (uriPort != -1) { // use specified port port = uriPort; } } @Override public void setProxyServer(String _proxyServer, int _proxyPort) { proxyServer = _proxyServer; proxyPort = _proxyPort; HttpHost proxy = new HttpHost(proxyServer, proxyPort); client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } @Override public void authenticate(String _user, String _password) { client.getCredentialsProvider().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(_user, _password)); } @Override public void authenticateProxy(String _user, String _password) { client.getCredentialsProvider().setCredentials(new AuthScope(proxyServer, proxyPort), new UsernamePasswordCredentials(_user, _password)); } @Override public void setFollowRedirects(boolean _follow) { followRedirects = _follow; client.getParams().setParameter("http.protocol.handle-redirects", followRedirects); } @Override public void setTimeout(int _timeout) { client.getParams().setParameter("http.connection.timeout", _timeout); client.getParams().setParameter("http.socket.timeout", _timeout); } private DefaultHttpClient getHttpClient(File pKeyFile, String pKeyPassword) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); KeyStore keyStore = KeyStore.getInstance("PKCS12"); InputStream keyInput = null; try { keyInput = new FileInputStream(pKeyFile); keyStore.load(keyInput, pKeyPassword.toCharArray()); } finally { if (keyInput != null) try { keyInput.close(); } catch (IOException ignored) { } } keyManagerFactory.init(keyStore, pKeyPassword.toCharArray()); SSLSocketFactory sf = new SSLSocketFactory(keyStore, pKeyPassword); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register(new Scheme("https", sf, 443)); ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); return new DefaultHttpClient(ccm, params); } @Override public void connect() throws cfmRunTimeException { // Collect up the request addHeaders(); addCookies(); addURLData(); addFormData(); addFiles(); setBody(); setDefaultProxy(); // if we are building up a multipart then we should add this to the message if (multipartEntityBuilder != null) { HttpEntity reqEntity = multipartEntityBuilder.build(); ((HttpPost) message).setEntity(reqEntity); } // Execute the method. int statusCode = -1; int redirectLimit = 5; HttpResponse response; try { client.getParams().setParameter("http.protocol.max-redirects", redirectLimit); response = client.execute(message); statusCode = response.getStatusLine().getStatusCode(); } catch (ConnectTimeoutException ce) { if (!throwOnError) { handleError("Connect Exception: Connection timed out.", "Connection Failed"); } else { throw newRunTimeException("Connect Exception: Connection timed out."); } return; } catch (ClientProtocolException e) { if (!throwOnError) { handleError("Connect Exception: " + e.getMessage(), "Connection Failed"); } else { throw newRunTimeException("Failed due to invalid Protocol: " + e.getMessage()); } return; } catch (IOException e) { if (!throwOnError) { handleError("Connect Exception: " + e.getMessage(), "Connection Failed"); } else { throw newRunTimeException("Connect Exception: " + e.getMessage()); } return; } // if status code is -1 if (statusCode != -1) handleResponse(response, statusCode); } private void setDefaultProxy() { HttpHost currentProxy = (HttpHost) client.getParams().getParameter(ConnRoutePNames.DEFAULT_PROXY); if (currentProxy == null) { ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner( client.getConnectionManager().getSchemeRegistry(), ProxySelector.getDefault()); client.setRoutePlanner(routePlanner); } } private void handleResponse(HttpResponse response, int _statusCode) throws cfmRunTimeException { // if the status code is not 2xx and throwOnError is true then throw an exception if (throwOnError && (_statusCode < 200 || _statusCode > 299)) { throw newRunTimeException(_statusCode + " " + response.getStatusLine().getReasonPhrase()); } // Read response headers Header[] respHeaders = response.getAllHeaders(); cfStructData responseHeaders = new cfStructData(); StringBuilder allHeaders = new StringBuilder(); String mimeType = ""; Header nextHeader; // loop through the response headers creating the necessary cfStructData // if there are any duplicate headers then an array of the values is created for (int i = 0; i < respHeaders.length; i++) { nextHeader = respHeaders[i]; if (responseHeaders.containsKey(nextHeader.getName())) { cfData headerVals = responseHeaders.getData(nextHeader.getName()); if (headerVals.getDataType() == cfData.CFSTRUCTDATA) { ((cfStructData) headerVals).setData(String.valueOf(((cfStructData) headerVals).size() + 1), new cfStringData(nextHeader.getValue())); } else { cfStructData newHeaderVals = new cfStructData(); newHeaderVals.setData("1", headerVals); newHeaderVals.setData("2", new cfStringData(nextHeader.getValue())); responseHeaders.setData(nextHeader.getName(), newHeaderVals); } } else { responseHeaders.setData(nextHeader.getName(), new cfStringData(nextHeader.getValue())); } allHeaders.append(nextHeader); if (nextHeader.getName().toLowerCase().equals("content-type")) mimeType = nextHeader.getValue(); } httpData.setData("responseheader", responseHeaders); StatusLine httpStatus = response.getStatusLine(); responseHeaders.setData("HTTP_VERSION", new cfStringData(httpStatus.getProtocolVersion().toString())); responseHeaders.setData("EXPLANATION", new cfStringData(httpStatus.getReasonPhrase())); responseHeaders.setData("STATUS_CODE", new cfNumberData(_statusCode)); httpData.setData("header", new cfStringData(httpStatus.toString() + " " + allHeaders.toString())); httpData.setData("mimetype", new cfStringData(mimeType)); int charsetIndex = mimeType.toLowerCase().indexOf("charset"); String charsetFromHeader = null; if (charsetIndex != -1) { charsetFromHeader = mimeType.substring(charsetIndex + 8).trim(); httpData.setData("charset", new cfStringData(charsetFromHeader)); } else { httpData.setData("charset", new cfStringData("")); } byte[] responseBody = getResponseBody(response, outFile); if (responseBody == null) { throw newRunTimeException("Failed to read response body."); } cfData fileContent = null; byte resultType = getResultType(mimeType); switch (resultType) { case OBJECT: if (outFile == null) { java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream(); bos.write(responseBody, 0, responseBody.length); fileContent = new cfJavaObjectData(bos); break; } case BINARY: if (outFile == null) fileContent = new cfBinaryData(responseBody); else fileContent = new cfStringData(new String(responseBody)); break; case STRING: String fileContentStr = getAsString(responseBody, charsetFromHeader); if (resolveLinks) { fileContentStr = resolveLinks(fileContentStr); } fileContent = new cfStringData(fileContentStr); break; } httpData.setData("filecontent", fileContent); // if binary data then we ignore if (query != null && fileContent.getDataType() == cfData.CFSTRINGDATA) { handleQuery(fileContent.getString()); } httpData.setData("statuscode", new cfStringData(_statusCode + " " + httpStatus.getReasonPhrase())); httpData.setData("errordetail", new cfStringData("")); httpData.setData("text", fileContent.getDataType() == cfData.CFSTRINGDATA ? cfBooleanData.TRUE : cfBooleanData.FALSE); cleanHttpData(); } @Override public void close() throws IOException { client.getConnectionManager().shutdown(); } // Private Methods private HttpUriRequest resolveMethod(String _method, boolean _multipart) throws cfmRunTimeException { String method = _method.toUpperCase(); if (method.equals("GET")) { return new HttpGet(); } else if (method.equals("POST")) { return new HttpPost(); } else if (method.equals("HEAD")) { return new HttpHead(); } else if (method.equals("TRACE")) { return new HttpTrace(); } else if (method.equals("DELETE")) { return new HttpDelete(); } else if (method.equals("OPTIONS")) { return new HttpOptions(); } else if (method.equals("PUT")) { return new HttpPut(); } throw newRunTimeException("Unsupported METHOD value [" + method + "]. Valid METHOD values are GET, POST, HEAD, TRACE, DELETE, OPTIONS and PUT."); } private void addURLData() throws cfmRunTimeException { addQueryStringData(httpData.getURLData(), httpData.getCharset()); } private void addQueryStringData(Map<String, String> _data, String _charset) throws cfmRunTimeException { if (_data.size() > 0) { // don't need to do anything if there's no url data // to add StringBuilder queryString = new StringBuilder(); // method.getQueryString() // ); Iterator<String> keys = _data.keySet().iterator(); while (keys.hasNext()) { String nextKey = keys.next(); try { queryString.append(urlEncoder.encode(nextKey, _charset)); } catch (UnsupportedEncodingException e1) { queryString.append(urlEncoder.encode(nextKey)); } queryString.append('='); try { queryString.append(urlEncoder.encode(_data.get(nextKey), _charset)); } catch (UnsupportedEncodingException e) { queryString.append(urlEncoder.encode(_data.get(nextKey))); } queryString.append("&"); } // remove last &. We know there is at least one url param queryString = queryString.deleteCharAt(queryString.length() - 1); String currentQStr = message.getURI().getQuery(); if (currentQStr == null) currentQStr = ""; try { URI uri = message.getURI(); String schemeName = uri.getScheme(); String hostName = uri.getHost(); int port = uri.getPort(); String fragment = uri.getFragment(); String path = uri.getPath(); String queryStr = queryString.toString(); if (currentQStr.length() > 0) { uri = URIUtils.createURI(schemeName, hostName, port, path, currentQStr + '&' + queryStr, fragment); } else { uri = URIUtils.createURI(schemeName, hostName, port, path, queryStr, fragment); } ((HttpRequestBase) message).setURI(uri); } catch (URISyntaxException e) { throw newRunTimeException("Failed due to URI Syntax Error: " + e.getMessage()); } } } private void addFormData() throws cfmRunTimeException { Map<String, String> formData = httpData.getFormData(); Iterator<String> keys = formData.keySet().iterator(); String nextKey; if (message.getMethod().equalsIgnoreCase("POST")) { if (isMultipart || httpData.getFiles().size() > 0) { if (multipartEntityBuilder == null) multipartEntityBuilder = MultipartEntityBuilder.create().setCharset(charset); while (keys.hasNext()) { nextKey = keys.next(); multipartEntityBuilder.addPart(nextKey, new StringBody(formData.get(nextKey), ContentType.TEXT_PLAIN)); } } else { Header contentType = message.getFirstHeader("Content-type"); if (contentType == null) { // otherwise it's been set manually so don't override it message.setHeader("Content-type", "application/x-www-form-urlencoded"); } StringBuilder paramStr = new StringBuilder(); while (keys.hasNext()) { nextKey = keys.next(); paramStr.append(nextKey); paramStr.append('='); paramStr.append(formData.get(nextKey)); paramStr.append('&'); } if (paramStr.length() > 0) { paramStr.deleteCharAt(paramStr.length() - 1); // remove last & ((HttpPost) message).setEntity(new StringEntity(paramStr.toString(), this.charset)); } } } } private void addFiles() throws cfmRunTimeException { List<fileDescriptor> files = httpData.getFiles(); if (files.size() > 0) { if (message instanceof HttpPost && (isMultipart || httpData.getFiles().size() > 0)) { if (multipartEntityBuilder == null) multipartEntityBuilder = MultipartEntityBuilder.create().setCharset(charset); for (int i = 0; i < files.size(); i++) { fileDescriptor nextFile = files.get(i); multipartEntityBuilder.addPart(nextFile.getName(), new FileBody(nextFile.getFile(), ContentType.create(nextFile.getMimeType()), nextFile.getFile().getName())); } } else if (message instanceof HttpPut) { fileDescriptor nextFile = files.get(0); // just use the first file specified try { FileInputStream fileIn = new FileInputStream(nextFile.getFile()); InputStreamEntity entity = new InputStreamEntity(fileIn, nextFile.getFile().length(), ContentType.create(nextFile.getMimeType())); ((HttpPut) message).setEntity(entity); } catch (FileNotFoundException e) { throw newRunTimeException("Failed to locate file " + nextFile.getFile().getAbsolutePath()); } } } } /** * Reads the response from the remote site * * @param _response * @param gzip * @param file * @return */ private byte[] getResponseBody(HttpResponse _response, File file) { Header contentLenHdr = _response.getFirstHeader("Content-Length"); int expected = StringUtil.toInteger((contentLenHdr != null) ? contentLenHdr.getValue() : null, 4096); try { if (_response.getEntity() != null) { // response body might be null if there is no body e.g. HEAD method used InputStream in = _response.getEntity().getContent(); if (file != null) { FileOutputStream out = new FileOutputStream(file); try { StreamUtil.copyTo(in, out); } finally { out.close(); } return new String(file.getAbsolutePath()).getBytes(); } else { ByteArrayOutputStream out = new ByteArrayOutputStream(expected); StreamUtil.copyTo(in, out); return out.toByteArray(); } } else { return new byte[0]; } } catch (IOException ioe) { return null; } } private void addHeaders() { // There is no need to add HOST header since this is done by the // "Jakarta Commons-HttpClient" HttpClient class. message.addHeader("Connection", "close"); Map<String, String> headers = httpData.getHeaders(); Iterator<String> keys = headers.keySet().iterator(); boolean addUserAgent = true; while (keys.hasNext()) { String nextKey = keys.next(); message.addHeader(nextKey, headers.get(nextKey)); if (nextKey.equalsIgnoreCase("User-Agent")) { addUserAgent = false; } } if (addUserAgent) message.addHeader("User-agent", useragent); // only set the content-type if it hasn't already been set, thus allowing for it to be overridden if (httpData.isBodySet() && message.getLastHeader("Content-type") == null) message.setHeader("Content-type", httpData.getContentType()); } private void addCookies() { Map<String, List<String>> cookies = httpData.getCookies(); Iterator<String> keys = cookies.keySet().iterator(); String domain = ""; domain = message.getURI().getHost(); CookieStore cookieStore = new BasicCookieStore(); HttpContext localContext = new BasicHttpContext(); // Bind custom cookie store to the local context localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); while (keys.hasNext()) { String nextKey = keys.next(); List<String> values = cookies.get(nextKey); Date date = new Date(2038, 1, 1); for (int i = 0; i < values.size(); i++) { BasicClientCookie cookie = new BasicClientCookie(nextKey, values.get(i)); cookieStore.addCookie(cookie); cookie.setVersion(1); cookie.setDomain(domain); cookie.setPath("/"); cookie.setExpiryDate(date); cookie.setSecure(false); } } client.setCookieStore(cookieStore); } public void setBody() throws cfmRunTimeException { // if there is a request body set and this is a PUT or POST if (httpData.isBodySet()) { try { if (message instanceof HttpPost) { if (this.charset == null) { ((HttpPost) message).setEntity(new StringEntity(httpData.getBody())); } else { ((HttpPost) message).setEntity(new StringEntity(httpData.getBody(), this.charset)); } } else if (message instanceof HttpPut) { if (this.charset == null) { ((HttpPut) message).setEntity(new StringEntity(httpData.getBody())); } else { ((HttpPut) message).setEntity(new StringEntity(httpData.getBody(), this.charset)); } } } catch (UnsupportedEncodingException | UnsupportedCharsetException e) { throw newRunTimeException( "Failed due to UnsupportedEncoding while setting body: " + e.getMessage()); } } } protected String url; protected int port; protected Charset charset; protected boolean resolveLinks; protected boolean followRedirects; protected String useragent; protected cfSession session; protected boolean throwOnError; protected String getAsBinary; protected File outFile = null; protected queryDetails query = null; protected cfHttpData httpData; protected String proxyServer; protected int proxyPort; protected final static byte STRING = 0, BINARY = 1, OBJECT = 2; protected void init(cfSession _session, cfHttpData _httpData) { session = _session; httpData = _httpData; } protected void handleQuery(String _page) throws cfmRunTimeException { if (query == null) return; // shouldn't happen but check anyway if (query.columns == null && _page.trim().length() == 0) { throw newRunTimeException( "Cannot create Query. Empty file returned in HTTP call with no COLUMNS specified."); } if (query.name.length() == 0) { // no need to create query with no name return; } if (query.delimiter.length() != 1) { throw newRunTimeException("Invalid delimiter value. Delimiter must be one character in length."); } char delimiter = query.delimiter.charAt(0); if (query.textqualifier.length() > 1) { throw newRunTimeException( "Invalid textQualifier set. TextQualifier must be 0 or 1 character in length."); } // get columns and create the query // columns are given in the tag as COLUMNS parameter new cfHttpQueryData(session, _page, query.columns, query.name, delimiter, query.textqualifier, false, query.firstRowAsHeaders); } protected void saveToFile(cfData _filecontent) throws cfmRunTimeException { try { FileOutputStream fout = new FileOutputStream(outFile); if (_filecontent.getDataType() == cfData.CFSTRINGDATA) { fout.write(_filecontent.getString().getBytes()); } else if (_filecontent.getDataType() == cfData.CFBINARYDATA) { fout.write(((cfBinaryData) _filecontent).getByteArray()); } fout.flush(); fout.close(); } catch (IOException ioe) { throw newRunTimeException("Failed to save filecontent to file. IOException: " + ioe); } } protected String resolveLinks(String _content) { tagFilterReader reader = new tagFilterReader(new StringReader(_content)); reader.registerTagFilter(new urlResolver(url, port)); java.io.StringWriter writer = new java.io.StringWriter(); try { int ch = reader.readChar(); while (ch != -1) { writer.write(ch); ch = reader.readChar(); } return writer.toString(); } catch (IOException ignored) { } // won't happen since the source is a String return _content; } protected cfmRunTimeException newRunTimeException(String _msg) { cfCatchData catchData = new cfCatchData(session); catchData.setMessage(_msg); return new cfmRunTimeException(catchData); } private class queryDetails { String name; String columns; String textqualifier; String delimiter; boolean firstRowAsHeaders; public queryDetails(String _name, String _cols, String _tq, String _delim, boolean _first) { name = _name; columns = _cols; textqualifier = _tq; delimiter = _delim; firstRowAsHeaders = _first; } } @Override public void setQueryDetails(String _name, String _cols, String _textqualifier, String _delimiter, boolean _first) { query = new queryDetails(_name, _cols, _textqualifier, _delimiter, _first); } @Override public void setThrowOnError(boolean b) { throwOnError = b; } @Override public void setFile(File _out) { outFile = _out; } @Override public void setCharset(String _charset) throws cfmRunTimeException { try { charset = Charset.forName(_charset); } catch (java.nio.charset.IllegalCharsetNameException e) { throw newRunTimeException("Invalid CHARSET value specified: " + _charset + "."); } } @Override public void setUserAgent(String _ua) { useragent = _ua; } protected void cleanHttpData() { // remove headers, data, files httpData.removeData(); httpData.removeHeaders(); httpData.removeFiles(); httpData.removeCookies(); } protected static boolean isText(String _contentType) { if (_contentType.equals("") || _contentType.startsWith("text") || _contentType.startsWith("message") || _contentType.equals("application/octet-stream") || _contentType.equals("application/xml") || _contentType.equals("application/json")) { return true; } else { return false; } } protected void handleError(String _error, String _content) { httpData.setData("charset", new cfStringData("")); httpData.setData("errordetail", new cfStringData(_error)); httpData.setData("filecontent", new cfStringData(_content)); httpData.setData("header", new cfStructData()); httpData.setData("mimetype", new cfStringData("Unable to determine MIME type of file")); httpData.setData("responseheader", new cfStructData()); httpData.setData("statuscode", new cfStringData("Status code unavailable")); httpData.setData("text", cfBooleanData.TRUE); } protected byte getResultType(String _contentType) throws cfmRunTimeException { if (getAsBinary.equals("yes")) { return BINARY; } else if (getAsBinary.equals("no")) { if (isText(cleanContentType(_contentType))) { return STRING; } else { return OBJECT; } } else if (getAsBinary.equals("auto")) { if (isText(cleanContentType(_contentType))) { return STRING; } else { return BINARY; } } else { throw newRunTimeException("Invalid GETASBINARY value specified: " + getAsBinary + ". Supported values are NO, YES and AUTO."); } } private static String cleanContentType(String _contentType) { int semiColonIndx = _contentType.indexOf(';'); if (semiColonIndx != -1) { return _contentType.substring(0, semiColonIndx); } return _contentType; } @Override public void setGetAsBinary(String _gab) { getAsBinary = _gab; } @Override public void setResolveLinks(boolean _resolve) { resolveLinks = _resolve; } private String getAsString(byte[] _body, String _charsetFromHeader) throws cfmRunTimeException { if (_body == null) { return ""; } String useCharset; if (charset == null) { useCharset = _charsetFromHeader; } else { useCharset = charset.toString(); } String fileContentStr; if (useCharset != null) { try { fileContentStr = new String(_body, com.nary.util.Localization.convertCharSetToCharEncoding(useCharset)); } catch (UnsupportedEncodingException ue) { throw newRunTimeException("Unsupported charset specified: " + useCharset); } } else { fileContentStr = new String(_body); } return fileContentStr; } }