Linux: Using inode number to delete files with special characters


Today I found there is one special file named -v in the folder.
-rw-r--r-- 1 root root 790 Apr 23 18:36 -v

In this case, we can find the file's inode number and use the inode number to delete it.

First let's find the file's inode number using ls -li. 
The -i prints the inode number of each file.
ls -li
5242899 -rw-r--r-- 1 root root 790 Apr 23 18:36 -v

Then use one of below commands to delete it:
find . -inum 5242899 -delete
find . -inum 5242899 -exec rm -i {} \;

Also if we are creating multiple hard links to one file, and we want to remove that file completely- even there are still multiple hard links. We can use the same trickL:
find . -inum [inum] -delete

Checking if the value is a palindrome in binary notation


1. Determine whether bit-wise representation of the integer is a palindrome. Consider all bits including leftmost zeros.
The idea is simple: use two pointers, left and right, first left pointer points to the left most bit, right pointer points to right most bit, check whether these 2 bit values are same, loop all 32 bit.

public static boolean isPalindrome(int n) {
 int count = 32;
 int right = 1;
 int left = 1 << (32 - 1);
 while (count > 0) {
   int leftBitValue = n & left, rightBitValue = n
    & right;
  if (!((leftBitValue == 0 && rightBitValue == 0) || (leftBitValue != 0 && rightBitValue != 0))) {
   return false;
  }
  left = left >> 1;
  right = right << 1;
  count -= 2;
 }
 return true;
}
Variant: Determine whether bit-wise representation of the integer is a palindrome. Ignore all leftmost zeros.
This means 5 = 101b is also a palindrome.
The idea comes from this link, I just converted it to java code:
public static boolean isPalindrome(int x) {
 int original = x, reverse = 0;
 while (x != 0) {
  reverse <<= 1;
  reverse += x & 1;
  x >>>= 1;
 }
 return reverse == original;
}
References
Fun with Bitwise Operations, Part 1

Using Guava to Convert between Primitives Array and Wrapper List


Usually we nee convert between primitives array to wrapper list, for example: convert int[] to List.
Solution 1: Convert them manully
We can write code to convert them manually like below:
 public void intArrayIntListManully() {
    int[] aInts = {1, 2, 3};
    // int array to List
    List aList = new ArrayList(aInts.length);
    for (int i : aInts) {
      aList.add(i);
    }
    System.out.println(aList);
    // this throws UnsupportedOperationException
    // aList.add(4);
    // aList.remove(0);

    // List to int array
    aInts = new int[aList.size()];
    for (int i = 0; i < aList.size(); i++) {
      aInts[i] = aList.get(i);
    }
    System.out.println(aInts.length);
  }
But it's kind of annoy to have to write this boilerplate code  again and again.
Solution 2: Using Guava primitives
We can use utils in Guava com.google.common.primitives to easily convert between them: the code is cleaner, also its performance is better.

public void intArrayIntListViaGuava() {
  int[] aInts = {1, 2, 3};
  List<Integer> aList = Ints.asList(aInts);
  System.out.println(aList);
  
  aInts = Ints.toArray(aList);
  System.out.println(aInts.length);
}
If we check Guava's implementation, Ints.asList doesn't create one ArrayList then add all ints to that list, instead, it creates IntArrayAsList which holds a reference to the original int array, its get method creates and returns the wrapper object.
We can't add new element or remove element to the IntArrayAsList.
  public static List<Integer> asList(int[] backingArray)
  {
    if (backingArray.length == 0) {
      return Collections.emptyList();
    }
    return new IntArrayAsList(backingArray);
  }
  
  public static int[] toArray(Collection<? extends Number> collection)
  {
    if (collection instanceof IntArrayAsList) {
      return ((IntArrayAsList)collection).toIntArray();
    }

    Object[] boxedArray = collection.toArray();
    int len = boxedArray.length;
    int[] array = new int[len];
    for (int i = 0; i < len; ++i)
    {
      array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).intValue();
    }
    return array;
  }
 private static class IntArrayAsList extends AbstractList<Integer>    implements RandomAccess, Serializable
  {
    final int[] array;
    final int start;
    final int end;
    IntArrayAsList(int[] array)
    {
      this(array, 0, array.length);
    }

    IntArrayAsList(int[] array, int start, int end) {
      this.array = array;
      this.start = start;
      this.end = end;
    }
    public Integer get(int index) {
      Preconditions.checkElementIndex(index, size());
      return Integer.valueOf(this.array[(this.start + index)]);
    } 
  }
Solution 3: Using Apache Commons Lang
If your project doesn't use Guava, you may use Apache Commons Lang:
public void intArrayIntListViaCommonsLang() {
  int[] aInts = {1, 2, 3};
  List<Integer> aList = Arrays.asList(ArrayUtils.toObject(aInts));
  System.out.println(aList);
  
  aInts = ArrayUtils.toPrimitive(aList.toArray(new Integer[aList.size()]));
  System.out.println(aInts.length);
}
Reference
Guava Primitives Explained

Ant: Compiling Using Specific JDK


The Problem
In some cases, when use ant to compile code, we may have to use a specific JDK version which may be different than the default jdk in the system: for example, the project may use some jdk internal code which is not good, but sometimes we have to deal with the legacy project. 
Solution 1: Using JAVACMD Environment Variable
We can define a system environment variable: JAVACMD which points to full path of the Java executable. Ant will use the JVM defined by JAVACMD instead of JAVA_HOME/bin/java
set "JAVACMD=C:\Program Files\Java\jdk1.6.0_45\bin\java.exe"

export "JAVACMD=/Library/Java/JavaVirtualMachines/jdk1.7.0_75.jdk/Contents/Home/jre/bin/java"

But this will make all ant project uses same JVM defined by JAVACMD.
Solution 2: Using javac executable and fork
We can define specify system environment to specific JDK, for example JAVA6_HOME to point to JDK6.
Then in the ant build.xml, define a property env.java.home which point to JAVA6_HOME, then in javac task, set fork=yes and sepecify executable to ${env.java.home}/bin/javac

  <property environment="env"/>
 <property name="env.java.home" value="${env.JAVA6_HOME}"/>
 <javac destdir="${dest-path}/main" fork="yes" executable="${env.java.home}/bin/javac" source="1.6" target="1.6" debug="on" encoding="utf8" classpathref="common.classpath">
  <src path="./src/main" />
 </javac>
javac executable
Complete path to the javac executable to use in case of fork="yes". Defaults to the compiler of the Java version that is currently running Ant. Ignored if fork="no".

Resources
Running Apache Ant
Ant javac

How Math in JDK8 Detect Overflow


JDk8 add methods such as add/subtract/multiply/increment/decrement/Exact etc to throw ArithmeticException if it the result overflows.

The code:

public static long addExact(long x, long y) {
  long r = x + y;
  // HD 2-12 Overflow iff both arguments have the opposite sign of the result
  if (((x ^ r) & (y ^ r)) < 0) {
    throw new ArithmeticException("long overflow");
  }
  return r;
}

public static long subtractExact(long x, long y) {
  long r = x - y;
  // HD 2-12 Overflow iff the arguments have different signs and
  // the sign of the result is different than the sign of x
  if (((x ^ y) & (x ^ r)) < 0) {
    throw new ArithmeticException("long overflow");
  }
  return r;
}

public static int multiplyExact(int x, int y) {
  long r = (long)x * (long)y;
  if ((int)r != r) {
    throw new ArithmeticException("integer overflow");
  }
  return (int)r;
}
public static long multiplyExact(long x, long y) {
  long r = x * y;
  long ax = Math.abs(x);
  long ay = Math.abs(y);
  if (((ax | ay) >>> 31 != 0)) {
    // Some bits greater than 2^31 that might cause overflow
    // Check the result using the divide operator
    // and check for the special case of Long.MIN_VALUE * -1
    if (((y != 0) && (r / y != x)) ||
      (x == Long.MIN_VALUE && y == -1)) {
      throw new ArithmeticException("long overflow");
    }
  }
  return r;
}
public static long incrementExact(long a) {
  if (a == Long.MAX_VALUE) {
    throw new ArithmeticException("long overflow");
  }

  return a + 1L;
}
public static long negateExact(long a) {
  if (a == Long.MIN_VALUE) {
    throw new ArithmeticException("long overflow");
  }

  return -a;
}  
public static int floorDiv(int x, int y) {
  int r = x / y;
  // if the signs are different and modulo not zero, round down
  if ((x ^ y) < 0 && (r * y != x)) {
    r--;
  }
  return r;
}
Resources
Hacker's Delight
Hacker's Delight: The Basics
The Aggregate Magic Algorithms, 26 bit twiddling algorithms from Hank Dietz and others
Bit Twiddling Hacks, by Sean Anderson

Practice: Using JSZip to Download Current Week's Images in Blogger


The Task
There is a blogger: its main content is pictures and photos, client wants to allow users to download today, this week and this month's pictures.

The Solution
The basic idea is to send a request to Blogger feed url, parse its json response to get all image links, then use JSZip and JQuery Deferred pattern to download all remote images.
Using GAE to Serve JavaScript Files
After download JSZip and JSZip-Utils, we need put them somewhere, so the blogger can load them. So we create one GAE application, and put them in the webapp/js/jszip folders.

We only want to load these scripts if the pageType is item: mean current page is a post page. So we add the following code under <b:includable id='post' var='post'>:

<b:includable id='post' var='post'>
<b:if cond='data:blog.pageType == "item"'>
<script src='//youapp.appspot.com/js/jszip/jszip.min.js'/>
<script src='//youapp.appspot.com/js/jszip/jszip-utils.min.js'/>
<script src='//youapp.appspot.com/js/jszip/FileSaver.js'/>
</b:if>

Add Download Links to Item Page
<div class='blog-pager' id='blog-pager'>
 <b:if cond='data:blog.pageType == "item"'>
  <div class='blog-pager' id='blog-pager'>
     <div id='blog-pager-newer-link'>
    <a class='blog-pager-newer-link' href='' id='downloadToday'>Download Today's Images</a>
   </div>

   <div id='blog-pager-older-link'>
    <a class='blog-pager-newer-link' href='' id='downloadMonth'>Download This Month's Images</a>
   </div>

  <div id='blog-pager-home-link'>
    <a class='blog-pager-newer-link' href='' id='downloadWeek'>Download This Week's Images</a>
  </div>

  </div>
 </b:if>
...
</div>
The Complete JavaScript Code
Using Blogger Feeds URL to Get Post in Range
Using JSZip and JQuery Deferred Pattern to Download Multiple Remote Images
<b:includable id='post' var='post'>
<b:if cond='data:blog.pageType == "item"'>
<script src='//lifelongprogrammertools.appspot.com/js/jszip/jszip.min.js'/>
<script src='//lifelongprogrammertools.appspot.com/js/jszip/jszip-utils.min.js'/>
<script src='//lifelongprogrammertools.appspot.com/js/jszip/FileSaver.js'/>
<script>
  var dateHeader= '<data:post.dateHeader/>';
  var parts = dateHeader.split('-');
  var postDate = new Date(parts[0], parts[1]-1, parts[2]);
  console.log("postDate:" + postDate);  
//<![CDATA[

$(function($) {
  if(JSZip.support.blob) {
   $("#downloadToday").click(function (e) {
   getTodayAllImages(dateHeader);
         e.preventDefault();
         return false;
   });
   $("#downloadWeek").click(function (e) {
   getWeekAllImages(postDate);
         e.preventDefault();
         return false;
   });
   $("#downloadMonth").click(function (e) {
   getMonthAllImages(postDate);
         e.preventDefault();
         return false;
   });

  }
});

function addToZip(zip, link, postUrl, i) {
var deferred = $.Deferred();

 JSZipUtils.getBinaryContent(link, function (err, data) {
    if(err) {
      alert("Problem happened when download image from " + postUrl + ", img link: " + link);
      console.error("Problem happened when download image from " + postUrl + ", img link: " + link);
      deferred.resolve(zip); // ignore this error: just logging
      // deferred.reject(zip);
    } else {
      zip.file("picture"+i+".jpg", data, {binary:true});
      deferred.resolve(zip);
    }
 });
return deferred;
}

function parseImagesRsp(root){
    var feed = root.feed;
  var parser = new DOMParser();  
  var zip = new JSZip();
  var deferreds = [];
  for(var i=0; i<feed.entry.length; i++)
  {
   var e=feed.entry[i];
   var doc = parser.parseFromString(e.content.$t, "text/html");
   var img = doc.querySelector("img");
   var pageUrl = e.link[2].href;
   if(!img)
   {       
     console.error("No img tag in " + pageUrl);  
   }
   else{
     var imgLink = img.src;
     console.log("img link: " + imgLink);
     deferreds.push( addToZip(zip, imgLink, pageUrl, i) );
   }
  }

$.when.apply(window, deferreds).done(generateZip);
}
function generateZip(zip)
{
 var content = zip.generate({type:"blob"});
 // see FileSaver.js
 saveAs(content, "downloadImages.zip");
}
function doDownload(startDate, endDate){
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = '/feeds/posts/default?published-min=' + startDate + '&published-max='+endDate+'&alt=json-in-script&max-results=1000&callback=parseImagesRsp';
    document.getElementsByTagName('head')[0].appendChild(script);
}
function getTodayAllImages(dateStr){
 var startDate = dateStr + "T00:00:01", endDate = dateStr + "T23:59:59";
    console.log("Download images from " + startDate + " to " + endDate);
    doDownload(startDate, endDate);
    return false;
}
function getMonthAllImages(dateObj){
 var startDate = yymmdd(getFirstDayOfCurrentMonth(dateObj)) + "T00:00:01", endDate = yymmdd(getLastDayOfCurrentMonth(dateObj))  + "T23:59:59";
    doDownload(startDate, endDate);
    return false;
}
function getWeekAllImages(dateObj){
 var startDate = yymmdd(getMondayOfCurrentWeek(dateObj)) + "T00:00:01", endDate = yymmdd(getSundayOfCurrentWeek(dateObj))  + "T23:59:59";
    doDownload(startDate, endDate);
    return false;
}
function yymmdd(dataObj){
  var month = (dataObj.getMonth()+1);
  var monthStr = month<10? ('0' + month): month;
  var dateStr = dataObj.getDate()< 10? ('0' + dataObj.getDate()): dataObj.getDate();
  return dataObj.getFullYear() + "-" + monthStr + "-" + dateStr;
}
function getMondayOfCurrentWeek(d)
{
    var day = d.getDay();
    return new Date(d.getFullYear(), d.getMonth(), d.getDate()-day + (day == 0 ? -6:1));
}
function getSundayOfCurrentWeek(d)
{
    var day = d.getDay();
    return new Date(d.getFullYear(), d.getMonth(), d.getDate()-day + (day == 0 ? 0:7));
}
function getFirstDayOfCurrentMonth(d){
  return new Date(d.getFullYear(), d.getMonth(), 1);
}
function getLastDayOfCurrentMonth(d){
  return new Date(d.getFullYear(), d.getMonth()+1, 0);
}
//]]>
</script>
</b:if>

Blogger: Get Url of First Post


The Solution
Edit the blogger's template to include the following javascript code:

<script>
function getFirstPostLink(){
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = '/feeds/posts/default?alt=json-in-script&max-results=1&callback=parseRsp';
    document.getElementsByTagName('head')[0].appendChild(script);
}
function parseRsp(root){
    var feed = root.feed;
    var e0 = feed.entry[0];
    var firstPage = e0.link[2].href;
    // use the firstPage lin: window.location.href=firstPage;
}
getFirstPostLink();
</script>
Resources
Advanced Blogger Feeds Settings
Blogger Feed URLs

Practice: Using JSZip to Download Multiple Remote Images


Using JSZipUtils.getBinaryContent
JSZipUtils provides getBinaryContent to fetch a file from remote server like below:
// loading a file and add it in a zip file
JSZipUtils.getBinaryContent("path/to/picture.png", function (err, data) {
   if(err) {
      throw err; // or handle the error
   }
   var zip = new JSZip();
   zip.file("picture.png", data, {binary:true});
});
Using JQuery Deferred Pattern to Wait all Ajax Request Finished
We will loop all image urls, and call getBinaryContent to add the remote image into the dest zip file. But getBinaryContent is an async call, it will return immediately. We have to wait until al ajax request fished: either succeeded or failed.

We can use JQuery Deferred pattern

When loop al image urls, we will call addToZip: it calls JSZipUtils.getBinaryContent and return a Deferred object, which will be set as resolved when the ajax request finished. 
We put all Deferred objects into an array, then use jQuery.when().done(generateZip) to execute the callback generateZip when all ajax requests finished.
The generateZip will generate the zip and call saveAs in FileSaver.js.
The Complete Code
<script src='//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'/>
<script src='/js/jszip/jszip.min.js'/>
<script src='/js/jszip/jszip-utils.min.js'/>
<script src='/js/jszip/FileSaver.js'/>
<script>
function downloadAllImages(imgLinks){
 var zip = new JSZip();
 var deferreds = [];
 for(var i=0; i<imgLinks.length; i++)
 {
  deferreds.push( addToZip(zip, imgLinks[i], i) );
 }
 $.when.apply(window, deferreds).done(generateZip);
}
function generateZip(zip)
{
 var content = zip.generate({type:"blob"});
 // see FileSaver.js
 saveAs(content, "downloadImages.zip");
}
function addToZip(zip, imgLink, i) {
  var deferred = $.Deferred();
  JSZipUtils.getBinaryContent(imgLink, function (err, data) {
    if(err) {
      alert("Problem happened when download img: " + imgLink);
      console.erro("Problem happened when download img: " + imgLink);
      deferred.resolve(zip); // ignore this error: just logging
      // deferred.reject(zip); // or we may fail the download
    } else {
      zip.file("picture"+i+".jpg", data, {binary:true});
      deferred.resolve(zip);
    }
 });
return deferred;
}
</script>
Resources
jQuery.Deferred is the most important client-side tool you have
Understanding JQuery.Deferred and Promise
How to use JSZip
JSZipUtils.getBinaryContent

Blogger: Get Post Publish Date in JavaScript


You may want to use value of Blogger's data tag inside javascript. 
For example to get the page type of current page, you may add the following code in the template:
<script>
var pageType = '<data:pageTitle/>';
</script>

To get the publish date of current post when page type is "item" (post page).
First in Layout tab, change the Blog Posts widget to include date header like below:

Then search <b:includable id='post' var='post'> in your blogger's template, add the following code below it:

<b:includable id='post' var='post'>
<b:if cond='data:blog.pageType == "item"'>
<script>
  var dateHeader= '<data:post.dateHeader/>';
  var parts = dateHeader.split('-');
 var postDate = new Date(parts[0], parts[1]-1, parts[2]);
</script>
</b:if>

If you don't want to show date header in post, then make it invisible by adding the following css in your blogger template:
<style>
  .date-header {display: none;}
</style>

To view a complete list of Blogger's data tags, check:
How to make a blogger template : data tags - part 1
How to make a blogger template : data tags - part 2

Using Javascript to Disallow IFramed and How to Hack it


Using Javascript to Disallow IFramed
By accident, I accessed http://www.webupd8.org/, which uses the following JavaScript to disallow other sites to put its webpages into iframe.

If you put it the follow iframe in webpage, it will open an alter dialog and redirect to its original site webpage.
<iframe src="http://www.webupd8.org/"></iframe>
How it's implemented
It compares the top window with self, if they are not same, then current page is put inside a frame.
The top property returns the topmost browser window of the current window. 
The self property returns the current window.

<script type='text/javascript'> 
// <![CDATA[
if ( top != self) {      
   top.location.replace(document.location);
   alert("iFrame not allowed; click OK to load this page without the iFrame.")
}
// ]]>
</script>
How to Hack It
But this protection can be easily bypassed and hacked.
In HTML5, the iframe has a new attribute sandbox to help safeguard your site from the embedded iframe. 
allow-same-origin - allows the iframe to access cookies and local storage from the parent, as if it came from the same domain.
allow-top-navigation - allows the iframe to navigate the parent to a different URL.
allow-forms - allows form submission
allow-scripts - allows JavaScript execution
allow-popups - allows the iframe to open new windows or tabs
allow-pointer-lock - allows pointer lock
so if we add sandbox="" or just sandbox in the iframe attribute, then brwoser will disallow javscript in the iframe to be executed.  Then the previous javascript protecttion would be voided.
<iframe allowtransparency="true" frameborder="0" sandbox="" scrolling="no" src="http://www.webupd8.org/" style="border: none; overflow: hidden;"></iframe>
Resources
Protect Your Website From Its Embedded Content With Iframes
HTML iframe sandbox Attribute

JavaScript: Get the First and Last day of Current Week and Month


Get the First and Last day of Current Week

The basic idea is to use getDate() and getDay(), and get the difference of current date and the first or last day of this week.

  • getDate() returns the day of the month (from 1 to 31) for the specified date.
  • getDay() returns the day of the week (from 0 to 6) for the specified date.
function getMondayOfCurrentWeek(d)
{
    var day = d.getDay();
    return new Date(d.getFullYear(), d.getMonth(), d.getDate() + (day == 0?-6:1)-day );
}
function getSundayOfCurrentWeek(d)
{
    var day = d.getDay();
    return new Date(d.getFullYear(), d.getMonth(), d.getDate() + (day == 0?0:7)-day );
}

Get the First and Last day of Current Month

function getFirstDayOfCurrentMonth(d){
  return new Date(d.getFullYear(), d.getMonth(), 1);
}
function getLastDayOfCurrentMonth(d){
  return new Date(d.getFullYear(), d.getMonth()+1, 0);
}

Get String in yyyy-mm-dd Format

function yymmdd(dataObj){
  var month = (dataObj.getMonth()+1);
  var monthStr = month<10? ('0' + month): month;
  var dateStr = dataObj.getDate()< 10? ('0' + dataObj.getDate()): dataObj.getDate();
  return dataObj.getFullYear() + "-" + monthStr + "-" + dateStr;
}

Date Formatting In Java With Time Zone


The Problem
GAE's system timezone is UTC and I need print date using the specified timezone and format.

The Solution
We can call DateFormat.setTimeZone to set it's timezone:

  public static String formatDate(Date date, String format, TimeZone tz) {
    DateFormat df = new SimpleDateFormat(format);
    df.setTimeZone(tz);
    return df.format(date);
  }
To get get all available time zone ids: System.out.println(Arrays.toString(TimeZone.getAvailableIDs()));
The test code is like below:
  @Test
  public void testDfWithTZ() {
    // To get all available time zone ids:
    System.out.println(Arrays.toString(TimeZone.getAvailableIDs()));
    Date date = new Date();
    String format = "yyyy-MM-dd hh:mm:ss";
    TimeZone tz = TimeZone.getTimeZone("US/Eastern");
    String dateStr = formatDate(date, format, tz);
    System.out.println(dateStr);
    
    tz = TimeZone.getTimeZone("Asia/Shanghai");
    dateStr = formatDate(date, format, tz);
    System.out.println(dateStr);
    
    // Get system's default timezone
    tz = TimeZone.getDefault();
    dateStr = formatDate(date, format, tz);
    System.out.println(dateStr);
  }

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)