Tag a Revision using Subclipse

Posted by Dan | Posted in Development, Eclipse, Languages | Posted on 05-20-2010

0

Tagging a revision is a simple task if you’re using the subclipse plugin for Eclipse. For this example, we’re going to tag the trunk in our repository. This also assumes that your repository uses the traditional “3 directory setup” of branches, tags, and trunk.

1. Make sure you have a SVN View tab in Eclipse.

To do this, go to:
Window > Show View > Other > SVN > SVN Repositories

2. Under “WebSites” (in the following screenshot), right click on the trunk, and select “Branch/Tag…”:

3. Make sure you use the appropriate tag version that adheres to your versioning needs. Also, make sure it’s under the “tags” folder: svn://WebSites/Project-2/tags/

Implementing the Strategy Pattern in ColdFusion

Posted by Dan | Posted in ColdFusion, Java | Posted on 05-02-2010

0

In spirit of the amazing book Head First Design Patterns, I wanted to put together a ColdFusion example that depicts the Strategy pattern. Essentially, the Strategy Pattern lets you group related algorithms together so that an object is able to select which algorithm to run at runtime.

So let’s say for example you had a parent class that has two properties and two methods. You now create a subclass that inherits the parent class, meaning that it will gobble up all the properties and methods (whether you like it or not) from the parent class. You can’t choose, for example, what methods you subclass needs, even if some methods don’t make sense for your subclass. It’s an all-or-nothing solution. Yes, you can override, but what if there were 10 methods to override? Also, what if you had to create other types of subclasses – you’ll have to override those as well. Things can get a little sloppy at the end. That’s where the strategy pattern comes in.

With this pattern, you first think about related methods and algorithms. (One method can have various algorithms; different implementations for doing the same thing.) For this blog post’s example, we’ll think of different ways a SuperHero can punch. To keep things simple, let’s give him two ways (two different algorithms for punching) he can punch. He can punch normally, or he can punch you, which freezes you as well. Let’s UML this to make things clearer.

First what the lines mean:


Here’s the UML diagram for our SuperHero scenerio:


From the diagram, you can see that the SuperHero abstract class is able to choose a punch set of algorithms (a strategy). We also see that Punch and PunchFreeze are implementation classes (classes that serve to implement an interface). Both of them have a punch() method that return void (nothing) – in this example, they’ll do stuff, and not return anything.

To make things a little more interesting, and to follow closer the example in the Strategy Pattern chapter of the book, we’re going to also create a subclass called Freezer that inherits the SuperHero class. Also, we’ll create another strategy for kicking. Here’s what the UML for that looks like:


Here’s the CF code:

SuperHero.cfc

<cfcomponent>
 
<!--- This is our abstract class. Responsibility to implement is delegated to --->
<!--- classes that implement interfaces. --->
 
<cffunction name="init" access="public" returntype="SuperHero">  
  <!--- Some other init code goes here.  --->  
  <cfargument name="name" type="string">  
  <cfargument name="gender" type="string">  
  <cfset this.name = arguments.name />  
  <cfset this.gender = arguments.gender />  
  <cfreturn this />  
</cffunction>
 
<cffunction name="setPunchAlgorithm" access="public">
  <!--- The next two lines are key. It's where you set the implementation --->
  <!--- of punch from an object that's being passed in. --->
  <cfargument name="PunchAlgorithm" type="IPunchAlgorithm" required="true" />  
  <cfset this.punchAction = PunchAlgorithm.punch />
</cffunction>
 
<cffunction name="setKickAlgorithm" access="public">
  <cfargument name="KickAlgorithm" type="IKickAlgorithm" required="true" />  
  <cfset this.kickAction = KickAlgorithm.kick />
</cffunction>
 
<!--- This function will be overridden.  --->
<cffunction name="energyProject" access="public" returntype="SuperHero" >  
  You have been pointed at by a weak flash light.  
  <cfreturn this />
</cffunction>
 
</cfcomponent>

IPunchAlgorithm.cfc

<cfinterface>
 
<cffunction name="punch" access="public" />
 
</cfinterface>

Punch.cfc

<cfcomponent implements="IPunchAlgorithm">
 
<cffunction name="punch" access="public">
  You have been punched normally. Ouch.
</cffunction>
 
</cfcomponent>

PunchFreeze.cfc

<cfcomponent implements="IPunchAlgorithm">
 
<cffunction name="punch" access="public">
  You have been punched and are now frozen, stuck. Good luck thawing!
</cffunction>
 
</cfcomponent>

IKickAlgorithm.cfc

<cfinterface>
 
<cffunction name="kick" access="public" />
 
</cfinterface>

Kick.cfc

<cfcomponent implements="IKickAlgorithm">
 
<cffunction name="kick" access="public">
  You have been kicked in the gut. Yummy.
</cffunction>
 
</cfcomponent>

Freezer.cfc

<cfcomponent extends="SuperHero">
 
<!--- We are overriding the energyProject from Freezer's parent class.  --->
<cffunction name="energyProject">
  You have been snowed on. 
</cffunction>  
 
</cfcomponent>

Now let’s actually use these the pattern:

run.cfm

<!--- Create context object.  --->
<cfset IceMan = CreateObject( "component", "SuperHero" ).init( Name = "Iceman", Gender = "Male" ) />
 
<!--- Create a strategy #1 for punching.  --->
<cfset PunchStrategy_1 = CreateObject( "component", "Punch" ) />
 
<!--- Create a different strategy for punching.  --->
<cfset PunchStrategy_2 = CreateObject( "component", "PunchFreeze" ) />
 
<!--- Tell the IceMan object that you'll be using the Punch Strategy #2, NOT #1.  --->
<cfset IceMan.setPunchAlgorithm( PunchStrategy_2 ) />
 
 
<!--- Now let's create a kicking strategy... --->
<cfset KickStrategy = CreateObject( "component", "Kick" ) />
 
<!--- ... and now let's tell the IceMan object that you'll be using the Kick Strategy.  --->
<cfset IceMan.setKickAlgorithm( KickStrategy ) />
 
 
<!--- Now let's see some action!  --->
 
<!--- Punch, using the strategy chosen! --->
<cfset IceMan.punchAction() />
 
<!--- Punch, using the strategy chosen! --->
<cfset IceMan.kickAction() />
 
 
<!--- Let's create another SuperHero object. --->
<cfset Frosty = CreateObject( "component", "SuperHero" ).init( Name = "Frosty the Snowman", Gender = "Unknown" ) />
 
<!--- Let's inspect the objects --->
<p>Notice that both objects have different number of methods - only the methods they need. </p>
<cfdump var="#IceMan#" /><hr />
<cfdump var="#Frosty#" /><hr />
 
 
<!--- Let's create another SuperHero object. --->
<cfset Frostman = CreateObject( "component", "Freezer" ).init( Name = "Calvin Hobbes", Gender = "Male" ) />
<cfset Frostman.energyProject() />

You can download all the CF code here with the original Visio diagram source.

TSQL Functions Inspired By ColdFusion’s Lists Functions

Posted by Dan | Posted in ColdFusion, Databases, SQL Server | Posted on 04-27-2010

0

In my last project, there was a bit of data scrubbing on the database side (SQL Server 2008) that I decided to create a few UDF’s that function similar to ColdFusion’s Lists function. The one that varies a little bit is ListLen(), since I needed to take into account empty tokens. The ChopIf() was inspired by Perl’s chop() function. These UDFs should be SQL Server 2005-compatible.

I should say though, that some of these functions depend on each other. ListLen(), GetToken(), and ChopIf() are independent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
------------------------------------------------------------------
-- Functions similarly like ColdFusion ListSort() function,
-- except it currently only sorts strings. 
--
-- Example 1:
--    dbo.ListSort( 'dan is so mega awesome that he rules all the time', 'ASC', ' ' )
--
-- Returns: 
--    all awesome dan he is mega rules so that the time
--
-- Example 2:
--    dbo.ListSort( 'dan is so mega awesome that he rules all the time', 'DESC', ' ' )
--
-- Returns: 
--    time the that so rules mega is he dan awesome all
------------------------------------------------------------------
 
CREATE FUNCTION [dbo].[ListSort]
(
  @string    VARCHAR(2000),  
  @sort_type CHAR(3)       = 'ASC',
  @delimiter VARCHAR(2000) = ','
)
RETURNS VARCHAR(500)
AS
 
BEGIN
 
  DECLARE @position AS INT
  DECLARE @token AS VARCHAR (2000)
  DECLARE @counter   AS INT
  DECLARE @sortedList AS VARCHAR(500)
 
  DECLARE @sortTempTable TABLE ( token VARCHAR(500) )
  DECLARE @sortedTable   TABLE ( token VARCHAR(500) )  
 
  SELECT @string   = @string + @delimiter,
         @counter  = 1,
         @position = 0,
         @token    = ''
 
  WHILE ( PATINDEX( '%' + @delimiter + '%' , @string ) <> 0 ) 
  BEGIN
    SELECT @position = PATINDEX('%' + @delimiter + '%' , @string ),
           @token    = LEFT( @string, @position - 1 ),
           @string   = STUFF( @string, 1, @position, NULL ),
           @counter  = @counter + 1
 
    INSERT @sortTempTable( token ) VALUES( @token )     
  END
 
  SET @sortedList = ''
 
  -- Let's sort the table and put it into @sortedTable
  -- Because of nature of Rank(), we can't set @sortedList in this statement.
  -- Have to separate it into another select clause.
  INSERT INTO @sortedTable
    SELECT LTRIM( token )
    FROM   @sortTempTable
    ORDER  BY CASE WHEN @sort_type = 'ASC'  THEN ( RANK() OVER ( ORDER BY LTRIM(token) ASC ) )
                   WHEN @sort_type = 'DESC' THEN ( RANK() OVER ( ORDER BY LTRIM(token) DESC ) )
              END  
 
  SELECT @sortedList = @sortedList + token + @delimiter
  FROM   @sortedTable
 
  RETURN dbo.ChopIf( @sortedList, @delimiter )
 
END
GO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
------------------------------------------------------------------
-- Functions sort of like ColdFusion's ListLen() method, but it
-- takes into account empty tokens. 
--
-- Example 1:
--    dbo.ListLen( 'Dan is cool', ' ' )
--
-- Returns: 
--    3
-- 
-- Example 2:
--    dbo.ListLen( 'dan,,very,,,,awesome,', ',' )
--
-- Returns: 
--    8
------------------------------------------------------------------
 
CREATE FUNCTION [dbo].[ListLen]
(
  @string VARCHAR(2000),
  @delimiter VARCHAR(2000) = ','
)
RETURNS INT
AS
BEGIN
 
  DECLARE @loopCount INT, 
          @tokenCount INT
 
  SELECT @loopCount = 0, 
         @tokenCount = 0
 
  -- If it's an empty string, the list length is 0
  IF DATALENGTH( @string ) = 0
    BEGIN
      SET @tokenCount = 0
    END
  ELSE
    BEGIN
      -- Count tokens, including empty ones like dan,,very,,,,awesome,
      SET @tokenCount = @tokenCount + 1
      WHILE ( @loopCount < DATALENGTH( @string ) )
      BEGIN
        IF SUBSTRING( @string, @loopCount, DATALENGTH( @delimiter ) ) = @delimiter
          BEGIN
            SET @tokenCount = @tokenCount + 1
          END
        SET @loopCount = @loopCount + 1
      END
    END
 
  -- Handle extra count from space being delimiter
  IF @delimiter = ' '
    SET @tokenCount = @tokenCount - 1
 
  -- If there's no token to the right of the last delimiter, then count that
  -- as an empty token.
  IF ( RIGHT( @string, 1 ) = @delimiter ) 
  BEGIN
    SET @tokenCount = @tokenCount + 1
  END
 
  RETURN @tokenCount
 
END
GO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
------------------------------------------------------------------
-- Functions like ColdFusion's ListLast()
-- Gets token value that's been separated by a delimiter.
--
-- Example:
--    dbo.ListLast( 'Dan is cool', ' ' )
--
-- Returns: 
--    cool
------------------------------------------------------------------
 
CREATE FUNCTION [dbo].[ListLast]
(
  @string VARCHAR(2000),
  @delimiter VARCHAR(2000) = ','
)
RETURNS VARCHAR(2000)
AS
BEGIN
 
  RETURN dbo.ListGetAt( @string, dbo.ListLen( @string, @delimiter ) , @delimiter  )
 
END
GO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
------------------------------------------------------------------
-- Wrapper for GetToken() Function
-- Gets token value that's been separated by a delimiter.
--
-- Example:
--    dbo.ListGetAt( 'Dan is cool', 2, ' ' )
--
-- Returns: 
--    is
------------------------------------------------------------------
 
CREATE FUNCTION [dbo].[ListGetAt]
(
  @string VARCHAR(2000),
  @token INT,
  @delimiter VARCHAR(2000)
)
RETURNS VARCHAR(2000)
AS
BEGIN
  RETURN dbo.GetToken( @string, @token, @delimiter )
END
GO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
------------------------------------------------------------------
-- Returns the first item in a tokenized list.
--
-- Example:
--    dbo.ListFirst( 'Dan is cool', ' ' )
--
-- Returns: 
--    Dan
------------------------------------------------------------------
 
CREATE FUNCTION [dbo].[ListFirst]
(
  @string VARCHAR(2000),
  @delimiter VARCHAR(2000) = ','
)
RETURNS VARCHAR(2000)
AS
BEGIN
 
  RETURN dbo.ListGetAt( @string, 1, @delimiter )
 
END
GO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
------------------------------------------------------------------
-- Functions similarly like ColdFusion GetToken() Function.
-- Gets token value that's been separated by a delimiter.
--
-- Example:
--    dbo.GetToken( 'Dan is cool', 2, ' ' )
--
-- Returns: 
--    is
------------------------------------------------------------------
 
CREATE FUNCTION [dbo].[GetToken]
(
  @string VARCHAR(2000),
  @tokenPosition INT,
  @delimiter VARCHAR(2000)
)
RETURNS VARCHAR(2000)
AS
BEGIN
 
  DECLARE @position AS INT
  DECLARE @token AS VARCHAR (2000)
  DECLARE @counter AS INT
 
  SELECT @string = @string + @delimiter,
         @counter = 1,
         @position = 0,
         @token = ''
 
  WHILE ( PATINDEX('%' + @delimiter + '%' , @string ) <> 0) AND ( @tokenPosition + 1 <> @counter )
  BEGIN
    SELECT @position = PATINDEX('%' + @delimiter + '%' , @string),
           @token    = LEFT(@string, @position-1),
           @string   = STUFF(@string, 1, @position, null),
           @counter  = @counter + 1
  END
 
  RETURN @token
END
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
------------------------------------------------------------------
-- Chops the last character if it's @chopped
--
-- Example:
--    dbo.ChopIf( 'Dan is cool!', '!' )
--
-- Returns: 
--    Dan is cool
------------------------------------------------------------------
 
CREATE FUNCTION [dbo].[ChopIf]
(
  @string VARCHAR(2000),
  @chopped VARCHAR(2000)
)
RETURNS VARCHAR(2000)
AS
BEGIN
 
  IF ( RIGHT( @string, DATALENGTH(@chopped) ) = @chopped )
  BEGIN
    SET @string = LEFT( @string, DATALENGTH( @string ) - DATALENGTH( @chopped ) ) 
  END 
 
  RETURN @string
 
END
GO

Generate Junk Files

Posted by Dan | Posted in Python | Posted on 04-24-2010

0

The other day I was testing benchmarks for a delete script. I needed to create files with various file sizes. More specific, 1,000,000 files with 5K per file. A while ago I found this great snippet on StackOverflow to generate a junk random string:

junk =  (("%%0%dX" % (junk_len * 2)) % random.getrandbits(junk_len * 8)).decode("hex")

I’ve wrapped that around to make a utility function and snippet:

import os, random, sys
 
# This tool takes 3 parameters
#
#   testing <directory to put files in> <how many files> <size of each file in bytes>
#
# Example:
#
#   testing dan 100 500
 
def createLocalDirectory( directoryName ):
  if not os.path.exists( directoryName ):
    os.makedirs( directoryName )
 
folderName      = sys.argv[1]
how_many_files  = int(sys.argv[2])
junk_len        = int(sys.argv[3])
 
 
createLocalDirectory( folderName )
 
for i in range( 0, how_many_files ):  
  junk =  (("%%0%dX" % (junk_len * 2)) % random.getrandbits(junk_len * 8)).decode("hex")
  path = folderName + "/" + str(i) + ".txt"
  f = open( path, 'w' )
  f.write( junk )
  print f
  f.close()

Search In One File from Keywords in Another File

Posted by Dan | Posted in Languages, Python | Posted on 04-24-2010

0

I needed to see if this list of email addresses were found in a logs file. So I had one file with a list of email addresses. Another file is a list emails sent. I needed to make sure that the emails were sent. Here’s a quick Python script I put together that does this:

import re
import sys
 
def searchInLogFile( FILE, query ):  
  FILE.seek( 0, 0 )  
  for line in LogFile:
    logLine = line.replace("\n","").replace("\r","").rstrip().lstrip()
    if re.search( query, logLine, re.IGNORECASE | re.MULTILINE ):
      return True
 
# This file has a list (\r\n delimited) email addresses.
EmailListFile = open( "email-list-internal.txt", "r")
 
# This is the log file which we'll use to see if email addresses are in here.
LogFile = open( "POST20100201.log", "r" )
 
EmailFound = []
EmailNotFound = []
breakTime = 0
# 0 = does the whole list
EmailsToSearchFor = 0
 
for emailLine in EmailListFile:
  email = emailLine.replace("\n","").replace("\r","").rstrip().lstrip()
 
  if ( searchInLogFile( LogFile, email ) ):
    print email, "was found"
    EmailFound.append( email )
 
  else:
    print email, "not found"
    EmailNotFound.append( email )  
 
 
  if ( EmailsToSearchFor != 0 ):
    breakTime += 1
    if ( breakTime == EmailsToSearchFor ):
      break;
 
LogFile.close()
EmailListFile.close()
 
# Log results to a file.
OutputFile = open( "output.log", "w" )
 
divider = "\n\n======== Found ========================================"
print divider
OutputFile.write( divider )
 
for i in EmailFound:
  print i
  OutputFile.write( "\n" + i )
 
divider = "\n\n======== Not Found ===================================="  
print divider
OutputFile.write( divider )
 
for i in EmailNotFound:
  print i
  OutputFile.write( "\n" + i )
 
OutputFile.close()

Pretty straightforward. The script also writes a file called “output.log” which has a list of emails that were found (marked under “found”) and not found (marked under “not found”).

Quick Simple Way to Show/Hide with a Checkbox using jQuery

Posted by Dan | Posted in JavaScript | Posted on 04-03-2010

0

Here’s a quick and simple way to do this. I often have to show and hide set of panels based on whether something is checked or not. jQuery code is pretty straightforward and it comes in handy.

$( function() {    
 
  function toggleCheckbox( trigger, hidethese )
  {
    if ( $( trigger ).attr("checked") )
    {
      $( hidethese ).hide();
    }
    else
    {
      $( hidethese ).show();
    }
  }
 
  // jQuery object that has your checkbox
  var triggerCheckbox = $( "#showPreonDescription" );
 
  // jQuery object for collection of elements you want to hide
  // For this example, I could've also just done #panel by itself
  // to hide everything
  var panelsToHide = $("#subpanel,#maincontent,#nav");  
 
  // Call the function on click.
  triggerCheckbox.click(
    function ()
    {
      toggleCheckbox( triggerCheckbox, panelsToHide );
    }
  );
});

I have the demo if you want the source as well.

IsNumericList() Function

Posted by Dan | Posted in ColdFusion | Posted on 04-03-2010

0

Whipped up this UDF while working on a project. It checks to see if the list is valid to use in a TSQL WHERE IN Clause. I wanted to check for a list of valid positive integers (including 0), ignoring spaces.

<cffunction name="isNumericList" returntype="boolean" hint="Check for either single positive number or a set of positive numbers. Spaces ignored." >
 
  <!--- Useful when inserting into an "IN" TSQL list in the WHERE clause.  --->
 
  <cfargument name="list" required="true">
 
  <cfargument name="delimiter" required="false" default=",">   
 
  <cfset var isNumericList = false />
 
  <cfif REFind( "^(\d+)$|^(([\d\s]+#Arguments.delimiter#)+\s*\d+)$", Trim(Arguments.list) ) >
 
    <cfreturn true >
 
  </cfif>
 
  <cfreturn isNumericList >  
 
</cffunction>

Now let’s test it!

<!--- Dummy Data --->
<cfset dataList = ArrayNew(1) />
<cfset dataList[1] = "456c" />
<cfset dataList[2] = "456" />
<cfset dataList[3] = "45c," />
<cfset dataList[4] = "5,,," />
<cfset dataList[5] = "565,651,34,643232,45" />
<cfset dataList[6] = "454,c,45,5454,32" />
<cfset dataList[7] = "121.45,43,565,1,1,2" />
<cfset dataList[8] = "43,54,65,1," />
<cfset dataList[9] = "67,54,73,436," />
<cfset dataList[10] = ",6565,656,77,32,3" />
<cfset dataList[11] = "" />
<cfset dataList[12] = ",43656" />
<cfset dataList[13] = "4365,  55,31,24,   5,   5  ,1,      34" />

Now let’s use it!

<!--- Use it! --->
<cfoutput>
   <cfloop array="#dataList#" index="i">  
      [#i#] => #isNumericList(i)#<br />
   </cfloop>
</cfoutput>

Results!

[456c] => false
 
[456] => true
 
[45c,] => false
 
[5,,,] => false
 
[565,651,34,643232,45] => true
 
[454,c,45,5454,32] => false
 
[121.45,43,565,1,1,2] => false
 
[43,54,65,1,] => false
 
[67,54,73,436,] => false
 
[,6565,656,77,32,3] => false
 
[] => false
 
[,43656] => false
 
[4365,  55,31,24,   5,   5  ,1,      34] => true

Convert Relative URLs to Absolute

Posted by Dan | Posted in ColdFusion | Posted on 02-19-2010

0

I put this ColdFusion UDF together the other day to turn relative URLs to Absolute. Code is pretty straightforward.

<cffunction name="URLRelativeToAbsolute" returntype="string"
  hint="Converts relative URLs in an element and converts to absolute. It includes the http:// protocol prefix.">  
 
  <cfargument name="content" type="string" required="true" hint="HTML content that will be scanned and replaced." />
 
  <cfargument name="domain" type="string" required="true" hint="Add domain name to relative links." />
 
  <cfset var local = StructNew() /> 
 
  <!--- The following regexp handles the following elements: link, a, img, script, form, frame. --->
  <cfset local.contentFixed = REReplaceNoCase( Arguments.content, "(href|src|action)=""/?((\./)|(\.\./)+|)(?=[^http])", "\1=""http://" & domain & "/", "all" ) />  
 
  <!--- The following regexp handles the url() attribute of the background CSS property. --->
  <cfset local.contentFixed = REReplaceNoCase( local.contentFixed, "url\((\s)?(')?/?((\./)|(\.\./)+|)(?=[^http])", "url(\2http://" & domain & "/", "all" ) />  
 
  <cfreturn local.contentFixed />    
 
</cffunction>

Usage:

<cfsavecontent variable="htmlContent">
<textarea name="data" rows="20" cols="60">
  <style>
    body { 
      background-image:url('stars.png');
      background-image:url('../stars.png');
      background-image:url('/stars.png');
      background-image:url('/../../../stars.png');
    }
  </style>
  <a href="../../../images/shiny.jpg">Shiny</a>
  <a href="http://www.google.com">This should not be touched</a>
  <img border="0" src="/images/cool.png" /> 
  <link rel="index" href="../../index.asp">
  <form method="POST" action="cgi/processing.cgi"></form>  
</textarea>
</cfsavecontent>
 
<cfoutput>
 
  #htmlContent#
  #URLRelativeToAbsolute( htmlContent, "www.shinylight.com" )#
 
</cfoutput>

Result:

Get Latest File

Posted by Dan | Posted in Automation / Scripting, Python | Posted on 02-04-2010

0

In my last post, I made a quick script that checks for the date. It was very limiting, since it used the dir command. This one uses several date/time Python modules and is more capable.

import os, os.path, stat, time
from datetime import date, timedelta, datetime
 
# Reference
# http://docs.python.org/library/datetime.html
# http://docs.python.org/library/time.html
 
def getFileDate( filenamePath ):    
 
  used = os.stat( filenamePath ).st_mtime      
  year, day, month, hour, minute, second = time.localtime(used)[:6]
  objDateTime = datetime(year, day, month, hour, minute, second)
 
  return objDateTime
 
  # Ways to reference this DateTime Object
  # objDateTime.strftime("%Y-%m-%d %I:%M %p")
  # objDateTime.year
  # objDateTime.month
 
 
def isDaysOldFromNow( filenamepath, days ):
 
  # Checks how old a file is. Is it older than "days" [variable] days?
  inTimeRange = False  
  timeDeltaDiff = ( datetime.now()-getFileDate( filenamepath ) ).days
 
  # Check if the file's date is days old or less:
  if ( timeDeltaDiff >= days ):
    inTimeRange = True  
 
  return inTimeRange
 
fname = "C:/temp/decision2.pdf"  
 
# Set this variable to check if the file is this days old
howOld = 3
 
 
if ( isDaysOldFromNow( fname, howOld ) ):
  print fname, "is more than", howOld, "days old"
else:
  print fname, "is NOT more than", howOld, "days old"

Output:

Compress and Move Log Files

Posted by Dan | Posted in Automation / Scripting, Python, Systems, Windows | Posted on 01-30-2010

0

Sometimes log files bog a system down. For one of our servers, I made this little Python script that compresses (via WinRAR) the log files in a directory, and then moves them to a backup location. The only little catch is that I wanted to leave the latest log files for in that directory. Log files are created daily, so the the latest log files have a datestamp of today. Here’s how I did it.

First Create the Python Script:

import os
import datetime
 
dateStamp  = datetime.datetime.now().strftime("%Y-%m-%d") 
imsLogPath = 'd:\\LogFiles\\'                     
# Don't use a mapped drive but use UNC for network drives. Task Schedule seems to choke when it calls Python.
newRARPath = '"\\\\192.168.1.2\\Root\\backups\\' + dateStamp + '.rar"'
rarPath    = '"C:\\Program Files\\WinRAR\\rar.exe" a -m5 ' + newRARPath 
 
# Get Latest Files
smtpLatest   = os.popen(r"dir /od /a-d /b " + imsLogPath + "SMTP*.log").read().splitlines()[-1]
postLatest   = os.popen(r"dir /od /a-d /b " + imsLogPath + "POST*.log").read().splitlines()[-1]
ischedLatest = os.popen(r"dir /od /a-d /b " + imsLogPath + "iSched*.log").read().splitlines()[-1]
relayLatest  = os.popen(r"dir /od /a-d /b " + imsLogPath + "Relay*.log").read().splitlines()[-1]
qengLatest   = os.popen(r"dir /od /a-d /b " + imsLogPath + "Qeng*.log").read().splitlines()[-1]
 
# Get List of All Files
allFiles     = os.popen(r"dir /od /a-d /b " + imsLogPath + "*.log").read().splitlines()
 
# Remove Latest Files from All Files List
allFiles.remove( smtpLatest )
allFiles.remove( postLatest )
allFiles.remove( ischedLatest )
allFiles.remove( relayLatest )
allFiles.remove( qengLatest )
 
# allFiles Array Has the list of files
 
# Flatten Array allFiles to be used as a parameter in system command
flatLogPathList = ""
for filenameWithPath in allFiles:
  flatLogPathList = flatLogPathList + imsLogPath + filenameWithPath + " "
 
 
# Execute WinRar
path = rarPath + " " + flatLogPathList.rstrip()
os.system( '"' + path + '"' )
 
# Delete all log files
os.system( '"del ' + flatLogPathList.rstrip() + '"' )

Then I set up the Scheduled Task:

With these Settings: