Sunday, April 14, 2013

Struts2 + Hibernate + Jpa 2 + Spring + Netbeans how to make it all work together

After many days of frustration, searching, trying ..and failing finally got it working and because I couldn't locate any full descriptions online I will lay out my solution here.

Bare in mind that if you use different versions of these libraries, you should be sure that they are compatible with each other, because one of the issues I was dealing with (and I didn't know that at the time) was because of incompatible libraries.

So I am using:

netbeans  7.3

hibernate: hibernate-release-4.1.8.Final download
                  (+ hibernate-entitymanager-4.0.1.Final) download


listing:
hibernate-release-4.1.8.Final/lib/required/antlr-2.7.7.jar
hibernate-release-4.1.8.Final/lib/required/dom4j-1.6.1.jar
hibernate-release-4.1.8.Final/lib/required/hibernate-commons-annotations-4.0.1.Final.jar
hibernate-release-4.1.8.Final/lib/required/hibernate-core-4.1.8.Final.jar
hibernate-release-4.1.8.Final/lib/required/hibernate-jpa-2.0-api-1.0.1.Final.jar
hibernate-release-4.1.8.Final/lib/required/javassist-3.15.0-GA.jar
hibernate-release-4.1.8.Final/lib/required/jboss-logging-3.1.0.GA.jar
hibernate-release-4.1.8.Final/lib/required/jboss-transaction-api_1.1_spec-1.0.0.Final.jar
hibernate-entitymanager-4.0.1.Final


aopalliance: aopaliance 1.0  download 

aopalliance.jar

Spring    : spring3.1.1release (bundled with netbeans  7.3)


listing: 

spring-aop-3.1.1.RELEASE.jar
spring-asm-3.1.1.RELEASE.jar
spring-aspects-3.1.1.RELEASE.jar
spring-beans-3.1.1.RELEASE.jar
spring-context-3.1.1.RELEASE.jar
spring-context-support-3.1.1.RELEASE.jar
spring-core-3.1.1.RELEASE.jar
spring-expression-3.1.1.RELEASE.jar
spring-instrument-3.1.1.RELEASE.jar
spring-instrument-tomcat-3.1.1.RELEASE.jar
spring-jdbc-3.1.1.RELEASE.jar
spring-jms-3.1.1.RELEASE.jar
spring-orm-3.1.1.RELEASE.jar
spring-oxm-3.1.1.RELEASE.jar
spring-struts-3.1.1.RELEASE.jar
spring-test-3.1.1.RELEASE.jar
spring-tx-3.1.1.RELEASE.jar
spring-web-3.1.1.RELEASE.jar
spring-webmvc-3.1.1.RELEASE.jar
spring-webmvc-portlet-3.1.1.RELEASE.jar



Struts2    : struts-2.3.12 download
listing:
(remember to remove unnecessary plugins - otherwise you will have problems deploying e.g I am using tiles, so I have left the plugin in listing but I also have the corresponding  tiles.xml to make it work, if you don't just do not include struts2-tiles-plugin)

asm-3.3.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
classworlds-1.1.jar
commons-beanutils-1.8.0.jar
commons-chain-1.2.jar
commons-collections-3.1.jar
commons-digester-2.0.jar
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
commons-lang-2.4.jar
commons-lang3-3.1.jar
commons-logging-1.1.1.jar
commons-logging-api-1.1.jar
commons-validator-1.3.1.jar
ezmorph-1.0.6.jar
freemarker-2.3.19.jar
google-collections-1.0.jar
google-gxp-0.2.4-beta.jar
jackson-core-asl-1.9.2.jar
jackson-mapper-asl-1.9.2.jar
javassist-3.11.0.GA.jar
json-lib-2.3-jdk15.jar
juli-6.0.18.jar
ognl-3.0.6.jar
org.apache.felix.bundlerepository-1.2.1.jar
org.apache.felix.framework-1.4.1.jar
org.apache.felix.main-1.4.1.jar
org.apache.felix.shell-1.0.2.jar
org.apache.felix.shell.tui-1.0.2.jar
oval-1.31.jar
plexus-container-default-1.0-alpha-10.jar
plexus-utils-1.2.jar
struts2-convention-plugin-2.3.12.jar
struts2-core-2.3.12.jar
struts2-dojo-plugin-2.3.12.jar
struts2-embeddedjsp-plugin-2.3.12.jar
struts2-jasperreports-plugin-2.3.12.jar
struts2-javatemplates-plugin-2.3.12.jar
struts2-spring-plugin-2.3.12.jar
struts2-tiles-plugin-2.3.12.jar
testng-5.1-jdk15.jar
tiles-api-2.0.6.jar
tiles-core-2.0.6.jar
tiles-jsp-2.0.6.jar
xmlpull-1.1.3.1.jar
xpp3_min-1.1.4c.jar
xstream-1.4.2.jar
xwork-core-2.3.12.jar




web.xml
...
 <filter>
        <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

  <!-- deprecated
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
        <init-param>
            <param-name>actionPackages</param-name>
            <param-value>my.action</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

...

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:aop="http://www.springframework.org/schema/aop"
               xmlns:tx="http://www.springframework.org/schema/tx"
               xmlns:context="http://www.springframework.org/schema/context"
               xmlns:p="http://www.springframework.org/schema/p" 
               xmlns:cache="http://www.springframework.org/schema/cache" 
               xmlns:jee="http://www.springframework.org/schema/jee"
               xsi:schemaLocation="
                    http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                    http://www.springframework.org/schema/tx
                    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
                    http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
                    http://www.springframework.org/schema/context     
                    http://www.springframework.org/schema/context/spring-context-3.1.xsd
                    http://www.springframework.org/schema/cache
                    http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
                    http://www.springframework.org/schema/jee
                    classpath:org/springframework/ejb/config/spring-jee-3.1.xsd"> 
     
      <context:component-scan base-package="myBasePackage" />

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/DATABASENAME"/>
    </bean>
   
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
                   <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="database" value="ORACLE"/>
            <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect"/>
        </bean>
    </property>
      </bean>

      <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
           <property name="entityManagerFactory" ref="entityManagerFactory" /> 
      </bean> 
      <!--mybeans -->
      <bean id="daoExample" class="my.dao.DaoExample"/>
      <bean id="portfolioService" class="my.utilities.ServiceTest"/>
      <tx:annotation-driven transaction-manager="transactionManager"/>
     
</beans>



Thursday, April 4, 2013

Netbeans Maven Proxy Settings

You can set up proxy for maven project in Netbeans 7.3 (on Windows)  by editing


C:\Program Files\NetBeans 7.3\java\maven\conf\settings.xml.

That simple... It took me 30 min to find it on net  - hope you found this page much quicker ;-)

Barbecue barcode label problem and solution

I am using barbecue 1.5.beta to generate barcode images on my Windows 2003 server.
When migrating to a new server though (Windows 2008 x64 ) I encountered the following issue: text label underneath the barcode wasn't showing any more...users where baffled by this ..and so was I .

After searching the web I came to a conclusion that this must be happening because some servers (don't ask me why) are considered to be headless (without monitor) and in that case...well there is a bug in Barcode class namely in its calculateSize() method.  Credits for this solution must go to Paul

So, to fix Barcode.class you must replace its calculateSize() method, as Paul suggested:

-------------------------------------

private Dimension calculateSize() { 
Dimension d = new Dimension(); 
   if(EnvironmentFactory.getEnvironment() instanceof HeadlessEnvironment)
     try { 
          if(font == null) { 
               d = draw(new SizingOutput(font, getForeground(), getBackground()), 0, 0, barWidth, barHeight);
         } 
         else { 
              java.awt.FontMetrics fontMetrics = getFontMetrics(font); 
              d = draw(new SizingOutput(font, fontMetrics, getForeground(), getBackground()), 0, 0, barWidth, barHeight); 
              }
         } 
      catch(OutputException e) { 
          e.printStackTrace(); 
      } 
   else 
    try { 
         java.awt.FontMetrics fontMetrics = null;
         if(font != null) fontMetrics = getFontMetrics(font);
         d = draw(new SizingOutput(font, fontMetrics, getForeground(), getBackground()), 0, 0, barWidth, barHeight);
    } catch(OutputException e) { }
 return d; 
}

-------------------------------------
Works like charm.  If you have enough patience you should download Barbecue source code, downland dependencies,  use maven,  make changes ...recompile (as I did). Or if you don't -  then just take  this  Barbecue (myFix) version.

Monday, April 1, 2013

Netbeans user defined Libraries Xml Definitions

Did you know where Netbeans stores user defined libraries?  I for sure didn't.
It turns out that Net Beans creates an Xml file for each user defined library and to carry them around with you...when say upgrading, all you have to do is to copy these xmls to appropriate folder. 

I was upgrading from NB 7.0 to 7.3 so I had to copy from

[userName]\.netbeans\7.0\config\org-netbeans-api-project-libraries\Libraries

to

[userName]\AppData\Roaming\NetBeans\7.3\config\org-netbeans-api-project-libraries\Libraries.

and it worked ;-)

Tuesday, February 19, 2013

Java Find Next / Previous / Nth Business / Working Day

Below is a Utility class for calculating business days, holidays, moths'  nth weekdays (e.g. second Monday) etc. Most credits must go to http://stackoverflow.com/users/66125/jnt30 though I did add some code for previous business day, nth business day calculation and Greek Orthodox Easter Algorithm. Haven't fully tested it yet so feel free to comment if you find any issues with this code:
(dependencies: http://commons.apache.org/lang/ , http://logging.apache.org/log4j/1.2/ )

---------------------------------------------------------------------------------------------
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;

public class Holidays {
    private static Logger log = Logger.getLogger(Holidays.class);
    private static transient Map> computedDates = new HashMap>();

    /**
     * This method will calculate the next business day
     * after the one input.  This means that if the next
     * day falls on a weekend or one of the following
     * holidays then it will try the next day.
     *
     *
     **/
    public static boolean isBusinessDay(Date dateToCheck)
    {
        //Setup the calendar to have the start date truncated
        Calendar baseCal = Calendar.getInstance();
        baseCal.setTime(DateUtils.truncate(dateToCheck, Calendar.DATE));

        List offlimitDates;

        //Grab the list of dates for the year.  These SHOULD NOT be modified.
        synchronized (computedDates)
        {
                int year = baseCal.get(Calendar.YEAR);

                //If the map doesn't already have the dates computed, create them.
                if (!computedDates.containsKey(year))
                        computedDates.put(year, getOfflimitDates(year));
                offlimitDates = computedDates.get(year);
        }

        //Determine if the date is on a weekend.
        int dayOfWeek = baseCal.get(Calendar.DAY_OF_WEEK);
        boolean onWeekend =  dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY;

        //If it's on a holiday, increment and test again
        //If it's on a weekend, increment necessary amount and test again
        //System.out.println(offlimitDates);

        if (offlimitDates.contains(baseCal.getTime()) || onWeekend)
                return false;
        else
                return true;
    }

    
    /**
     *
     * This method will calculate the previous business day
     * before the one input.  This leverages the isBusinessDay
     * heavily, so look at that documentation for further information.
     *
     * @param startDate the Date of which you need the previous business day.
     * @return The previous business day.  I.E. it doesn't fall on a weekend,
     * a holiday or the official observance of that holiday if it fell
     * on a weekend.
     *
     */
    public static Date getPreviousBusinessDay(Date startDate)
    {
        //Decrement the Date object by a Day and clear out hour/min/sec information
        Date previousDay = DateUtils.truncate(addDays(startDate, -1), Calendar.DATE);
        //If yesterday is a valid business day, return it
        if (isBusinessDay(previousDay))
                return previousDay;
        //Else we recursively call our function until we find one.
        else
                return getPreviousBusinessDay(previousDay);
    }

    /**
     *
     * This method will calculate the last business day of the month of the 
     * input date.  This leverages the  getPreviousBusinessDay
     * heavily, so look at that documentation for further information.
     *
     * @param startDate the current Date, from which we will derive a month.
     * @return last business day of the month of the date given 
     * @see #getPreviousBusinessDay(java.util.Date) 
     **/
    public static Date getMonthsLastBusinessDay(Date startDate)
    {
        Date result=null;
        Calendar cal = new GregorianCalendar();
        cal.setTime(startDate);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int day = cal.getActualMaximum(Calendar.DAY_OF_MONTH); //cal.get(Calendar.DAY_OF_MONTH);
        result = new GregorianCalendar(year,month,day).getTime();
        if (!isBusinessDay(result))
            result = getPreviousBusinessDay(result);
        return result;
    }
    
    /**
     *
     * This method will calculate the Nth business day of the month of the 
     * input date.  This leverages the isBusinessDay
     * heavily, so look at that documentation for further information.
     *
     * @param startDate the current Date, from which we will derive a month.
     * @param n Number of days
     * @return last business day of the month of the date given 
     * @see #isBusinessDay(java.util.Date) 
     **/
    public static Date getNthBusinessDayOfMonth(Date startDate, int n)
    {
        Date result=null;
        Calendar cal = new GregorianCalendar();
        cal.setTime(startDate);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int day = 1; //cal.get(Calendar.DAY_OF_MONTH);
        result = new GregorianCalendar(year,month,day).getTime();
        int i=0;
        do{
         if (isBusinessDay(result)){
             i++;
             if (i>=n) break;
         }
         result = addDays(result, 1);
        }while(i getOfflimitDates(int year)
    {
        List offlimitDates = new ArrayList();

        Calendar baseCalendar = GregorianCalendar.getInstance();
        baseCalendar.clear();

        //Add in the static dates for the year.
        //New years day
        baseCalendar.set(year, Calendar.JANUARY, 1);
        offlimitDates.add(baseCalendar.getTime());

        //Christmas
        baseCalendar.set(year, Calendar.DECEMBER, 25);
        offlimitDates.add(baseCalendar.getTime());
        baseCalendar.set(year, Calendar.DECEMBER, 26);
        offlimitDates.add(baseCalendar.getTime());
        
        //Now deal with floating holidays.
        //Martin Luther King Day
        //offlimitDates.add(calculateFloatingHoliday(3, Calendar.MONDAY, year, Calendar.JANUARY));

        //Thanksgiving Day and Thanksgiving Friday
        //Date thanksgiving = calculateFloatingHoliday(4, Calendar.THURSDAY, year, Calendar.NOVEMBER);
        //offlimitDates.add(thanksgiving);
        //offlimitDates.add(addDays(thanksgiving, 1));
       
        //Greece Specific
        Date pasxa = getOrthodoxEaster(year);
        offlimitDates.add(pasxa);
        offlimitDates.add(addDays(pasxa,-3));
        offlimitDates.add(addDays(pasxa,1));
        //25 March 
        baseCalendar.set(year, Calendar.MARCH, 25);
        offlimitDates.add(baseCalendar.getTime());
        //28 October
        baseCalendar.set(year, Calendar.OCTOBER, 28);
        offlimitDates.add(baseCalendar.getTime());
        //Fwta
        baseCalendar.set(year, Calendar.JANUARY, 6);
        offlimitDates.add(baseCalendar.getTime());
        //May Day
        baseCalendar.set(year, Calendar.MAY, 1);
        offlimitDates.add(baseCalendar.getTime());
        // 15 August
        baseCalendar.set(year, Calendar.AUGUST, 15);
        offlimitDates.add(baseCalendar.getTime());
        
        return offlimitDates;
    }


    /**
     * This method will take in the various parameters and return a Date objet
     * that represents that value.
     *
     * Ex. To get Martin Luther Kings BDay, which is the 3rd Monday of January,
     * the method call woudl be:
     *
     * calculateFloatingHoliday(3, Calendar.MONDAY, year, Calendar.JANUARY);
     *
     * Reference material can be found at:
     * http://michaelthompson.org/technikos/holidays.php#MemorialDay
     *
     * @param nth 0 for Last, 1 for 1st, 2 for 2nd, etc.
     * @param dayOfWeek Use Calendar.MODAY, Calendar.TUESDAY, etc.
     * @param year
     * @param month Use Calendar.JANUARY, etc.
     * @return
     */
    private static Date calculateFloatingHoliday(int nth, int dayOfWeek, int year, int month)
    {
        Calendar baseCal = Calendar.getInstance();
        baseCal.clear();

        //Determine what the very earliest day this could occur.
        //If the value was 0 for the nth parameter, incriment to the following
        //month so that it can be subtracted alter.
        baseCal.set(year, month + ((nth <= 0) ? 1 : 0), 1);
        Date baseDate = baseCal.getTime();

        //Figure out which day of the week that this "earliest" could occur on
        //and then determine what the offset is for our day that we actually need.
        int baseDayOfWeek = baseCal.get(Calendar.DAY_OF_WEEK);
        int fwd = dayOfWeek - baseDayOfWeek;

        //Based on the offset and the nth parameter, we are able to determine the offset of days and then
        //adjust our base date.
        return addDays(baseDate, (fwd + (nth - (fwd >= 0 ? 1 : 0)) * 7));
    }

    /**
     * If the given date falls on a weekend, the
     * method will adjust to the closest weekday.
     * I.E. If the date is on a Saturday, then the Friday
     * will be returned, if it's a Sunday, then Monday
     * is returned.
     **/
    private static Date offsetForWeekend(Calendar baseCal)
    {
        Date returnDate = baseCal.getTime();
        if (baseCal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY)
        {
                if (log.isDebugEnabled())
                        log.debug("Offsetting the Saturday by -1: " + returnDate);
                return addDays(returnDate, -1);
        }
        else if (baseCal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
        {
                if (log.isDebugEnabled())
                        log.debug("Offsetting the Sunday by +1: " + returnDate);
                return addDays(returnDate, 1);
        }
        else
                return returnDate;
    }

    /**
     * Private method simply adds
     * @param dateToAdd
     * @param numberOfDay
     * @return
     */
    private static Date addDays(Date dateToAdd, int numberOfDay)
    {
        if (dateToAdd == null)
                throw new IllegalArgumentException("Date can't be null!");
        Calendar tempCal = Calendar.getInstance();
        tempCal.setTime(dateToAdd);
        tempCal.add(Calendar.DATE, numberOfDay);
        return tempCal.getTime();
    }
    /**
     *  Compute the day of the year that Orthodox Easter falls on.
     *  Based on Gausean Algorithm.
     *   
     *  @param the_year Year 
     *  @return Orthodox Easter Sunday
     */
    public static final Date getOrthodoxEaster(int the_year){
    //Gaus Algorithm
    Date easter;
    int res = (19*(the_year%19)+16)%30+(2*(the_year%4)+4*(the_year%7)+6*(((19*(the_year%19))+16)%30))%7+3;
    if (res < 31)  
    easter = (new GregorianCalendar(the_year,Calendar.APRIL, res)).getTime(); // 4-1  //  pasxa = res+"/"+"04"+"/"+the_year;
    else 
    easter = (new GregorianCalendar(the_year,Calendar.MAY, res-30)).getTime(); // 5-1  // pasxa =  (res-30)+"/"+"05"+"/"+the_year;  
    return easter;
    } 
    
 /**
   * Compute the day of the year that Easter falls on. Step names E1 E2 etc.,
   * are direct references to Knuth, Vol 1, p 155. @exception
   * IllegalArgumentexception If the year is before 1582 (since the algorithm
   * only works on the Gregorian calendar).
   * 
   * @param year Year
   * @return Catholic Easter
   **/
  public static final Date findHolyDay(int year) {
    if (year <= 1582) {
      throw new IllegalArgumentException(
          "Algorithm invalid before April 1583");
    }
    int golden, century, x, z, d, epact, n;

    golden = (year % 19) + 1; // E1: metonic cycle 
    century = (year / 100) + 1; // E2: e.g. 1984 was in 20th C 
    x = (3 * century / 4) - 12; // E3: leap year correction 
    z = ((8 * century + 5) / 25) - 5; // E3: sync with moon's orbit 
    d = (5 * year / 4) - x - 10;
    epact = (11 * golden + 20 + z - x) % 30; // E5: epact 
    if ((epact == 25 && golden > 11) || epact == 24)
      epact++;
    n = 44 - epact;
    n += 30 * (n < 21 ? 1 : 0); /* E6: */
    n += 7 - ((d + n) % 7);
    if (n > 31) /* E7: */
      return (new GregorianCalendar(year, 4 - 1, n - 31)).getTime(); // April 
    else
      return (new GregorianCalendar(year, 3 - 1, n)).getTime(); // March 
  }
  
    public static void main(String [] args){
        SimpleDateFormat sdf  = new SimpleDateFormat("MM-dd-yyyy HH:mm");

        java.util.Date dd = sdf.parse("09-01-2011 13:00", new ParsePosition(0));
        dd = new java.util.Date(dd.getTime() - 24L*3600L*1000L);
        for(int j=0; j<7; j++){
            dd = Holidays.getNextBusinessDay(dd);
          //  System.out.println(j + ": " + dd);
        }

      System.out.println(dd);
      int thisYear = new GregorianCalendar().get(Calendar.YEAR);
      Date c = Holidays.findHolyDay(thisYear);
      System.out.println("catholic "+ c);
      System.out.println("orthodosx" + Holidays.getOrthodoxEaster(thisYear));
      System.out.println(Holidays.isBusinessDay(new GregorianCalendar(2013, 5 - 1, 5).getTime()));
      System.out.println(Holidays.isBusinessDay(new GregorianCalendar(2013, 10 - 1, 28).getTime()));
      System.out.println(Holidays.getMonthsLastBusinessDay(new GregorianCalendar(2013, Calendar.AUGUST, 1).getTime()));
      System.out.println(Holidays.getNthBusinessDayOfMonth(new Date(),7));
    }

}



---------------------------------------------------------------------------------------------

Thursday, December 20, 2012

Automatically download subtitles and shows

For those of You who love to watch TV shows downloaded from internet .. but hate the procedure of finding the correct torrent file and subtitles I will present a way to automate the whole process.

What we will need:
  1. Utorrent client:  http://www.utorrent.com/
  2. Python 2.7.3 http://www.python.org/download/releases/2.7.3/
  3. BeautifulSoup 3.2.1 (Python library)
      http://www.crummy.com/software/BeautifulSoup/
      http://www.crummy.com/software/BeautifulSoup/download/3.x/BeautifulSoup-3.2.1.tar.gz
  4. Periscope (Python module)
    http://code.google.com/p/periscope/

    python-periscope_0.2.4.orig.tar.gz
    (Or use my  python-periscope_0.2.4.orig.plirkee.repack)
 Target System: (in my case) Windows Vista
 Let's begin.

  •  Utorrent (briefly, cause you can find information on how to do this on many sites)
  1.  First you install Utorrent and open it.
  2.  Right click on Feeds and add  new Rss feed
    (it could be any rss feed of your favorite site mine is EzTv so I add  rss feed with feed url:  http://feeds.feedburner.com/eztv-rss-atom-feeds?format=xml )
  3. Go to Options => Rss downloader and Add new rule for your favorite show...
And thus You  are ready to  automatically download  your shows as soon as they are available! .... but, we will be back to utorrent settings to make it download subtitles as well, however first we need to set up python

  • Python
  1. install python to c:\python27
  2. download BeautifulSoup, unzip it into c:\python27\BeautifulSoup,
    run form command prompt: 
    cd c:\python27\BeautifulSoup\
    setup.py install
  3. download Periscope, unzip it into c:\python27\Periscope,
    run from command prompt:
    cd c:\python27\Periscope\
    setup.py install
  4. go to your user's folder (C:\Users\USERNAME) (this folder is defined ether by %HOME% or %USERPROFILE% or %HOMEDRIVE%%HOMEPATH% env variables) from command prompt and create directory with name ".config" e.g. 
    • cmd
    • cd C:\Users\USERNAME
    • mkdir .config
          (if you omit this step, you could get access denied error from periscope script)   
  • Vb Script
  1. create .vbs file that will handle subtitle downloading


  • c:\MyScripts\download.vbs
  • 'In v5 uTorrent kind (%K) support is added kind can be single  or multi
    Const RUN = "C:\Python27\python.exe C:\Python27\scripts\periscope"  
    Const LANGS = "-l el -l en"
    Const LOGFILE_POSTFIX = "_downloader.log"
    Const SUB_EXT = "srt"
    Const EXPECETED=3 ' utorrent pause code
    Const FORAPPENDING = 8
    Const LEAST_NUM_OF_ARG=3 ' (0) = Directory  (1) = File (2) = Kind + optional (3) = Status 
    Const KIND_MULTI = "multi"
    
    
    On Error Resume Next
    Dim directory,file,kind,extension,whatToRun 
    set objFSO = CreateObject("Scripting.FileSystemObject")
    
    Function log(logfile,str)
     set objFile = objFSO.OpenTextFile(logfile, FORAPPENDING, True)
     objFile.WriteLine("Time Stamp: " & Now)
     objFile.WriteLine(" " & str)
     objFile.Close
     set objFile=Nothing
    End Function
    
    if ( WScript.Arguments.Count LEAST_NUM_OF_ARG) then 
     if (WScript.Arguments.Count=LEAST_NUM_OF_ARG+1 and WScript.Arguments(LEAST_NUM_OF_ARG)<>CStr(EXPECETED)) then  
      'Wscript.Echo "Arg3 unexpected value" &  WScript.Arguments(2) &" " & EXPECETED
      log logfile,WScript.Arguments(1) & "Arg3 unexpected value " &  WScript.Arguments(2) &" was expecting " & EXPECETED
      WScript.quit()
     end if
     end if
     
     extension = Right(file,3)
     if kind=KIND_MULTI then
        whatToRun = RUN & " " & LANGS &" " & chr(34) &directory&           chr(34)
     else 
        whatToRun = RUN & " " & LANGS &" " & chr(34) &directory&"\" &file& chr(34) 
     if (extension<>"mp4" and extension<>"avi" and extension<>"mkv") then 
      'Wscript.Echo "unsupported extension:" &  extension
      log logfile,"unsupported extension:" &  extension
      WScript.quit()
     end if 
     end if
     
      log logfile,"Will try " & file 
      Set WshShell = WScript.CreateObject("WScript.Shell") 
      'WshShell.Run "cmd.exe /c start /min  " 
      WshShell.Run "cmd.exe /c  " &_ 
                   " echo %date% %time% " &_
          directory & " " & file & whatToRun & " >> " & logfile & " &" &_
          whatToRun &  " >> "&logfile&"  2>&1"&_
          " & exit",0,True  
       newFile = left(file,len(file)-3)&SUB_EXT
      'Wscript.Echo(newFile)
       If objFSO.FileExists(chr(34) & directory&"\"&newFile &chr(34)) Then
       'Wscript.Echo("Downloaded subtitles for " & file)
        End If 
      
      set objFSO=nothing
      Set WshShell=nothing
    




  • Set  Utorrent - Preferences - Advanced - Run Program :
    Run This program when torrent finishes
    c:\MyScripts\download.vbs "%D" "%F" %K
    Run When torrent  changes state
    c:\MyScripts\download.vbs "%D" "%F" %K %S

  •  Of course you could create your own .bat file as I did  at first. In that case I would recommend you to call it with following command: "cmd.exe /c start /min  C:\MyPythonSubsDowloader.bat "%D" "%F" %K %S ^& exit", from utorrent. The downside of using bat file is the flickering of dos window that appears every time torrent state changes.
     Also, as you can see in vbs, the  script tries to download Greek and  English subs [Const LANGS = "-l el -l en"],  you can add your own languages by changing that line.

     Any way, we have finished our task. Now any time video has finished downloading ..or whenever you hit pause on downloaded video in utorrent - subtitle search is performed.
    I use utorrent pause (state code = 3) to cause downloading of subtitles at time of my choosing ...and use it in cases when no subs are found, the first time  the torrent finished.
     
    P.S. Also, it seems that currently there are some problems with a number of plugins of periscope (v 0.2.4) .. but you can download my fixes for Addic7ed and TVsubtitles. If you do, then don't forget to un-comment  these plugins in periscope\plugins\__init__.py before executing  setup.py install 

    P.S2 I upgraded the download vb script to v5 (24/07/2013) now it downloads subs even if you are getting muti-item torrent (e.g. complete season). The old version of the script is still available @ my  support site.
    From there you can download my repack of periscope which includes all  the above fixes.

    Sunday, November 25, 2012

    PDFBox Printing Greek Problem

    Still working with PdfBox and got another obstacle to tackle...printing Pdf containing Geek text seems to be problematic. Most of the text prints out fine but there are some characters that do not print correctly.
    For example small Greek letter  π  prints out as "pi", also there is an issue with small μ that prints out differently ... thought, at least it looks like μ.

    Filled out bug report yesterday, hope this could be fixed.
    So far no solution on the horizon ...I will update this blog in case the solution is found.
    ....

    16.11.2013 
    And so it's time to update (I know, I know... millions were expecting this update!! ;-)...this issue seams to be solved by Andreas Lehmkühler https://issues.apache.org/jira/browse/PDFBOX-1452 ... however there is a catch .. the solution is in version 2.0 and currently G.A. version is 1.8.2. I suppose, one could download and build 2.0 version from the trunk  http://svn.apache.org/repos/asf/pdfbox/trunk/ (use: svn checkout http://svn.apache.org/repos/asf/pdfbox/trunk/), but I haven't tried it yet.
    If you do - let me know how it went for you.