Tom Schober's Blog Rotating Header Image

Detecting Code-behind in Actionscript

Code-behind is a TERRIBLE practice yet completely possible in Flex via:

<mx:Script source=”blah.as”>

My Orphan Finder script adds detection for this, but I had to update it because the regular expression I use to define a valid non-code-behind file was slightly off.  So in case you’re curious, doing a grep on a file like so will help you:

grep "package[[:space:]]\{0,1\}\(.\{1,\}\(\..\{1,\}\).\{1,\}\)\{0,1\}" $filePath

No lines will be returned if this $filePath is code behind.  Those .as files don’t have package definitions.

Killing Orphans

Ok the title sounds really bad and I might want to rethink the evil connotation I’m giving to the term “Orphan,”  but in software development, they ARE evil.  So after you run the findOrphans script I made, kill them!  Use the file created by the script called UnusedClassFiles.  It has full paths.

for filePath in $(<UnusedClassFiles) ; do rm $filePath ; done

Then rebuild, test your application, and commit the cleanup.

Implementing Orphan Finder for Your Flex App

I recently posted how to detect unused classes (orphans) in your Flex Application (Bigger, Badder, Orphan Finder) so here’s an implementation of it and a downloadable version:

Download Here: findOrphans

Here’s how you can write a script of your own to use it and save yourself a lot of typing:

#!/bin/bash FLEXHOME="/Applications/Adobe Flash Builder 4/sdks/4.1.0" PROJECT_ROOT="/path/to/your/flex/project/" BUILD_DIR="/path/to/your/flex/project/build/dir" SOURCE_DIRS="/proj1dir/src/main/flex,/proj2/src/main/flex" OUTPUT_DIR="/path/to/desired/output" SWF_PATH="/path/to/project/swf/dir/MyProject.swf" echo "Updating code..." svn update "$PROJECT_ROOT" mvn -f "$BUILD_DIR/pom.xml" clean install ./findOrphans -f "$FLEXHOME" -p $PROJECT_ROOT -l $SOURCE_DIRS -o $OUTPUT_DIR -s $SWF_PATH

Dont forget to chmod +x myProjectScript

Late Hotel Checkins and Getting a Free Night’s Sleep

There’s this blurry line that exists in hotel check-in times.  Most commonly, corporate policy dictates that you cannot check in until 3pm on the day of arrival.  That’s just a suggestion though.  Most hotel front desks have the ability to check you in at any time from 12am – 3pm.  So what if you show up at just after midnight?  If you’re staying at a hotel that isn’t right off a major interstate you can pull off getting an extra night’s sleep for free.

The reason this won’t work near interstate highways, is that is a typical time for people to show up and get a rest from long road trips.  If you’re at a hotel that isn’t busy at that hour you can ask (in a naive sounding voice):

“I’m a lot later than I thought I’d be today.  Do I have to pay for yesterday or can I just check in for today early?”

A lot of registration systems won’t even allow a check-in between about 3am-5am Eastern Time, because there’s nightly maintenance that occurs in the system.  Sometimes they’ll be generous and just take your credit card info and let you go sleep; checking you in later.  Your best bet is actually after 3am ET.  The reason for this is that some registration systems are based on Pacific Time.  So you have to wait until after midnight Pacific.

This is really playing off the generosity of the hotel clerk, so BE NICE!  They don’t owe you anything at that hour.   It’s probably even best to ask them how their late night has been, or what it’s like working at that hour.  This shouldn’t even be fake; I’m sure it sucks to work that shift.

Good luck :)

Getting the Most Bag for your Buck

The more I travel, the more I start to forget the finer details that differentiate the airlines’ policies on baggage. The baggage policy debacle started years ago when the airlines freaked out about going under, and now we have this confusing mess. I thought I’d write down the details so as to not get dinged hundreds of dollars by making the wrong assumption about an airline’s baggage policy.

Comparison of The Baggage Policies from Some Airlines I Fly Frequently

1st Bag
($)
2nd Bag
($)
1st Bag
Frequent Flyer
($)
2nd Bag
Frequent Flyer
($)
Weight Limit
(lbs)
Weight Limit
Frequent Flyer
(lbs)
Delta23*/2532*/35FREEFREE5070
US Air2535FREEFREE5050
SouthwestFREEFREEFREEFREE5050
Airtran2025FREEFREE5050
Continental23*/2532*/35FREEFREE5070†
Jet BlueFREE30N/AN/A50N/A
* If Checked in Online
† Continental starts its baggage benefits at the Gold Tier

What’s best for whom


For the infrequent traveler, the best option is Southwest, followed up in a close second by Jet Blue.  Combined with these airlines’ already very low fares, FREE baggage makes these airlines a great bargain.

 

For the elite traveler, Delta is the most valuable.  Most airlines give the free 1st and 2nd bag benefit to their frequent flyers, but only a few offer a higher weight limit as well.  Continental would be tied for best, but their benefits don’t start until you reach their Gold Level frequent flyer program.  Delta gives it to you at their lowest (Silver).  In all these cases, first class passengers don’t have to pay for their first two bags.

Using a scale


If you live out of your bags like I do, you’ll want the most you can carry.  So if you’re in decent shape you can handle manuevering 140lbs of checked bags plus your two carry-ons.  Be very careful not to exceed your weight limit though or you’ll get charged an obscene fee!  The way I avoid this is by traveling with a hand scale.

 

Bigger, Badder, Orphan Finder

I decided that my Flex App Orphan Finder script hints were pretty darn useful and needed some implementation, so here’s a fully useful version:

#!/bin/bash # findOrphans # designed by Tom Schober # http://tomschober.com # Copyright (C) 2011 by Tom Schober # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. usage() { cat << EOF usage: $0 options Script to find unused class names in a Flex Project OPTIONS: -h Show this message -f Flex Home. Must be Flex 4.1 or higher due to need for swfdump (required) -p Project Root Folder (required) -l List of source folders relative to project root (comma delimited: "/firstSource,/secondSource") (required) -s Path to the SWF (before OR after build) (required) -o Output Directory Root (required) EOF } FLEXHOME= PROJECTROOT= SOURCEFOLDERS= SWFPATH= OUTPUTROOT= while getopts "hf:p:l:s:o:" OPTION do case $OPTION in h) usage exit 1 ;; f) FLEXHOME=$OPTARG ;; p) PROJECTROOT=$OPTARG ;; l) SOURCEFOLDERS=$OPTARG ;; s) SWFPATH=$OPTARG ;; o) OUTPUTROOT=$OPTARG ;; ?) usage exit ;; esac done if [[ -z $FLEXHOME ]] || [[ -z $PROJECTROOT ]] || [[ -z $OUTPUTROOT ]] || [[ -z $SWFPATH ]] || [[ -z $SOURCEFOLDERS ]] then usage exit 1 fi if [ ! -d "$FLEXHOME" ]; then echo "Directory ($FLEXHOME) does not exist" exit fi if [ ! -d "$PROJECTROOT" ]; then echo "Directory ($PROJECTROOT) does not exist" exit fi if [ ! -d "$OUTPUTROOT" ]; then mkdir $OUTPUTROOT fi if [[ ! -z "$SWFPATH" ]] && [[ ! -e "$SWFPATH" ]]; then echo "Specified SWF PATH (-s) $SWFPATH does not exist" exit 1 fi rm -f asFilePaths rm -f mxmlFilePaths rm -f validFiles rm -f unusedNames rm -f unusedValidFiles rm -f possibleCodeBehind echo "Disassembling SWF..." swfdumpPath=$FLEXHOME"/lib/swfdump.jar" java -ea -Dapplication.home="$FLEXHOME" -Xms32m -Xmx384m -jar "$swfdumpPath" -abc "$SWFPATH" > projectSwfDump echo "Searching for files in source directories..." declare -a sourceDirectoryArray sourceDirectoryArray=('echo ${SOURCEFOLDERS//,/ }') for sourceDirectory in "${sourceDirectoryArray[@]}" do if [ -d "$PROJECTROOT/$sourceDirectory" ]; then find "$PROJECTROOT/$sourceDirectory" -type f -name "*.as" > asFilePaths find "$PROJECTROOT/$sourceDirectory" -type f -name "*.mxml" >> mxmlFilePaths else echo "Source directory does not exist: $PROJECTROOT/$sourceDirectory" exit 1 fi done echo "Searching for code-behind and listing Actionscript classes..." for filePath in $(<asFilePaths) ; do packageString=$(grep "package[[:space:]]\{0,1\}\(.\{1,\}\(\..\{1,\}\).\{1,\}\)\{0,1\}" $filePath) if [[ -z $packageString ]]; then # There is no package definition so this is not a class. Must be code-behind! echo $filePath >> possibleCodeBehind echo "[CODE-BEHIND] $filePath" else echo $filePath >> validFiles fi done echo "Listing MXML classes..." for filePath in $(<mxmlFilePaths) ; do echo $filePath >> validFiles done echo "Searching for orphaned classes..." tput sc echo -n "" for validFile in $(<validFiles) ; do pathSegment=$(expr "$validFile" : ".*/src/main/flex/\(.*\)\..*") fullyQualifiedClassName=${pathSegment//\//.} tput rc tput el tput sc echo -n " ORPHAN TEST : $fullyQualifiedClassName" dumpSearchResult=( $(grep $fullyQualifiedClassName projectSwfDump) ) if [ ${#dumpSearchResult[@]} == 0 ]; then echo $fullyQualifiedClassName >> unusedNames echo $validFile >> unusedValidFiles tput rc tput el echo "[ORPHANED CLASS] $fullyQualifiedClassName" tput sc fi done tput rc tput el echo "Orphan Search Complete" echo "" echo "Creating output directory..." outputDirectory="$OUTPUTROOT/$(date +%Y%m%d-%H%M%S)" mkdir $outputDirectory echo "Formatting output..." sort unusedNames > $outputDirectory/UnusedClasses sort unusedValidFiles > $outputDirectory/UnusedClassFiles sort possibleCodeBehind > $outputDirectory/PossibleCodeBehind echo "Results:" if [ -e "$outputDirectory/UnusedClasses" ]; then echo $(cat $outputDirectory/UnusedClasses | wc -l)" Unused Classes" else echo "No Unused Classes Detected!" fi if [ -e "$outputDirectory/PossibleCodeBehind" ]; then echo $(cat $outputDirectory/PossibleCodeBehind | wc -l)" Possible Code-Behind Instances" else echo "No Possible Code-Behind Instances Detected!" fi # Cleanup rm -f projectSwfDump rm -f asFilePaths rm -f mxmlFilePaths rm -f validFiles rm -f unusedNames rm -f unusedValidFiles rm -f possibleCodeBehind

I’ll post an example of how to use this soon!

Finding Unused Classes in Flex Applications

After your Flex project gets a bit large you’re inevitably going to start forgetting to remove old, unused code..  Included in the Flex 4 SDK is an updated version of the SWF Tool’s swfdump application.  It’s a swf disassembler that can help you in some fun ways.  One of which is finding orphaned classes in your application.  Here’s a little script to help you do this:

If you haven’t already, as a flex developer you should already have the FLEX_HOME environment variable defined in your bash profile.  For an example on a mac see http://stackoverflow.com/questions/135688/setting-environment-variables-in-os-x

Create a directory to play in

mkdir MyProjectTemp
cd MyProjectTemp

Get a fresh copy of your application (skip this and the next step if you just want to use a swf you already have)

svn checkout https://path-to-your project/

Compile it (hopefully you’re using a tool like Maven or Ant)

mvn clean install OR ant ./build/build.xml

Execute swfdump from its home in the FlexSDK folder defined by FLEX_HOME.
Note: the “-abc” is important here (stands for Actionscript Byte Code).  You need this level of detail to search for class names in the following steps.

java -ea -Dapplication.home="$FLEX_HOME" -Xms32m -Xmx384m -jar "$FLEX_HOME/lib/swfdump.jar" -abc ./buildOutpuTarget/MyProject.swf > MyProjectSwfDump

Now we use some bash trickery to output the filenames of all the Actionscript and MXML files in our project for ONLY classes meant to be compiled.  This should EXCLUDE test cases (usually under /src/test/…).  Those are not typically included in your build and will just make noise in our search.
NOTE: the different “>” and “>>” are important so you don’t overwrite your find output every time.

find ./MyCommonLibraryProject/src/main/flex -name "*.as" -exec basename {} .as \; > classes
find ./MyCommonLibraryProject/src/main/flex -name "*.mxml" -exec basename {} .mxml \; >> classes

find ./MyMainProject/src/main/flex -name "*.as" -exec basename {} .as \; >> classes
find ./MyMainProject/src/main/flex -name "*.mxml" -exec basename {} .mxml \; >> classes

Now we have a file called “classes” that is a list of all the filenames (without extensions) in our projects.  So now some more bash fun to compare the swf dump with our file list.

for class in $(<classes) ; do grep -q $class MyProjectSwfDump || echo $class >> UnusedClassNames ; done

Now you have a file called UnusedClassNames that is a list of all class names that could not be found in your compiled application.

Happy Garbage Hunting!

Unique File Names with bash find and regex

So this problem might be more common that I thought after a little google searching. In any application that deals with photo processing (i.e. Flickr, Photoshop, Lightroom, etc) you may come across a time when you have a bunch of files in the same directory that represent different versions of the same image; like so:

1AAE45FC-580A-4857-D4CE-CCCF07101D55.jpg
1AAE45FC-580A-4857-D4CE-CCCF07101D55_m.jpg
1AAE45FC-580A-4857-D4CE-CCCF07101D55_t.jpg

(_t for thumbnail, _m for medium, etc.)

If you need to generate a list of unique identifiers that are represented in the base part of the file names you can use bash to do this (linux/macOS):

find . -regex ‘.*_t\.jpg’ -exec basename {} _t.jpg \; > uniques

where “t” is one of your image-type designators.  Or, if you aren’t using a delimeter (bad idea) you can do this:

find . -regex ‘.*t\.jpg’ -exec basename {} t.jpg \; > uniques

This will dump all the base file IDs (i.e. “1AAE45FC-580A-4857-D4CE-CCCF07101D55″) into a file called uniques.  It’s very useful if you need to do things like generate a DB setup script.

Now Performing with PasoFino Dance Studio from Atlanta

That’s How I Roll

If you travel this much you rack up mileage on your bags quickly! Check out the damage I can put on these puppies haha! A quick stop to a local Marshalls (pronounced Mar-shal-ays) can fix that problem. I decided on a couple big bags since I get two free on most airlines nowadays. Also got a carry-on size rollerboard to take on the plane. They’re nice and light so I stop going over the weight limit a few pounds.

Before

After