Matthew Clemente
Adobe ColdFusion Summit 2021
And when you don't need Java!
With lots of code examples!
One step
at a time
system = createObject("java", "java.lang.System");
writeDump( system.getenv() );
// Introduced in ColdFusion 2018
system = new java( "java.lang.System" );
writeDump( system.getenv() );
What Version of Java is ColdFusion Using?
java.lang.System
system = createObject( "java", "java.lang.System" );
writeDump( system.getProperty("java.version") );
Give it a try!
// Introduced in ColdFusion 2018
writeDump( server.system.properties.java.version );
Do you need Java here?
How do I access Environment variables?
java.lang.System
var system = createObject('java', 'java.lang.System');
for ( var key in secrets ) {
var envValue = system.getenv( secrets[key] );
if ( !isNull(envValue) && envValue.len() ) {
variables[ key ] = envValue;
continue;
}
var propValue = system.getProperty( secrets[key] );
if ( !isNull(propValue) && propValue.len() ) {
variables[ key ] = propValue;
}
}
// Introduced in ColdFusion 2018
writeDump( server.system.environment );
Do you need Java here?
How do I write to stdout?
java.lang.System
stdout = createObject( "java", "java.lang.System" ).out;
stderr = createObject( "java", "java.lang.System" ).err;
stdout.println( "ahhhhh... information." );
stderr.println( "AHHHHH! ERRORS!" );
java.lang.System.out
function writeToConsole(required message) {
var args = arguments.copy();
args["timestamp"] = now().dateTimeFormat("iso");
stdout = createObject( "java", "java.lang.System" ).out;
stdout.println(serializeJSON(args));
}
writeToConsole( 'testing' );
How can I write a newline in a string in ColdFusion?
java.lang.System
system = createObject( "java", "java.lang.System" );
nl = system.getProperty("line.separator");
How can I tell if it's a leap year?
java.util.GregorianCalendar
<CFOBJECT ACTION="CREATE" TYPE="Java"
CLASS="java.util.GregorianCalendar" NAME="myCalendar">
<CFSET is2001LeapYear = myCalendar.isLeapYear(2001)>
<CFSET theYear = myCalendar.get(myCalendar.YEAR)>
<CFSET theMonth = myCalendar.get(myCalendar.MONTH) + 1>
<CFSET theDay = myCalendar.get(myCalendar.DATE)>
<cfoutput>
<html>
<body>Is 2001 a leap-year? <b>#is2001LeapYear#</b>
<p>Today is the <b>#theMonth# / #theDay# / #theYear#</b>
</body>
</html>
</cfoutput>
That code was 20 years old!
🤯
// Introduced in some time after 2001
writeDump( isLeapYear(2001) );
You don't need Java here!
Can I preserve the order of keys in a struct?
java.util.LinkedHashMap
serial = createObject("java","java.util.LinkedHashMap").init();
serial.a = 1;
serial.b = 2;
serial.c = 3;
writeDump( serial );
// Introduced in ColdFusion 2016
serial = structNew( "ordered" );
serial.a = 1;
serial.b = 2;
serial.c = 3;
writeDump( serial );
Do you need Java here?
How do I create a standardized UUID?
java.util.UUID
uuid = createObject( "java", "java.util.UUID" );
writeDump( uuid.randomUUID().toString() );
How do I return the local hostname of the server?
java.net.InetAddress
function getHostname(){
return createObject( 'java', 'java.net.InetAddress' )
.getLocalHost()
.getHostName();
}
writeDump( getHostname() );
How do I work with Unix (Epoch) timestamps?
java.time.Instant
timestamp = 1637249609000;
instant = createObject("java","java.time.Instant").ofEpochMilli(timestamp);
date_time = createObject("java","java.util.Date").from( instant );
result = dateTimeFormat( date_time, 'full' );
writeDump(result);
So can I generate a Unix (Epoch) timestamp?
java.time.Instant
date_time = "2007-12-03T10:15:30.00Z";
instant = createObject("java","java.time.Instant").parse(date_time);
writeDump(instant.toEpochMilli());
instant = createObject("java", "java.time.Instant");
writeDump( instant.now().getEpochSecond() );
Can I gzip text strings?
java.util.zip.GZIPOutputStream
function gzip(required string str) {
if (!str.length()) {
return str;
}
var obj = createObject('java', 'java.io.ByteArrayOutputStream').init();
var gzip = createObject('java', 'java.util.zip.GZIPOutputStream').init(obj);
gzip.write(str.getBytes('UTF-8'));
gzip.close();
return binaryEncode(obj.toByteArray(), 'base64');
}
str = '“It is not the critic who counts; not the man who points out how the strong man stumbles, or where the doer of deeds could have done them better. The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood; who strives valiantly; who errs, who comes short again and again, because there is no effort without error and shortcoming; but who does actually strive to do the deeds; who knows great enthusiasms, the great devotions; who spends himself in a worthy cause; who at the best knows in the end the triumph of high achievement, and who at the worst, if he fails, at least fails while daring greatly, so that his place shall never be with those cold and timid souls who neither know victory nor defeat.”';
compressed = gzip(str);
writeDump(compressed);
size = [
"Original": arrayLen(str.getBytes()),
"Gzipped": arrayLen(compressed.getBytes())
];
writeDump(size);
Can I un-gzip compressed text strings?
java.util.zip.GZIPInputStream
function ungzip(required string str) {
var buffReader = createObject('java', 'java.io.BufferedReader').init(
createObject('java', 'java.io.InputStreamReader').init(
createObject('java', 'java.util.zip.GZIPInputStream').init(
createObject('java', 'java.io.ByteArrayInputStream').init(
toBinary(arguments.str))
)
)
);
var result = buffReader.readLine();
return result;
}
str = 'H4sIAAAAAAAAAFVS25HcMAxrhQV4roGtIP9pQLboFSd67Ii0Pf67QpLmrpKA0k7m8mWZhEAA1Nfn7x9GolSbkSWmrYvJRldqtLWjmj7+tUqoo/5qgjq1wyi1a7TUeqvPgVA7yppZF2odcO48ELFxp7ZTZI7q1DlSCqc36kAUWtmM+wf9HDI4iqGUwatk7T8F0Bs2O0LON0kdrdC5hsW7yrSHjR1UQgcPrTfFQ41CjaQXh3lac2vxMfggX05WOkOWUC3fs8y96/KOoqCtqXXcfQbMdIZxWiByC4cOE51nlsT77thLLHlOYEIaY75zgE7q80ErWk6PcL45mmrcc5y2R2ZT0q/aLqVndxNcLR0qQQtUOm6WI5/NpNX3DX1xReJJinLePa5AFzSkm4bsiQpzxSsjpjnjnSsujy80HeWVfIVJnglqk/DJBSKWYewbC+gVVQHUdyEZ+tDKHMA+/oGWDGOhI4epO98LqfsFMiHEV/YlakIkVDGpQ9zIExDf8dbwgnywSRHkihelQ0Rl8U0MG3TKZq3fWElHMDvmfHx9/vkLKBERbfYCAAA=';
writeDump(ungzip(str));
How can I easily parse URLS?
regex????
java.net.URI
uri = 'https://blog.mattclemente.com/etc';
parsed_uri = createObject( "java","java.net.URI" ).init( uri );
uri_components = {
"Scheme": parsed_uri.getScheme(),
"Scheme Specific Part": parsed_uri.getSchemeSpecificPart(),
"Authority": parsed_uri.getAuthority(),
"User Info": parsed_uri.getUserInfo(),
"Host": parsed_uri.getHost(),
"Port": parsed_uri.getPort(),
"Path": parsed_uri.getPath(),
"Query": parsed_uri.getQuery(),
"Fragment": parsed_uri.getFragment()
}
writeDump( uri_components );
java.net.URI ⚔ java.net.URL
🧐
Can I generate URL Safe Base64 Encoding?
java.util.Base64
function urlSafeBase64Encode(str) {
return createObject("java", "java.util.Base64")
.getUrlEncoder()
.withoutPadding()
.encodeToString(str.getBytes("UTF-8"));
}
str = "subjects?_d=1"
base64 = toBase64(str);
writeDump({ "Standard Base64": base64});
urlSafeBase64 = urlSafeBase64Encode(str);
writeDump({ "URL Safe Base64": urlSafeBase64 });
java.util.Base64
function urlSafeBase64Encode(str) {
return createObject("java", "java.util.Base64")
.getUrlEncoder()
.withoutPadding()
.encodeToString(str.getBytes("UTF-8"));
}
function urlSafeBase64Decode(str) {
var bytes = createObject("java", "java.util.Base64")
.getUrlDecoder()
.decode(str);
return createObject("java", "java.lang.String").init(bytes);
}
urlSafeBase64 = urlSafeBase64Encode("subjects?_d=1");
writeDump({ "URL Safe Base64": urlSafeBase64 });
writeDump({ "Decoded": urlSafeBase64Decode(urlSafeBase64)});
How can I randomly shuffle elements in a list?
books = [
"Pilgrim at Tinker Creek",
"Long Day's Journey into Night",
"We are in a Book!",
"A Confederacy of Dunces",
"Pride and Prejudice"
];
createObject('java','java.util.Collections').Shuffle(books);
writeDump(books);
java.util.Collections.Shuffle()
What if I need to cycle through the list?
books = [
"Pilgrim at Tinker Creek",
"Long Day's Journey into Night",
"We are in a Book!",
"A Confederacy of Dunces",
"Pride and Prejudice"
];
writeDump(books);
collection = createObject('java','java.util.Collections');
collection.Rotate(books,-1);
writeDump(books);
collection.Rotate(books,-1);
writeDump(books);
java.util.Collections.Rotate()
What else can I do with these "Collections"?
books = [
"Pilgrim at Tinker Creek",
"Long Day's Journey into Night",
"We are in a Book!",
"A Confederacy of Dunces",
"Pride and Prejudice"
];
writeDump(books);
createObject('java','java.util.Collections').Reverse(books);
writeDump(books);
min = createObject('java','java.util.Collections').min(books);
writeDump({"min": min});
max = createObject('java','java.util.Collections').max(books);
writeDump({"max": max});
createObject('java','java.util.Collections').swap(books,0,1);
writeDump(books);
java.util.Collections
Can I perform DNS lookups?
com.sun.jndi.dns.DnsContextFactory
function dnsLookup(domain, type, dnsServer = "8.8.8.8", timeout = 2000, retries = 1){
var dnsRecords = [];
var env = CreateObject('java','java.util.Hashtable');
env.put('java.naming.factory.initial','com.sun.jndi.dns.DnsContextFactory');
env.put('java.naming.provider.url', 'dns://#dnsServer#');
env.put('com.sun.jndi.dns.timeout.initial', javaCast('string', timeout));
env.put('com.sun.jndi.dns.timeout.retries', javaCast( 'string', retries));
var dirContext = CreateObject('java', 'javax.naming.directory.InitialDirContext');
dirContext.init( env );
try {
var records = dirContext.getAttributes( domain, [ type ] ).get( type ).getAll();
while( records.hasMore() ) {
var record = records.next().ToString();
dnsRecords.append( record );
}
} catch ( any e ){} //if there are no records, the lookup fails
return dnsRecords;
}
mxRecords = dnsLookup( "mattclemente.com", "MX" );
writeDump( mxRecords );
How can I do faster string concatenation?
start = getTickCount();
sys = createObject( "java", "java.lang.System" );
nl = sys.getProperty("line.separator");
csvstr = "Email,Rand" & nl;
cfloop( from=1, to=50000, index="i" ){
csvstr &= "#i#@test.com,";
csvstr &= "#randRange(1,1000)#"
csvstr &= nl;
}
result = {"Time": getTickCount() - start}
writeDump(result);
start = getTickCount();
sys = createObject( "java", "java.lang.System" );
nl = sys.getProperty("line.separator");
csvstr = "Email,Rand" & nl;
cfloop( from=1, to=50000, index="i" ){
csvstr &= "#i#@test.com,#randRange(1,1000)##nl#";
}
result = {"Time": getTickCount() - start}
writeDump(result);
start = getTickCount();
sys = createObject( "java", "java.lang.System" );
nl = sys.getProperty("line.separator");
csvstr = createObject("java","java.lang.StringBuffer");
csvstr.append("Email,Rand" & nl );
cfloop( from=1, to=50000, index="i" ){
csvstr.append("#i#@test.com," & randRange(1,1000) & nl);
}
result = {"Time": getTickCount() - start}
writeDump(result);
java.lang.StringBuffer
Do you need Java here?
start = getTickCount();
arr = ["Email,Rand"];
cfloop( from=1, to=50000, index="i" ){
arr.append("#i#@test.com,#randRange(1,1000)#");
}
sys = createObject( "java", "java.lang.System" );
nl = sys.getProperty("line.separator");
csvstr = arr.toList( nl );
result = {"Time": getTickCount() - start}
writeDump(result);
start = getTickCount();
sys = createObject( "java", "java.lang.System" );
nl = sys.getProperty("line.separator");
savecontent variable="csvstr" {
writeOutput("Email,Rand");
cfloop( from=1, to=50000, index="i" ){
writeOutput("#i#@test.com" & "," & randRange(1,1000) & nl);
}
};
result = {"Time": getTickCount() - start}
writeDump(result);
It's basically a zip.
this.javaSettings
// defaults
this.javaSettings = {
// paths to directories containing Java jars / classes
loadPaths: [], // only required setting
loadColdFusionClassPath: false,
reloadOnChange: false,
watchInterval: 60, //seconds
watchExtensions: "jar,class"
}
this.javaSettings
// Application.cfc
this.javaSettings = {
loadPaths: [
".\java\myjar.jar",
".\java_lib\"
]
}
// Application.cfc
this.javaSettings = {
loadPaths: directoryList(
path = expandPath( "/lib" ),
recurse = true,
type = 'file' )
};
Jsoup = createObject("java", "org.jsoup.Jsoup");
uri = "https://blog.mattclemente.com";
doc = Jsoup.connect( uri ).get();
title = doc.title();
writeDump(title);
links = doc.select("a[href]");
// writeDump( var='#links#', abort='true' );
for( link in links ){
parsed = {
"Text": link.wholeText(),
"href": link.attr("abs:href")
}
writeDump( parsed );
}
sanitizer = createObject("java","org.owasp.validator.html.AntiSamy");
policyFile = expandPath( 'config/default.xml' );
str = "<p> This is a test for
<h1 onclick= “alert(‘malicious code’);” > AntiSamy </h1>";
clean_results = sanitizer.scan( str, policyFile );
result = [
"Input": str,
"Cleaned": clean_results.getCleanHTML(),
"Errors": clean_results.getErrorMessages()
]
writeDump(result);
// Input
<p> This is a test for <h1 onclick= “alert(‘malicious code’);” > AntiSamy </h1>
// Cleaned
<p> This is a test for </p> <h1> AntiSamy </h1>
// Error message
The h1 tag contained an attribute that we could not process. The onclick attribute has been filtered out, but the tag is still in place. The value of the attribute was "alert(malicious".
// Introduced in ColdFusion 11
unsafeHtml = "<p> This is a test for <h1 onclick= “alert(‘malicious code’);” > AntiSamy </h1>";
writeDump( isSafeHTML(unsafeHtml) );
writeDump( getSafeHTML(unsafeHtml) );
Do you need Java here?
# Project Info. This comment refers to the whole document.
---
firstName: John
lastName: Doe
age: 20
grades:
CS: 10
Math: 9
other:
- 1
- 2
- 3
eoyaml = createObject("java", "com.amihaiemil.eoyaml.Yaml");
yaml_file = createObject("java", "java.io.File").init("example.yaml");
yml_parsed = eoyaml.createYamlInput(yaml_file).readYamlMapping();
iterator = yml_parsed.keys().iterator();
while( iterator.hasNext() ) {
key = iterator.next();
writedump(key.value());
writedump(yml_parsed.value(key.value()));
}
writeDump( var='#yml_parsed.comment().value()#', abort='true' );
yaml = eoyaml.createYamlMappingBuilder()
.add("name", "Elizabeth")
.add(
"siblings",
eoyaml.createYamlSequenceBuilder()
.add("Jane")
.add("Mary")
.add("Kitty")
.add("Lydia")
.build()
).add(
"suitors",
eoyaml.createYamlSequenceBuilder()
.add("Darcy")
.add("Wickham")
.add("Collins")
.build()
).build();
# Output of previous slide
name: Elizabeth
siblings:
- Jane
- Mary
- Kitty
- Lydia
suitors:
- Darcy
- Wickham
- Collins
Matthew Clemente
Adobe ColdFusion Summit 2021