Thursday, April 11, 2013

File download page using Spring


In web.xml, map directory listing URL to spring dispatcher:


 <servlet-mapping>
  <servlet-name>spring</servlet-name>
  <url-pattern>*.html</url-pattern>
 </servlet-mapping>

 <servlet-mapping>
  <servlet-name>spring</servlet-name>
  <url-pattern>/download/*</url-pattern>
 </servlet-mapping>

The first one is your existing dispatcher and the second one for download.

In spring security configuration set up appropriate configuration:
<intercept-url pattern="/download/**" access="permitAll" />

In Spring servlet config xml set this up to make path configurable:

 <bean id="appPropertiesBean" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="singleton" value="true" />
  <property name="properties">
   <props>
    <prop key="downloadPath">C:/</prop>
   </props>
  </property>
 </bean>

In your controller for the path property:

    @Value("#{appPropertiesBean.downloadPath}")
    private File downloadPath;

In controller add methods to generate directory listing:

   @RequestMapping(value = "/files/**", method = RequestMethod.GET)

    public ModelAndView archiveDirectoryListing(HttpServletRequest request, HttpServletResponse response) {
        try {
            //String restOfTheUrl=(String)request.getAttribute( HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE );
            //The above line seems to cause issues with filenames 
            // containing semicolon. Use the below line instead
            String restOfTheUrl=request.getPathInfo();
            restOfTheUrl=restOfTheUrl.substring("/files".length());
            File physicalFileRequested=new File(downloadPath,restOfTheUrl);
            System.out.println("Accessing .." + physicalFileRequested);
            if (!physicalFileRequested.getCanonicalPath().startsWith(archivePath.getCanonicalPath())) { //Requester is trying to go above the archive directory
         response.setStatus(HttpServletResponse.SC_FORBIDDEN);
         return;
            }
            if (!physicalFileRequested.exists()) {
         response.setStatus(HttpServletResponse.SC_FORBIDDEN);
         return;       
            }         
            System.out.println("Access allowed " + physicalFileRequested);
            System.out.println("Access allowed " + physicalFileRequested.isFile());
            System.out.println("Access allowed " + physicalFileRequested.isDirectory());
            System.out.println("Rest of url : " + restOfTheUrl);
            if (physicalFileRequested.isFile()) {
         System.out.println("Accessing file:" + physicalFileRequested);
         streamFile(physicalFileRequested,response);
            } else if (physicalFileRequested.isDirectory()){
         if (! restOfTheUrl.endsWith("/")) {
             response.sendRedirect(request.getContextPath() + "/download/files" + restOfTheUrl + "/");
         }
         System.out.println("Accessing dir:" + physicalFileRequested);
         generateDirectoryListing(physicalFileRequested,response);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Error accessing requested file/directory.");
        }
    }

    private void streamFile(File physicalFileRequested, HttpServletResponse response) {
 try {
     response.setContentType("application/pdf");
     // get your file as InputStream
     InputStream is = new FileInputStream(physicalFileRequested);
     // copy it to response's OutputStream
     IOUtils.copy(is, response.getOutputStream());
     response.flushBuffer();
 } catch (IOException ex) {
     throw new RuntimeException("Error accessing requested file/directory.");
 }
    }

    private void generateDirectoryListing(File physicalFileRequested, HttpServletResponse response) {
 try {
     StringBuilder sb=new StringBuilder();
     sb.append("<html>");
     sb.append("<body>");
     sb.append("<a href='..'>..</a><br>");

     File [] childFiles=physicalFileRequested.listFiles();
     for (File childFile:childFiles) {
  String relativePath = childFile.getName();
   sb.append("<a href='"+ URLEncoder.encode(relativePath,"UTF-8")  + "'>" +relativePath+"</a><br>");
     } 
     sb.append("</body>");
     sb.append("</html>");
    response.getWriter().print(sb.toString());
 } catch (Exception e) {
     throw new RuntimeException("Error accessing requested file/directory.");
 }
    }



Download URL will be like:

http://localhost:9090/context/download/files/

Alternatively, the directory listing HTML could be generated using a view, by using the following alternate implementation of the method (Note: wherever null is returned for ModelAndView, Spring assumes that response has already been handled and no view redirection needs to happen):


   @RequestMapping(value = "/files/**", method = RequestMethod.GET)
    public ModelAndView archiveDirectoryListing(HttpServletRequest request, HttpServletResponse response) {
        try {
            String restOfTheUrl=(String)request.getAttribute( HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE );
            restOfTheUrl=restOfTheUrl.substring("/files".length());
            File physicalFileRequested=new File(archivePath,restOfTheUrl);
            System.out.println("Accessing .." + physicalFileRequested);
            if (!physicalFileRequested.getCanonicalPath().startsWith(archivePath.getCanonicalPath())) { //Requester is trying to go above the archive directory
         response.setStatus(HttpServletResponse.SC_FORBIDDEN);
         return null;
            }
            if (!physicalFileRequested.exists()) {
         response.setStatus(HttpServletResponse.SC_NOT_FOUND);
         return null;         
            }           
            if (physicalFileRequested.isFile()) {
         streamFile(physicalFileRequested,response);
         return null;
            } else if (physicalFileRequested.isDirectory()){
         if (! restOfTheUrl.endsWith("/")) {
             response.sendRedirect(request.getContextPath() + "/archive/files" + restOfTheUrl + "/");
         }
         System.out.println("Accessing dir:" + physicalFileRequested);
         ModelAndView modelAndView=new ModelAndView("direcoryListing");
         modelAndView.addObject("fileList", physicalFileRequested.listFiles());
         return modelAndView;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Error accessing requested file/directory.");
        }
 response.setStatus(HttpServletResponse.SC_NOT_FOUND);
 return null;         
    }


And a freemarker view, direcoryListing.ftl:

<html>
<body>
<h1>Welcome to the download page</h1>
<a href='..'>..</a><br>
<#list fileList as file>
<a href='${file.name}'> ${file.name}</a><br>
</#list>
</body>
</html>

Configure freemarker in application context:

<!-- freemarker config -->
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/pages/" />
</bean>           
<!-- View resolvers can also be configured with ResourceBundles or XML files. 
If you need different view resolving based on Locale, you have to use the 
resource bundle resolver. -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true" />
<property name="prefix" value="" />
<property name="suffix" value=".ftl" />
</bean>

Monday, April 8, 2013

Tiles Boardgame

During my college days I was introduced to a board game. We used to play that in the breaks, by drawing the board on paper and using two different pens to differentiate the players' pieces.

The board game is a two player game and like tic-tac-toe, but of a larger size. The board is typically a 7x7 square. The goal is for a player to occupy 4 contiguous boxes in the board, either horizontally, vertically or diagonally.

One day, in my friend Jerine's home, we were test driving VB for the first time and we decided to build this game using VB. In a few hours we had the VB implementation of the game with a very basic computer opponent. It was fun and we did not think about it much after then.

In a sudden rush of nostalgia I thought of implementing that in JS. It is now available in Google code http://tiles-game.googlecode.com Github https://github.com/kkleokrish/tiles-game. The core of the game is in Tiles.js and the HTML files are rudimentary UI on top that, just to visualize the functionality.

Saturday, January 21, 2012

Weird coincidences

There are a few instances of weird coincidences that I vividly remember which I wanted to record in the blog for past few months. Following are two such instances:

Catalytic Converter

It was during my school days when we started studying organic chemistry and about catalysts. Few of the reactions involved, conversion of hydrocarbons into carbon monoxide carbon dioxide and water etc.

At the same time we were introduced pollutants, carbon monoxide, NOx etc. I used to correlate and think that if we could convert CO to CO2 and NOx to N2 and water, we could reduce pollution. If they could be done in the exhaust of the cars we could eliminate air pollution in vehicles. Applying what we read, this may need catalysts.

I discussed this at length with my cousin during a week end. The Hindu used to carry a supplement on Thurdays for Science and Technology. The Thursday after that weekend, there was an article in that about catalytic converters. It discussed about beehive shaped compartments which would have catalysts to convert CO to CO2 etc. to reduce pollution.

I did not realize it then, but, it is such a weird coincidence looking back now.

Vertical Farming

This is more recent and happened in the last year or so. I kept thinking about the reducing agricultural lands in India and thought that if we could do farming in multi-stories, then potentially we could produce more in limited space. Each locality could have one such building. This would supply a part of the needs for the locality. It should not be a glass house so that it could be maintained easily, but instead lighting could be through mirrors sending the sunlight into the building or optical fibers running from the terrace. Neither of these might be economically feasible, but just a thought. I thought this could be called vertical farming.

The day after that there was an article in The Times of India, that discussed about an expert who was working on agriculture in increasingly urban set up and he mentioned about multi-storey agriculture and called it Vertical Farming. This is second weird coincidence and made me think about recording these in a blog.

Saturday, May 7, 2011

I have a dream ...

கவலைகள் இல்லா உறக்கம் - அதில்
இன்பங்கள் நிறைந்த கனவு
பசுமைகள் நிறைந்த நிலங்கள் - அதில்
சில்லென ஓடும் ஓடை
மரங்கள் நிறைந்த வனம் - அதில்
நிற்காதிசைக்கும் குயில்கள்
வேட்டை ஆடா புலிகள் - அதனால்
பயமின்றி உலவும் மான்கள்
மாசற்ற தென்றல் காற்று - அதில்
இனிமை நிறைந்த கீதம்
கைக்கெட்டும் உயரம் பழங்கள் - அதில்
தின்னத் தெவிட்டா சுவைகள்
பாய்ந்து சிதறும் அருவிகள் - அவை
பிறந்து வந்த முகடுகள்
அமைதியாக ஓடும் நதி - அதில்
பாய்ந்து நீந்தும் மீன்கள்
பனி படர்ந்த புல்வெளி - அதில்
மேய்கின்ற ஆடு மாடு
தேங்கி நிற்கும் தண்ணீர் - அதில்
குட்டியோடு குளிக்கும் யானை
தேவை யுத்தங்கள் அற்ற பூமி
மனிதர்கள் அற்ற தீவு - அதில்
தனிமையில் நான்

Conversation with God

கடவுள்

என் மீது என்னடா கோபம் உனக்கு?
சொல்லாமல் வாய் அடைத்து போனாய் எதற்கு?
கோபமா? தாபமா? வேகமா? சந்தேகமா?
நீ செய்த தவறுக்கு தண்டனை எனக்கு

மாற்றானோடு நீ பேசிச் சிரித்து குலாவுகையில்
என் மனம் பதைக்குதே என்னென்று நான் சொல்வேன்?
நாள் தோறும் குற்ற உணர்ச்சியிலே வெந்து நான் மடிகின்றேன்
இத்தண்டனயை எனக்களித்து
என்ன நீ கண்டாயோ சொல்?
-இது மனிதன்

சினம் கொண்டு சீறுவதும் மனிதப் பண்பே!
வாய் ஓயாமல் பேசுவதும் மனிதப் பண்பே!
கோபமும் தாபமும் மனிதப் பண்பே!
சந்தேகப் பேய் அதுவும் மனிதப் பண்பே!

உன்னை படைத்ததை தவறென்றாய் மனிதா!
படைக்கப் பட்டதின் சுகமறிவாயா?
வாழ்க்கையை தண்டனை என்றே சொன்ன நீ
அழகான ரோஜாவின் முள்ளறிவாயா?
மாற்றானோடு குலாவுகிறேன் என்ற நீ
இக்கரைக்கு அக்கரை பச்சை என்றறிவாயா?
குற்ற உணர்ச்சியிலே மடிகிறேன் என்ற நீ - அது
குற்றம் புரிந்தோரின் உடைமை என்றறிவாயா?
வாழ்கை ஒரு ரோஜா - அதை
இரசிக்கக் கற்றுகொள்.
புலம்பி என்னிடம் வந்து அழுது பயனில்லை
வாழ்கையிலே என்றும் நீ கடினமாய் உழைத்திட்டால் உன்
கடின உழைப்பினிலே பெரும் பகுதி நான் சுமப்பேன்
வாழ்கை ஒரு பஞ்சு மெத்தை
அதை சுகிக்க கற்றுக்கொள்.
அதில் துன்பங்கள் சிறு கற்கள்
அதை அகற்றக் கற்றுக்கொள்.


வாழ்க்கை ஒரு தென்றல்
அதை சுவாசிக்கக் கற்றுக்கொள்!
அதில் துன்பங்கள் சிறு தூசு
அதை சகிக்கக் கற்றுக்கொள்

வாழ்க்கையை வாழ்வதொரு பாடம் - அதை
வாழும் காலம் மட்டும் வழுவாமல் கற்றுக்கொள்

வாழ்க்கை ஒரு பாற்கடல் -அதன்
விடத்தை நீ சகித்தால்
அமுதமும் உனதுடைமை
இவ்வாறு வாழ்ந்து விட்டு
என்ன துன்பம் எனக்கூறு
துடைப்பதற்கு நான் உண்டு - துடைக்கப்
படுவதற்கு ஏதுண்டு?
- என்றார் கடவுள்

AS LONG AS YOU LIVE KEEP LEARNING HOW TO LIVE

My Early Attempts In Poem Writing

Like many of my friends and acquaintances, about a decade ago I used to write poems (or at least in my view) both in English and Tamil. I used to enjoy writing them and usually they reflect a theme that suddenly comes to mind causing an urge to write a poem on that theme.

I would be posting them in my blog starting from this one:

மின் வெட்டு
இயந்திர மயமான வாழ்க்கை
இயந்திரங்களான மனிதர்கள்
அன்புக்கு நேரமற்ற - ஆறு
அறிவுக்கு வேலையற்ற
அவலமான ஓட்டம் - இதில்
அறியாமல் வீழ்ந்துவிட்ட நாம்
வெளிவர என்ன வழி
யோசிக்க நேரமில்லை.

அன்று இரவு
அலுத்து சலித்து வீட்டை
அடைந்த அரை மணியில்
அழையா விருந்தாளியாய் வந்து
அடைந்தது மின் வெட்டு.

அலுத்த மனம் அலறியது - உள்ளே
அறைந்தது அரசாங்கத்தை - சபித்தது
மின் வாரியத்தை - நகர்ந்தது நேரம்
அமைதி அடைந்தது மனம்
பார்வை மாறியது:

எரியும் மெழுகு வர்த்தி
அதை சுற்றி வரும் விட்டில்
சுற்றி அமர்ந்திருக்கும் குடும்பத்தார்
சிறு நிறுத்தம் .... இயந்திர சுழற்சியில்
சிறு ஓய்வு ... இயந்திர மனிதனுக்கு
சிந்தனையில் தூங்கும் சிறு மனிதன் விழித்தான்
தொலைக்காட்சித் தொல்லை இல்லா
மடை திறந்த பேச்சு - தினமும்
அவசரமாய் உணவை அரைத்த மனிதனுக்கு
அவசரமற்ற உணவு
அசை போட பழங்கதை
இயற்கையின் சிறு தீண்டலையும்
இரக்கமின்றிப் பறித்து விட்ட
இயந்திரங்களை விட்டு மொட்டை
மாடியில் நித்திரை
எண்ணற்ற வின் மீன்
நடு நாயகமாய் நிலவு
சில்லென்ற தென்றல்
ஓடும் மேகங்கள்
ஓலைகளின் ஓசை
தூரத்து இடி முழக்கம்
இரசித்த படி உறக்கம்.

இது போல மேலும் தேவை
இன்னும் சில மின் வெட்டு - மனித
இயந்திரத்தை மனிதனாக்க.

Thursday, May 27, 2010

OJT vs. Traditional Training

1.1 OJT

Definition for this purpose:

Make a just-out-of-college or almost-so new employee to work on a problem in an ongoing project and let him come through it.

Action:

The employee should be handed a problem that has enough complexity. The employee has to setup his or her environment based on the choices made for the project. The employee could solve the problem in parallel with the team. This will prevent him from being a bottleneck, but at the same time allows enough room and an actual problem to think.

Additionally he can also be made to troubleshoot some issues. These issues could be current issues or issues that have been solved but have educational value.

The employee can be presented with a list of training courses, which he can attend to accomplish the task and should be encouraged to ask for one if he is stuck.

Result:

Employee learns to solve some of the problems that may crop up, which will help in production projects. The training becomes a pull model rather than a push model. This results in better take away from training. Since the training correlates with the knowledge required to solve the problem at hand, the information gets registered better.

But, it may also turn out that the employees don’t ask for training as most of the problem might have been solved by one-off discussions.

1.2 Traditional Training

The usual training models involve pushing the information to the employee. The information contains mainly of overview of technologies, which could be easily obtained from the Net and information on standards and conventions. Most of these are not registered in the minds of the employees, as they could not match this with a real need.

1.3 Hybrid Model

A better approach will be a hybrid of the above two. Let the employee go through OJT for a month or so until enough curiosity is awakened and then put him through the training. The training should involve general, but critical information on fundamentals (e.g. fundamentals of webapps – Web server, app server, ports, request, response etc. along with show and tell with a request analyzer), specific technologies (with emphasis on practical application), unit testing. Ideally, an employee could be trained in multiple technologies and then he may align into one or many of them.

1.4 Things that have not worked

Some approaches have not worked very well in an OJT:

  • Working on an internal project

Typically, this internal project will consist only of trainees/new employees. The whole team has an air that it is an unimportant one. Most of the times the project is not utilized.

  • Involving in a live project, but without any real problem to solve i.e. left to handle routine activities
  • Giving a problem from a real project but not attaching any importance to the results or worse not expecting any result at all

Better approach will be:

  • If it is a critical internal project, create a real team for it with proper team lead and some senior developers. If not, scrap the project. If it is not important enough it is not worth developing.
  • Utilizing an employee effectively only when forced does not add any value to the team. Prepare the employee for tomorrow’s requirement. Automate routine activities and share/cycle non-automated ones amongst the team.
  • Push for the results. Use parts of the results where it could be. Expect something that could be used. Give the employee a sandbox branch in the source control for the project and let him commit his changes there.