<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>Simpler is better!</title>
		<link>http://www.java2go.net/blog/</link>
		<description>Sehwan@Noh&#039;s Personal Weblog</description>
		<language>ko</language>
		<pubDate>Tue, 18 Nov 2008 15:29:51 +0900</pubDate>
		<generator>Tattertools 1.1.2.2 : Animato</generator>
		<image>
		<title>Simpler is better!</title>
		<url>http://www.java2go.net/blog/attach/1/1269604838.jpg</url>
		<link>http://www.java2go.net/blog/</link>
		<width>180</width>
		<height>120</height>
		<description>Sehwan@Noh&#039;s Personal Weblog</description>
		</image>
		<item>
			<title>Cron Job 설정 표현식</title>
			<link>http://www.java2go.net/blog/92</link>
			<description>스프링에서 Quartz를 사용하여 스케쥴링을 할 때 CronTriggerBean을 사용하여 설정할 경우 cronExpression 설정에 대한 예이다. &lt;br /&gt;&lt;br /&gt;
&lt;DIV style=&quot;BORDER-RIGHT: #777 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #777 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 5px; BORDER-LEFT: #777 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #777 1px solid; BACKGROUND-COLOR: #eee&quot;&gt;
&lt;TABLE cellSpacing=0 cellPadding=0 width=&quot;100%&quot; border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;PRE class=code&gt;&amp;lt;bean id=&quot;exampleCronTrigger&quot;
	class=&quot;org.springframework.scheduling.quartz.CronTriggerBean&quot;&amp;gt;
	&amp;lt;property name=&quot;jobDetail&quot;&amp;gt;
		&amp;lt;ref bean=&quot;exampleJob&quot; /&amp;gt;
	&amp;lt;/property&amp;gt;
	&amp;lt;property name=&quot;cronExpression&quot;&amp;gt;
		&amp;lt;value&amp;gt;&lt;STRONG&gt;0 59 23 * * ?&lt;/STRONG&gt;&amp;lt;/value&amp;gt;
	&amp;lt;/property&amp;gt;
&amp;lt;/bean&amp;gt;&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;br /&gt;1 Seconds (0-59)&lt;br /&gt;2 Minutes (0-59)&lt;br /&gt;3 Hours (0-23)&lt;br /&gt;4 Day of Month (1-31)&lt;br /&gt;5 Month (1-12 or JAN-DEC)&lt;br /&gt;6 Day of Week (1-7 or SUN-SAT)&lt;br /&gt;7 Year (1970-2099) &amp;lt;-- 생략 가능&lt;br /&gt;&lt;br /&gt;</description>
			<category>Spring</category>
			<category>Cron</category>
			<category>Cron Job</category>
			<category>Quartz</category>
			<category>Spring</category>
			<author> (노세환)</author>
			<guid>http://www.java2go.net/blog/92</guid>
			<comments>http://www.java2go.net/blog/92#entry92comment</comments>
			<pubDate>Fri, 24 Oct 2008 14:29:00 +0900</pubDate>
		</item>
		<item>
			<title>.svn 폴더 빠르게 삭제하기</title>
			<link>http://www.java2go.net/blog/90</link>
			<description>윈도우에서 아래와 같은 내용을 가진 bat/cmd 파일을 만들어 해당 폴더에서 실행한다.&lt;br /&gt;&lt;br /&gt;&lt;FONT face=&quot;&#039;courier new&#039;,courier,monospace&quot;&gt;for /f &quot;tokens=* delims=&quot; %%i in (&#039;dir /s /b /a:d *svn&#039;) do ( rd /s /q &quot;%%i&quot; )&lt;/FONT&gt;&lt;br /&gt;&lt;br /&gt;유닉스에서는 아래와 같은 명령을 해당 폴더에서 실행한다.&lt;br /&gt;&lt;br /&gt;&lt;FONT face=&quot;&#039;courier new&#039;,courier,monospace&quot;&gt;find . -type d -name &#039;.svn&#039; -print0 | xargs -0 rm -rdf&lt;br /&gt;&lt;br /&gt;&lt;/FONT&gt;</description>
			<category>Tools</category>
			<category>SVN</category>
			<category>Unix</category>
			<category>Windows</category>
			<author> (노세환)</author>
			<guid>http://www.java2go.net/blog/90</guid>
			<comments>http://www.java2go.net/blog/90#entry90comment</comments>
			<pubDate>Sun, 28 Sep 2008 17:52:00 +0900</pubDate>
		</item>
		<item>
			<title>콘솔로부터 패스워드 입력받기</title>
			<link>http://www.java2go.net/blog/89</link>
			<description>&lt;P&gt;커맨드라인 기반의 어플리케이션이나 서버 어플리케이션 등에서 커맨드라인에서 패스워드를 입력받는 경우는 종종 필요하다. 자바는 AWT/Swing에서는 패스워드를 마스킹할 수 있는 메소드를 별도로 제공하기 때문에 쉽게 구현할 수 있지만, 커맨드라인에서 패스워드를 마스킹하는 API를 별도로 제공하지 않아 여러 개발자에게 불편함을 주었다.&lt;br /&gt;&lt;br /&gt;Java SE 6.0에서는 java.io.Console 이라는 클래스에서 콘솔 장치에 대한 IO를 지원하는데, 패스워드 마스킹을 readPassword()라는 메소드를 통해 쉽게 구현할 수 있다. 아래는 Java SE 5.0 이하에서 사용할 수 있는 커맨드라인에서 패스워드를 입력을 마스킹하는 코드이다.&lt;br /&gt;&lt;br /&gt;&lt;/P&gt;
&lt;DIV style=&quot;BORDER-RIGHT: #777 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #777 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 5px; BORDER-LEFT: #777 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #777 1px solid; BACKGROUND-COLOR: #eee&quot;&gt;
&lt;TABLE cellSpacing=0 cellPadding=0 width=&quot;100%&quot; border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;PRE class=code&gt;import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 콘솔로부터 패스워드 입력 마스킹하기
 */
public class ConsolePassword {

    public static void main(String[] args) throws Exception {
        BufferedReader stdin =
            new BufferedReader(new InputStreamReader(System.in));
        ConsoleEraser consoleEraser = new ConsoleEraser();
        System.out.print(&quot;Enter Password: &quot;);
        consoleEraser.start();
        String password = stdin.readLine();
        consoleEraser.halt();
        System.out.print(&quot;\b&quot;);
        System.out.println(&quot;password=&quot; + password);
    }
}

class ConsoleEraser extends Thread {

    private boolean running = true;

    public void run() {
        while (running) {
            // System.out.print(&quot;\b*&quot;);
            System.out.print(&quot;\b &quot;);
            try {
                Thread.currentThread().sleep(1);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
    }

    public synchronized void halt() {
        running = false;
    }
}&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;br /&gt;참조: &lt;A href=&quot;http://java.sun.com/developer/technicalArticles/Security/pwordmask/&quot;&gt;http://java.sun.com/developer/technicalArticles/Security/pwordmask/&lt;/A&gt;&lt;br /&gt;</description>
			<category>Java SE</category>
			<category>Console</category>
			<category>Masking</category>
			<category>Password</category>
			<category>마스킹</category>
			<category>커맨드라인</category>
			<category>콘솔</category>
			<category>패스워드</category>
			<author> (노세환)</author>
			<guid>http://www.java2go.net/blog/89</guid>
			<comments>http://www.java2go.net/blog/89#entry89comment</comments>
			<pubDate>Sun, 24 Aug 2008 14:19:00 +0900</pubDate>
		</item>
		<item>
			<title>자바 암호화/복호화 코드</title>
			<link>http://www.java2go.net/blog/88</link>
			<description>자바에서 대칭키 방식의 문자열 및 파일을 암호화/복호화하는 코드이다. 암복호화 알고리즘은 Java Cryptography Extension (JCE)에 의해 지원된다.&lt;br /&gt;&lt;br /&gt;
&lt;DIV style=&quot;BORDER-RIGHT: #777 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #777 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 5px; BORDER-LEFT: #777 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #777 1px solid; BACKGROUND-COLOR: #eee&quot;&gt;
&lt;TABLE cellSpacing=0 cellPadding=0 width=&quot;100%&quot; border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;PRE class=code&gt;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;

/**
 * 문자열 및 파일에 대한 암호화/복호화
 */
public class Crypto {

    /** 파일 처리용 버퍼 크기 */
    private static final int BUFFER_SIZE = 8192;

    /** 디폴트 비밀키 파일 */
    private static final String DEFAULT_KEY_FILE = &quot;default.key&quot;;

    /** 비밀키 */
    private static Key key = null;

    /**
     * 비밀키 파일 생성 메소드
     * 
     * @return 비밀키 파일
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static File makeKey() throws IOException, NoSuchAlgorithmException {
        return makeKey(DEFAULT_KEY_FILE);
    }

    public static File makeKey(String filename) throws IOException,
                    NoSuchAlgorithmException {
        File file = new File(filename);
        KeyGenerator generator = KeyGenerator.getInstance(&quot;DES&quot;);
        generator.init(new SecureRandom());
        Key key = generator.generateKey();
        ObjectOutputStream out =
            new ObjectOutputStream(new FileOutputStream(file));
        out.writeObject(key);
        out.close();
        return file;
    }

    /**
     * 지정된 비밀키를 가지고 오는 메서드
     * 
     * @return 비밀키
     * @throws Exception
     */
    private static Key getKey() throws Exception {
        if (key != null) {
            return key;
        } else {
            return getKey(DEFAULT_KEY_FILE);
        }
    }

    private static Key getKey(String filename) throws Exception {
        if (key == null) {
            File file = new File(filename);
            if (!file.exists()) {
                file = makeKey();
            }
            if (file.exists()) {
                ObjectInputStream in =
                    new ObjectInputStream(new FileInputStream(filename));
                key = (Key) in.readObject();
                in.close();
            } else {
                throw new Exception(&quot;암호키 객체를 생성할 수 없습니다.&quot;);
            }
        }
        return key;
    }

    /**
     * 문자열 대칭 암호화
     * 
     * @param strVal 암호화할 문자열
     * @return 암호화된 문자열
     * @throws Exception
     */
    public static String encrypt(String strVal) throws Exception {
        if (strVal == null || strVal.length() == 0)
            return &quot;&quot;;
        Cipher cipher = Cipher.getInstance(&quot;DES/ECB/PKCS5Padding&quot;);
        cipher.init(Cipher.ENCRYPT_MODE, getKey());
        String amalgam = strVal;

        byte[] inputBytes1 = amalgam.getBytes(&quot;UTF8&quot;);
        byte[] outputBytes1 = cipher.doFinal(inputBytes1);
        sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
        String outputStr1 = encoder.encode(outputBytes1);
        return outputStr1;
    }

    /**
     * 문자열 대칭 복호화
     * 
     * @param strVal 복호화할 문자열
     * @return 복호화된 문자열
     * @throws Exception
     */
    public static String decrypt(String strVal) throws Exception {
        if (strVal == null || strVal.length() == 0)
            return &quot;&quot;;
        Cipher cipher = Cipher.getInstance(&quot;DES/ECB/PKCS5Padding&quot;);
        cipher.init(Cipher.DECRYPT_MODE, getKey());
        sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();

        byte[] inputBytes1 = decoder.decodeBuffer(strVal);
        byte[] outputBytes2 = cipher.doFinal(inputBytes1);

        String strResult = new String(outputBytes2, &quot;UTF8&quot;);
        return strResult;
    }

    /**
     * 파일 대칭 암호화
     * 
     * @param infile 암호화할 파일명
     * @param outfile 암호화된 파일명
     * @throws Exception
     */
    public static void encryptFile(String infile, String outfile)
                    throws Exception {
        Cipher cipher = Cipher.getInstance(&quot;DES/ECB/PKCS5Padding&quot;);
        cipher.init(Cipher.ENCRYPT_MODE, getKey());

        FileInputStream in = new FileInputStream(infile);
        FileOutputStream fileOut = new FileOutputStream(outfile);

        CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        while ((length = in.read(buffer)) != -1)
            out.write(buffer, 0, length);
        in.close();
        out.close();
    }

    /**
     * 파일 대칭 복호화
     * 
     * @param infile 복호화할 파일명
     * @param outfile 복호화된 파일명
     * @throws Exception
     */
    public static void decryptFile(String infile, String outfile)
                    throws Exception {
        Cipher cipher = Cipher.getInstance(&quot;DES/ECB/PKCS5Padding&quot;);
        cipher.init(Cipher.DECRYPT_MODE, getKey());

        FileInputStream in = new FileInputStream(infile);
        FileOutputStream fileOut = new FileOutputStream(outfile);

        CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        while ((length = in.read(buffer)) != -1)
            out.write(buffer, 0, length);
        in.close();
        out.close();
    }&lt;!--

    /**
     * 콘솔 커맨드 실행하기
     * 
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        if (args.length &amp;lt; 2) {
            System.out.println(&quot;USAGE: java net.java2go.util.Crypto &quot;
                + &quot;[-e | -d | -fe | -fd] [text | inputfile outputfile]&quot;);
        } else if (args[0].equals(&quot;-e&quot;)) {
            System.out.println(Crypto.encrypt(args[1]));
        } else if (args[0].equals(&quot;-d&quot;)) {
            System.out.println(Crypto.decrypt(args[1]));
        } else if (args[0].equals(&quot;-fe&quot;)) {
            Crypto.encryptFile(args[1], args[2]);
        } else if (args[0].equals(&quot;-fd&quot;)) {
            Crypto.decryptFile(args[1], args[2]);
        }
    }--&gt;
}&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;</description>
			<category>Java SE</category>
			<category>Crypto</category>
			<category>Cryptography</category>
			<category>JCE</category>
			<category>대칭키</category>
			<category>복호화</category>
			<category>비밀키</category>
			<category>암호화</category>
			<author> (노세환)</author>
			<guid>http://www.java2go.net/blog/88</guid>
			<comments>http://www.java2go.net/blog/88#entry88comment</comments>
			<pubDate>Sat, 23 Aug 2008 23:11:00 +0900</pubDate>
		</item>
		<item>
			<title>JUnit과 TestNG 비교</title>
			<link>http://www.java2go.net/blog/87</link>
			<description>다양한 프레임워크에서 도입되고 확장되어온 JUnit은 최근에 &lt;a href=&quot;http://www.junit.org/node/401&quot; target=&quot;_blank&quot;&gt;JUnit 4.5&lt;/a&gt;가 릴리즈 되었다. 한편 단위테스트를 넘어 통합/기능테스트를 지원하는 TestNG는 JUnit 보다 더 많은 테스팅 기능들을 제공하고 있다. 두 테스팅 프레임워크의 기능/특징 비교 내용을 옮겨보았다.&lt;br /&gt;&lt;br /&gt;
&lt;table align=&quot;center&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td width=&quot;300&quot;&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/td&gt;
&lt;td width=&quot;55&quot; align=&quot;middle&quot;&gt;&lt;strong&gt;JUnit&lt;/strong&gt;&lt;/td&gt;
&lt;td width=&quot;55&quot; align=&quot;middle&quot;&gt;&lt;strong&gt;TestNG&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User Defined Life Cycle&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test Organization (groups, etc)&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distributed Test Execution&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallel Test Execution&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Driven Tests&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency Testing&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDE Integration&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ant Integration&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maven Integration&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain Specific Extensions (Database, HTTP, etc)&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Active Community&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;
&lt;td align=&quot;middle&quot;&gt;&lt;img alt=&quot;check&quot; src=&quot;http://www.michaelminella.com/images/contentImages/accept.png&quot;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;출처: &lt;a href=&quot;http://www.michaelminella.com/blog/2.html&quot;&gt;http://www.michaelminella.com/blog/2.html&lt;/a&gt;&lt;br /&gt;</description>
			<category>Testing</category>
			<category>JUnit</category>
			<category>Testing</category>
			<category>TestNG</category>
			<author> (노세환)</author>
			<guid>http://www.java2go.net/blog/87</guid>
			<comments>http://www.java2go.net/blog/87#entry87comment</comments>
			<pubDate>Wed, 20 Aug 2008 17:02:10 +0900</pubDate>
		</item>
	</channel>
</rss>
