package com.cawring.simple.route;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
/**
*
* <pre>
* 클래스명 : 라우터 유틸
* 패키지명 : com.cawring.simple.route
* 파일명 : RouteUtils.java
* 설명 :
* 라우터 파서 및 정보 추출 시, 사용하는 유틸모음
* </pre>
* @Author : 백승건
* @Date : 2014. 3. 11.
* @Version : v.1.0.0 - 2014. 3. 11. 최초작성
*/
public class RouteUtils
{
/**
*
* <pre>
* 메소드명 : 라우터 정보를 추출한다.
* 메소드작성일 : 2014. 3. 12.
* 메소드설명 :
* routes 파일의 라인 정보를 받아 VO에 담는다.
* </pre>
* @param line : routes 파일을 1line
* @return routeVO
* @throws RuntimeException
*/
public static RouteVO getRouteInfo(String line)
{
/* 앞뒤 공백 제거 */
String routeLine = StringUtils.trimToNull(line);
/* 라우터 정보 : 라인에서 공백 및 탭을 구분하여 라우터 정보를 가지고 온다. */
CharMatcher token = CharMatcher.WHITESPACE.or(CharMatcher.is('\t')); // 공백과 탭으로 구분한다.
Splitter splitter = Splitter.on(token).trimResults().omitEmptyStrings(); // 앞뒤공백을 제거하고 값이 빌 경우 구분에서 제외시킨다.
String[] words = Iterables.toArray(splitter.split(routeLine), String.class); // 배열로 담는다.
/* 라우터 정보 유효성 체크 */
if(words.length != RouteConstants.ROUTE_INFO_ARR_LEN) // 정보구성이 3개가 아닌 경우 exception 처리한다.
{
throw new RouteParseException("라우터 정보 작성 시 "+RouteConstants.ROUTE_INFO_ARR_LEN+"구분값만을 요구합니다."+line);
}
/* url 메소드 정보가 아닌경우 */
if(!isUrlMethod(words[RouteConstants.ROUTE_INFO_METHOD_IDX]))
{
throw new RouteParseException("라우터 정보 작성 시 METHOD 허용값은 GET, POST입니다."+line);
}
/* url 메소드 정보가 아닌경우 */
if(!isController(words[RouteConstants.ROUTE_INFO_PKG_PATH_IDX]))
{
throw new RouteParseException("라우터 정보 작성 시 컨트롤러 정보에 오류가 있습니다."+line);
}
/* 라우터 정보를 담는다. */
String method = words[RouteConstants.ROUTE_INFO_METHOD_IDX];
String url = words[RouteConstants.ROUTE_INFO_URL_IDX];
String packagePath = words[RouteConstants.ROUTE_INFO_PKG_PATH_IDX];
RouteVO vo = new RouteVO(method, url, packagePath);
return vo;
}
/**
*
* <pre>
* 메소드명 : 파싱 제외 대상 SKIP
* 메소드작성일 : 2014. 3. 12.
* 메소드설명 :
* 파싱할 문자열에 COMMENT_MARK가 있는 경우 SKIP한다.
* </pre>
* @param line : routes 파일의 1line
* @return true or false
*/
public static boolean isLineSkip(String line)
{
/* 앞뒤 공백 제거 */
String routeLine = StringUtils.trimToNull(line);
/* 빈값 혹은 null일 경우 skip 한다. */
if(Strings.isNullOrEmpty(routeLine))
{
return true;
}
/* 코멘트 마크가 라인 선두에 있으면 skip한다. */
if(StringUtils.startsWith(line, RouteConstants.COMMENT_MARK))
{
return true;
}
/* 유효한 문자열 */
return false;
}
/**
*
* <pre>
* 메소드명 : 유효한 URL METHOD 정보가 맞는지 확인한다.
* 메소드작성일 : 2014. 3. 11.
* 메소드설명 :
* GET, POST 정보가 맞는지 문자열 확인한다.
* </pre>
* @param method : url method
* @return GET or POST ? true : false
*/
public static boolean isUrlMethod(String method)
{
if(StringUtils.equals(RouteConstants.METHOD_GET, method))
{
return true;
}
else if(StringUtils.equals(RouteConstants.METHOD_POST, method))
{
return true;
}
return false;
}
/**
*
* <pre>
* 메소드명 : 컨트롤러의 존재여부를 확인한다.
* 메소드작성일 : 2014. 3. 11.
* 메소드설명 :
* 라우터 정보값을 통해 클래스, 메소드 명을 추출하고
* 클래스 로드를 통해 컨트롤러와 메소드 선언을 통해 각각의
* 존재유무를 파악한다.
* </pre>
* @param packagePath : 클래스+메소드 - ex> com.cawring.idea.controllers.Stock.index
* @return true or false
*/
public static boolean isController(String packagePath)
{
/* 컨트롤러와 메소드 구분값 */
int lastDotIdx = StringUtils.lastIndexOf(packagePath, ".");
/* 구분자가 없는 경우 */
if(lastDotIdx == -1)
{
String errMsg = "라우터 정보 작성 시 Controller 정보는 패키지와 메소드의 구분자로 '.'을 포함하여야 합니다.";
throw new RouteParseException(errMsg);
}
/* 컨트롤러(class)명과 메소드명 추출 */
String controller = StringUtils.substring(packagePath, 0, lastDotIdx); // 컨트롤러
String method = StringUtils.substring(packagePath, lastDotIdx+1); // 메소드명
/* 에러메시지 작성 */
String contErr = "Controller가 클래스로 존재하지 않습니다. "+packagePath+" 컨트롤러 : "+controller;
String methodErr = "Controller에 method가 존재하지 않습니다. "+packagePath+" 메소드 : "+method;
/* 존재여부 확인 */
try
{
Class<?> contClass = Class.forName(controller); // 컨트롤러 클래스 호출
Object contObject = contClass.newInstance(); // 컨트롤러 생성
contObject.getClass().getDeclaredMethod(method); // 메소드 체크
}
catch (ClassNotFoundException e)
{
throw new RouteParseException(contErr);
}
catch (InstantiationException e)
{
throw new RouteParseException(contErr);
}
catch (IllegalAccessException e)
{
throw new RouteParseException(contErr);
}
catch (NoSuchMethodException e)
{
throw new RouteParseException(methodErr);
}
catch (SecurityException e)
{
throw new RouteParseException(methodErr);
}
return true;
}
}