2014年8月

使用casperjs截出优雅的图片

前言

  1. phantomjs中文问题

  2. phantomjs中文问题 [后续]

优化字体的显示

使用Chrome OS字体来代替serif, sans-serif, sans, monospace字体

/usr/share/fonts/default/truetype/croscorefonts
├── Arimo-BoldItalic.ttf
├── Arimo-Bold.ttf
├── Arimo-Italic.ttf
├── Arimo-Regular.ttf
├── Cousine-BoldItalic.ttf
├── Cousine-Bold.ttf
├── Cousine-Italic.ttf
├── Cousine-Regular.ttf
├── fonts.dir
├── fonts.scale
├── SymbolNeu.ttf
├── Tinos-BoldItalic.ttf
├── Tinos-Bold.ttf
├── Tinos-Italic.ttf
└── Tinos-Regular.ttf

0 directories, 15 files

~/.fonts.conf

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>

  <!-- Set preferred serif, sans serif, and monospace fonts. -->
  <alias>
    <family>serif</family>
    <prefer><family>Tinos</family></prefer>
  </alias>
  <alias>
    <family>sans-serif</family>
    <prefer><family>Arimo</family></prefer>
  </alias>
  <alias>
    <family>sans</family>
    <prefer><family>Arimo</family></prefer>
  </alias>
  <alias>
    <family>monospace</family>
    <prefer>
        <family>Meslo LG L DZ</family>
        <family>Cousine</family>
    </prefer>
  </alias>

  <!-- Aliases for commonly used MS fonts. -->
  <match>
    <test name="family"><string>Arial</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Helvetica</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Verdana</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Tahoma</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <!-- Insert joke here -->
    <test name="family"><string>Comic Sans MS</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Times New Roman</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Tinos</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Times</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Tinos</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Courier New</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Cousine</string>
    </edit>
  </match>

  <match target="font" >
    <edit mode="assign" name="autohint" >
      <bool>true</bool>
    </edit>
  </match>
  <match target="font" >
    <edit mode="assign" name="rgba" >
      <const>none</const>
    </edit>
  </match>
  <match target="font" >
    <edit mode="assign" name="hinting" >
      <bool>false</bool>
    </edit>
  </match>
  <match target="font" >
    <edit mode="assign" name="hintstyle" >
      <const>hintnone</const>
    </edit>
  </match>
  <match target="font" >
    <edit mode="assign" name="antialias" >
      <bool>true</bool>
    </edit>
  </match>
</fontconfig>
fc-cache -fv
# 查看一下字体是否选择正确
fc-match monospace

js脚本

example.js

var fs = require('fs');

var casper = require('casper').create({
    stepTimeout: 3000
});

var url = casper.cli.get(0);
url = url || 'http://tool.lu/';

casper.start().viewport(1280, 800).thenOpen(url, function () {
    // this.captureSelector('snap.png', '.post');
    var filename = 'snap.png';
    this.capture(filename);
    this.echo(JSON.stringify({url: this.getCurrentUrl(), path : fs.absolute(filename)}));
});

casper.run();
casperjs example.js http://tool.lu/

效果图

snap.png

java中的线程池

为什么要使用线程池

  1. 重复利用已创建的线程降低线程创建和销毁造成的消耗

  2. 提高线程的可管理性,可进行统一的分配,调优和监控

线程池的处理流程

threadpool.jpg

ExecutorService

newCachedThreadPool();
newFixedThreadPool();
newScheduledThreadPool();
newSingleThreadExecutor();

ScheduledThreadPool使用优先级队列进行排序(距离下次调度间隔短的任务排在前面)
DelayedWorkQueue


package lu.tool.demo;

import java.util.concurrent.*;

/**
 * Created by xiaozi on 14-8-28.
 */
public class CachedThreadPoolDemo {

    public static void main(String[] args) {
        ExecutorService es = Executors.newCachedThreadPool();
        ThreadPoolExecutor tpe = (ThreadPoolExecutor) es;

//        tpe.setMaximumPoolSize(100);

        Future<?> future = null;
//        for (int i = 1; i < 8000; i++) {
        for (int i = 1; i < 100; i++) {
            future = tpe.submit(new TaskDemo());
        }

        System.out.println("largest pool size: " + tpe.getLargestPoolSize());
        System.out.println("task count: " + tpe.getTaskCount());

        if (future != null) {
            try {
                future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

//        tpe.shutdown();
    }
}
package lu.tool.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Created by xiaozi on 14-8-28.
 */
public class FixedThreadPoolDemo {

    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(100);
        ThreadPoolExecutor tpe = (ThreadPoolExecutor) es;

        for (int i = 1; i < 8000; i++) {
            tpe.submit(new TaskDemo());
        }

        tpe.shutdown();
    }
}
package lu.tool.demo;

import java.util.concurrent.*;

/**
 * Created by xiaozi on 14-8-28.
 */
public class ScheduledThreadPoolDemo {

    public static void main(String[] args) {
        ScheduledExecutorService es = Executors.newScheduledThreadPool(100);

        for (int i = 1; i < 8000; i++) {
            es.schedule(new TaskDemo(), 3, TimeUnit.SECONDS);
        }

        // scheduleAtFixedRate
        // scheduleWithFixedDelay

        es.shutdown();
    }
}
package lu.tool.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by xiaozi on 14-8-28.
 */
public class SingleThreadExecutorDemo {

    public static void main(String[] args) {
        ExecutorService es = Executors.newSingleThreadExecutor();

        for (int i = 1; i < 8000; i++) {
            es.submit(new TaskDemo());
        }

        es.shutdown();
    }
}

ThreadPoolExecutor

ThreadPoolExecutor(int corePoolSize,
                    int maximumPoolSize,
                    long keepAliveTime,
                    TimeUnit unit,
                    BlockingQueue<Runnable> workQueue,
                    RejectedExecutionHandler handler);
参数解释
corePoolSize线程池维护线程的最少数量
maximumPoolSize线程池维护线程的最大数量
keepAliveTime线程池维护线程所允许的空闲时间
unit线程池维护线程所允许的空闲时间的单位
workQueue线程池所使用的缓冲队列
handler线程池对拒绝任务的处理策略
package lu.tool.demo;


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by xiaozi on 14-8-29.
 */
public class ThreadPoolExecutorDemo {

    public static void main(String[] args) {
        ThreadPoolExecutor tpe = new ThreadPoolExecutor(3, 5, 60,
                                                        TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10),
                                                        new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 1; i < 8000; i++) {
            tpe.submit(new TaskDemo());
        }

        tpe.shutdown();
    }
}

阻塞队列

ArrayBlockingQueu   // 有界
LinkedBlockingQueue // 无界
SynchronousQueue
PriorityBlockingQueue

线程池的监控

beforeExecute(Thread t, Runnable r)
afterExecute(Runnable r, Throwable t)

executor.getTaskCount();
executor.getCompletedTaskCount();

executor.getLargestPoolSize();

executor.isShutdown();  
executor.isTerminated();

多少线程合适

  1. CPU密集型任务(ncpu + 1)

  2. I/O密集型任务(2 * ncpu)

  3. 任务的执行时间

  4. 任务的依赖性

阻塞队列的实现

线程池队列
ScheduledThreadPoolDelayedWorkQueueReentrantLock.newConditionavailable
FixedThreadPoolLinkedBlockingQueueReentrantLock.newConditionput, take
CachedThreadPoolSynchronousQueueReentrantLock
SingleThreadLinkedBlockingQueueReentrantLock.newConditionput, take

引用

  1. 聊聊并发(三)——JAVA线程池的分析和使用

  2. 线程池

  3. Java四种线程池的使用

  4. 多线程之线程池探索

  5. 深入浅出多线程(4)对CachedThreadPool OutOfMemoryError问题的一些想法

  6. ScheduledThreadPoolExecutor实现原理

  7. JAVA线程池ThreadPoolExecutor

  8. JAVA线程池学习以及队列拒绝策略

phantomjs中文问题 [后续]

之前写过一篇文章:phantomjs中文问题

里面的解决办法也是碰巧,如今将解决问题之所在。

# 列出所有已经安装的中文字体,如果还没有安装中文字体,可参考上文提到的文章。
fc-list :lang=zh
# 宋体,SimSun:style=Regular

# 看下字体是怎么走的
fc-match Arial -s
# SimSun.ttf: "SimSun" "Regular"
# n019003l.pfb: "Nimbus Sans L" "Regular"
# cursor.pfa: "Cursor" "Regular"
# d050000l.pfb: "Dingbats" "Regular"
# s050000l.pfb: "Standard Symbols L" "Regular"
# 哎呀,是对的呀,为什么phantomjs不认呢,(ÒωÓױ)

# 查看下本地语言设置
locale
# LANG=zh_CN.UTF-8
# LC_CTYPE=zh_CN.UTF-8
# LC_NUMERIC="zh_CN.UTF-8"
# LC_TIME="zh_CN.UTF-8"
# LC_COLLATE="zh_CN.UTF-8"
# LC_MONETARY="zh_CN.UTF-8"
# LC_MESSAGES="zh_CN.UTF-8"
# LC_PAPER="zh_CN.UTF-8"
# LC_NAME="zh_CN.UTF-8"
# LC_ADDRESS="zh_CN.UTF-8"
# LC_TELEPHONE="zh_CN.UTF-8"
# LC_MEASUREMENT="zh_CN.UTF-8"
# LC_IDENTIFICATION="zh_CN.UTF-8"
# LC_ALL=


# 嗯,据说 QT 在对“宋体,SimSun:style=Regular”处理的时候是有问题的
export LC_CTYPE=en_US.UTF-8
fc-list :lang=zh
# SimSun,宋体:style=Regular
# 换了个顺序,试试...,呵呵,phantomjs中文的问题解决了 - - |||

因为不需要全局修改LC_CTYPE,所以在命令前面加一下就好了。为了方便写个alias

alias casperjs='LC_CTYPE=en_US.UTF-8 casperjs'

悬疑推理分类

悬疑推理

犯罪

1.沉默的羔羊系列

  赤龙
  汉尼拔
  沉默的羔羊

2.记忆碎片

3.十二宫杀手

4.足迹 Sleuth

5.王牌对王牌 The Negotiator

6.东方快车谋杀案 Murder on the Orient Express (1974)

7.大卫·戈尔的一生 The Life of David Gale

8.不道德的审判 Death and the Maiden

惊悚/恐怖

1.恐怖游轮

2.时空罪恶

3.禁闭岛

4.穆赫兰道

5.万能钥匙

6.心慌方

  异次元杀阵
  异次元杀阵3:前传
  异次元杀阵2:超级立方体

7.第六感 The Sixth Sense

8.十二猴子

9.蝴蝶效应 The Butterfly Effect (2004)

剧情

1.飞跃疯人院

2.搏击俱乐部

3.永无止境

4.低俗小说

5.猜火车

6.魔术师 The Illusionist

*7.盗墓者的忏悔 I Sell The Dead

8.时空三部曲

  天堂电影院
  海上钢琴师
  西西里的美丽传说

9.放牛班的春天 Les choristes

10.死亡诗社 Dead Poets Society

11.闻香识女人 Scent of a Woman

12.当幸福来敲门 The Pursuit of Happyness

13.燃情岁月 Legends of the Fall

14.国王的演讲 The King's Speech

15.贫民窟的百万富翁 Slumdog Millionaire

16.触不可及 Intouchables

17.心灵捕手 Good Will Hunting

18.七磅 Seven Pounds

19.美丽人生 La vita è bella

20.小鞋子 بچههای آسمان

21.偷自行车的人 Ladri di biciclette

22.蝴蝶 Le Papillon

23.中央车站 Central do Brasil

24.大鱼 Big Fish

25.勇敢的心 Braveheart

26.角斗士 Gladiator

27.美国丽人 American Beauty

28.十二怒汉 12 Angry Men (1957) (1997)(2007)

29.她比烟花寂寞 Hilary and Jackie

30.走出非洲 Out of Africa

31.玫瑰人生 La Môme

32.窃听风暴 Das Leben der Anderen

33.水果硬糖

34.拯救大兵瑞恩

35.八月迷情 August Rush

36.超脱 Detachment

37.蝙蝠侠系列

   蝙蝠侠:侠影之谜 Batman Begins (2005)
   蝙蝠侠:黑暗骑士 The Dark Knight (2008)
   蝙蝠侠:黑暗骑士崛起 The Dark Knight Rises (2012)

38.阳光小美女 Little Miss Sunshine

39.天才瑞普利 The Talented Mr. Ripley

40.碟中谍系列

   碟中谍 Mission: Impossible (1996)
   碟中谍2 Mission: Impossible II (2000)
   碟中谍3 Mission: Impossible III (2006)
   碟中谍4 Mission: Impossible - Ghost Protocol (2011)

41.谍影重重系列

   谍影重重 The Bourne Identity (2002)
   谍影重重2 The Bourne Supremacy (2004)
   谍影重重3 The Bourne Ultimatum (2007)
   谍影重重4 The Bourne Legacy (2012)

42.洛奇系列

   洛奇 Rocky (1976)
   洛奇2 Rocky II (1979)
   洛奇3 Rocky III (1982)
   洛奇4 Rocky IV (1985)
   洛奇5 Rocky V (1990)
   洛奇6:永远的拳王 Rocky Balboa (2006)

43.第一滴血系列

   第一滴血 First Blood (1982)
   第一滴血2 Rambo: First Blood Part II (1985)
   第一滴血3 Rambo III (1988)
   第一滴血4 Rambo (2008)

44.行动目标希特勒 Valkyrie

45.希望与荣耀 Hope and Glory

46.音乐永不停止 The Music Never Stopped

47.勇士 Warrior

48.斯图尔特:倒带人生 Stuart: A Life Backwards

49.美国往事 Once Upon a Time in America

50.逃离德黑兰 Argo

51.德黑兰43年 Тегеран-43

52.锅匠,裁缝,士兵,间谍 Tinker Tailor Soldier Spy

53.无耻混蛋 Inglourious Basterds

54.追风筝的人 The Kite Runner

55.两杆大烟枪 Lock, Stock and Two Smoking Barrels

56.偷拐抢骗 Snatch

57冰上轻驰 Cool Runnings

58.一次别离 جدایی نادر از سیمین

59.狩猎 Jagten

60.调音师 L'accordeur

61.天生杀人狂 Natural Born Killers

62.上帝之城 Cidade de Deus

63.登堂入室 Dans la maison

64.我是山姆 I Am Sam (2001)

65.狗镇 Dogville (2003)

66.克洛伊 Chloe

67.水中刀 Nóz w wodzie (1962)

68.邮差 Il postino (1994)

69.出租车司机 Taxi Driver (1976)

70.对她说 Hable con ella (2002)

71.布朗克斯的故事 A Bronx Tale (1993)

72.K星异客 K-PAX (2001)

73.这个男人来自地球 The Man from Earth (2007)

74.碧海蓝天 Le grand bleu (1988)

75.海盗电台 The Boat That Rocked

76.危情三日 The Next Three Days

77.这个杀手不太冷 Léon

78.巴黎,我爱你 Paris, je t'aime

79.疤面煞星 Scarface (1983)

80.荒岛余生 Cast Away

81.谜中谜 Charade (1963)

82.金蝉脱壳

83.罗拉快跑 Lola rennt (1998)

84.雌雄大盗 Bonnie and Clyde

85.雾中风景 Τοπίο στην ομίχλη

86.内布拉斯加 Nebraska

87.弱点 The Blind Side

88.感谢你抽烟 Thank You for Smoking

89.壮志凌云 Top Gun

90.通天塔 Babel

91.老无所依 No Country for Old Men

92.大地雄心 Far and Away

93.大河恋 A River Runs Through It

94.遗愿清单 The Bucket List

95.不可饶恕 Unforgiven

96.百万美元宝贝 Million Dollar Baby

97.撞车 Crash

98.钢琴家 The Pianist

99.布达佩斯大饭店 The Grand Budapest Hotel

科幻/奇幻

1.永无止境

2.时间规划局 In Time

3.楚门的世界

4.心灵传输者 Jumper

5.我是传奇 I Am Legend

6.香水 Perfume: The Story of a Murderer

7.人工智能 Artificial Intelligence: AI

8.铁甲钢拳 Real Steel

9.黑天鹅 Black Swan

10.潘神的迷宫 El laberinto del fauno

11.V字仇杀队 V for Vendetta

12.绿里奇迹 The Green Mile

13.夜访吸血鬼 Interview with the Vampire: The Vampire Chronicles

14.云图 Cloud Atla

15.午夜巴黎 Midnight in Paris (2011)

16.少年派的奇幻漂流 Life of Pi

17.白日梦想家 The Secret Life of Walter Mitty

18.机器管家 Bicentennial Man

19.土拨鼠之日 Groundhog Day

真实故事改编/传记/小说改编

1.死亡实验 Das Experiment

2.美丽心灵 A Beautiful Mind

3.穿条纹睡衣的男孩 The Boy in the Striped Pajamas

4.日瓦戈医生 Doctor Zhivago (1965)

5.卢旺达饭店 Hotel Rwanda

6.布拉格之恋 The Unbearable Lightness of Bein

7.基督山伯爵 The Count of Monte Cristo

8.莎翁情史 Shakespeare in Love

9.摩托日记 Diarios de motocicleta

10.荆棘鸟 The Thorn Birds

11.教父系列 The Godfather

   教父 The Godfather (1972)
   教父2 The Godfather: Part Ⅱ (1974)
   教父3 The Godfather: Part III (1990)

12.洛城机密 L.A. Confidential

13.莫扎特传 Amadeus (1984)

14.刺杀肯尼迪 JFK (1991)

15.浪潮 Die Welle (2008)

16.叫我第一名 Front of the Class

17.寻找小糖人 Searching for Sugar Man

18.兰迪·波许教授的最后一课 Randy Pausch's Last Lecture

19.十月的天空 October Sky

20.情人 L'amant (1992)

21.弗里达 Frida (2002)

22.情迷六月花 Henry & June

23.罗丹的情人 Camille Claudel (1988)

24.阿黛尔·雨果的故事 L'histoire d'Adèle H. (1975)

25.倾国之恋 W.E. (2011)

26.永远的车神 Senna (2010)

27.极速风流 Rush (2013)

28.圣安娜奇迹 Miracle at St. Anna (2008)

29.荒野生存 Into the Wild

30.菲利普船长 Captain Phillips

种族/社会问题

1.紫色 The Color Purple

2.光荣之路 Glory Road

3.为奴十二载 12 Years a Slave

4.美国X档案 American History X

5.达拉斯买家俱乐部 Dallas Buyers Club (2013)

6.远离天堂 Far from Heaven

7.费城故事 Philadelphia (1993)

8.勇者无惧 Amistad

一些php扩展的资料整理

Thread-Safe 宏

TSRM

Thread-Safe Resource Manager
线程安全资源管理

ZTS

Zend Thread Safety
Zend 线程安全

tsrm_ls

TSRM local storage
线程安全资源管理 本地存储

TSRMLS_??

TSRMLS_C tsrm_ls
TSRMLS_D void ***tsrm_ls
TSRMLS_CC , tsrm_ls
TSRMLS_DC , void ***tsrm_ls
CC - call with comma
     前置逗号的调用
C  - call
     调用
DC - declaration with comma
     前置逗号的声明
D  - declaration
     声明

zend_parse_parameters

类型符号

类型字符php参数类型c类型
llonglong
ddoubledouble
sstringchar* / int
bbooleanzend_bool
rresourcezval*
aarrayzval*
zzvalzval*
Zzvalzval**
ffunctionfunction
o/Oclasszval, zend_class_entry

控制字符

控制字符作用
|它之前的参数都是必须的,之后的都是非必须的,也就是有默认值的。
!如果接收了一个PHP语言里的null变量,则直接把其转成C语言里的NULL,而不是封装成IS_NULL类型的zval。
/如果传递过来的变量与别的变量共用一个zval,而且不是引用,则进行强制分离,新的zval的is_ref__gc==0, and refcount__gc==1.

返回值

返回函数
RETURN_RESOURCE(resource)
RETURN_BOOL(bool)
RETURN_NULL()
RETURN_LONG(long)
RETURN_DOUBLE(double)
RETURN_STRING(string, duplicate)
RETURN_STRINGL(string, length, duplicate)
RETURN_EMPTY_STRING()
RETURN_FALSE()
RETURN_TRUE()

helpers

helperexpanded解释
ZEND_FE_END(){NULL, NULL, NULL}用于zend_function_entry的最后一行
ZEND_STRL("str")"str", strlen("str")用于同时需要字符串和其长度的函数中

Bash杂记

取出文件列表

# 防止WordSplitting,避免使用$(ls *.txt)
for file in *.txt
do
    # 防止文件名以-开头
    cp "./$file" /path/to/target
done

按行读取文件

while read line
do
    echo "$line"
done < text.txt

拷贝文件

cp -- "$file" "$target"
# -- 防止文件名以-开头
# " 防止文件名中含有空格

字符串比较

[[ $foo == "$bar" ]]

cd到目录

# -P prefix
cd -P -- "$(dirname -- "$f")"

数字比较

((foo > 7))
# 或者
[ "$foo" -gt 7 ]

判断文件中是否包含某个字符串

if grep -q fooregex /path/to/file; then
    # do something here
fi

多条件判断

if [ a = b ] && [ c = d ]
# 或者
if [[ a = b && c = d ]]

对文件的修改

先修改到临时文件,再mv回去

多行字符串

# 不要使用echo
cat <<EOF
  Hello world
  How's it going?
EOF

对cd命令是否成功的判断

cd /foo && bar
# 或者有很多依赖于cd之后的命令
cd /foo || exit 1
# ...
# ...
# 或者顺便说点什么 
cd /foo || { echo "hi, man!"; exit 1; }

for循环

for ((i=1; i<=n; i++)); do
    # do something here
done

错误重定向

# 先重定向到文件,再定向到标准输出(标准输出已经到tty了)
somecmd >>logfile 2>&1

发布jar包之后的依赖解决

使用脚本获取所有依赖jar包 -cp

java --cp $(JARS=("$LIB"/*.jar); IFS=:; echo "${JARS[*]}") -jar you-project-jar.jar

直接将依赖jar包打包在要发布的jar中

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tool.js</groupId>
    <artifactId>js-tool</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <name>js-tool</name>
    <url>http://tool.lu</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.javascript</groupId>
            <artifactId>closure-compiler</artifactId>
            <version>v20140407</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.7</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.tool.js.App</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>