Jdk14 Conversion

From JCFWiKi

Jump to: navigation, search

그림:check.gif

  • 산출물: JCF 라이브러리 및 공통모듈 jdk1.4로 다운그레이드하기
  • 작성자: 서경진
  • 최초작성일 : 2008/07/03
  • 최종작성일 : 2008/07/03

Copyright © 2008 Daewoo Information Systems Co., Ltd.

그림:information.gif

  • 이 문서는 Java 1.4환경에서 JCF Framework와 공통모듈을 사용하기 위한 Tip을 제공한다.

목차

[편집] JCF 라이브러리 jdk1.4로 다운그레이드하기

JCF는 Java1.5를 기반으로 개발되었지만, MCI (Multi-Channel Interface)의 jcf.web.RequestContextHolder 클래스에서 사용하는 java.lang.ThreadLocal.remove() (rt.jar) 함수가 1.5 이상에서만 지원되는 것을 제외하면 java 1.4 환경에서의 구동이 가능하다. java1.4 환경에서 안정적으로 JCF를 기반으로 어플리케이션을 개발하기 위해서는 소스의 수정없이 Retrotranslator를 활용하여 java1.5로 컴파일된 JCF 라이브러리를 java1.4로 변환하면 된다.

[편집] Retrotranslator 1.2.7를 활용하여 java1.4로 변환하기

  • Retrotranslator와 JCF 라이브러리를 다운받아 아래와 같이 같은 디렉터리에 복사한다.
디렉터리 구조
디렉터리 구조
  • DOS Command를 통해 다음과 같은 명령을 실행한다.
java -jar retrotranslator-transformer-1.2.7.jar -advanced -srcjar jcf-3.0.1-SNAPSHOT.jar -destjar jcf-3.0.1-SNAPSHOT-jdk14.jar
java -jar retrotranslator-transformer-1.2.7.jar -advanced -srcjar jcf-ibatis-sqlmap-3.0.1-SNAPSHOT.jar -destjar jcf-ibatis-sqlmap-3.0.1-SNAPSHOT-jdk14.jar
  • 다음은 JCF 라이브러리가 Retrotranslator를 통해 java1.4용으로 변환된 결과이다.
변환 명령실행 결과
변환 명령실행 결과
  • 위의 과정을 통해 동일 디렉터리에 jcf-3.0.1-SNAPSHOT-jdk14.jar와 jcf-ibatis-sqlmap-3.0.1-SNAPSHOT-jdk14.jar 두 개의 라이브러리가 생성된다.
  • java1.4 환경에서 JCF 기반의 어플리케이션을 개발할 경우, 기존에 있는 java1.5용 JCF 라이브러리를 제거하고 생성된 두 개의 라이브러리를 buildpath에 설정하여 java1.4로 컴파일하면 어플리케이션이 정상적으로 구동할 것이다.

[편집] JCF 공통모듈 jdk1.4로 다운그레이드하기

[편집] JCF 공통모듈의 메뉴관리가 참조하는 Tree.jar 라이브러리 다운그레이드하기

  • JCF 공통모듈에는 메뉴관리 모듈이 있는데, 메뉴관리는 Tree형 데이터 구조를 활용하기 위해 sourceforge에 공시된 Tree.jar라는 open source 라이브러리를 활용한다.
  • Tree.jar는 다음 소스와 같이 java1.5 스팩인 jre1.5 이상에 포함된 rt.jar의 java.lang.Iterable과 GenericType <>을 사용한다.
  • 따라서 java1.4 환경에서는 구동이 불가능하다. (클래스를 찾을 수 없는 에러 발생)
  • 다음은 java1.5로 구현된 소스의 예제이다.
public interface Tree<T> extends Iterable<T>, Serializable
{
	public abstract TreeRoot<T> getRoot();
	public abstract Iterator<T> iterator();
	public abstract Iterator<TreeNode<T>> nodeIterator();
	public abstract List<T> getBreadthFirstList();
	public abstract List<TreeNode<T>> getBreadthFirstNodeList();
	public abstract List<T> getDepthFirstList();
	public abstract List<TreeNode<T>> getDepthFirstNodeList();
	public abstract List<T> getList();
	public abstract List<TreeNode<T>> getNodeList();
	public abstract int size();
	public abstract int depth();
}
public class ArrayTree<T> implements Tree<T>
{
	private static final long serialVersionUID = 7161315168915445688L;
	private TreeRoot<T> root;
	private final List<List<TreeNode<T>>> levels = new ArrayList<List<TreeNode<T>>>();
	
	public ArrayTree()
	{
		this(null);
	}
 
	public ArrayTree(final T element)
	{
		super();
		this.root = new ArrayTreeRoot<T>(this);
		this.root.setElement(element);
		this.saveNode(this.root, 0);
	}
 
	private void addLevel(final TreeNode<T> node) {
		List<TreeNode<T>> level = new ArrayList<TreeNode<T>>();
		level.add(node);
		this.levels.add(level);
	}
	
	protected void saveNode(final TreeNode<T> node, final int depth) {
		if (depth >= this.levels.size()) {
			this.addLevel(node);
		}
		else {
			this.levels.get(depth).add(node);
		}
	}
 
	protected void removeNode(final TreeNode<T> node, final int depth) {
		if (depth < this.levels.size()) {
			this.levels.get(depth).remove(node);
		}
	}
 
	protected List<TreeNode<T>> getNodes(final int depth) {
		if (depth < this.levels.size()) {
			return this.levels.get(depth);
		}
		
		return null;
	}
	
	public TreeRoot<T> getRoot()
	{
		return this.root;
	}
 
	public Iterator<T> iterator()
	{
		return this.getDepthFirstList().iterator();
	}
 
	public Iterator<TreeNode<T>> nodeIterator()
	{
		return this.getBreadthFirstNodeList().iterator();
	}
 
	public List<T> getBreadthFirstList()
	{
		final List<TreeNode<T>> nodes = this.getBreadthFirstNodeList();
		final List<T> elements = new ArrayList<T>(nodes.size());
		for (final TreeNode<T> node : nodes)
		{
			elements.add(node.getElement());
		}
		
		return Collections.unmodifiableList(elements);
	}
 
	public List<TreeNode<T>> getBreadthFirstNodeList()
	{
		final List<TreeNode<T>> nodes = new LinkedList<TreeNode<T>>();
		for (List<TreeNode<T>> level : this.levels) {
			nodes.addAll(level);
		}
		
		return Collections.unmodifiableList(nodes);
	}
 
	public List<T> getDepthFirstList()
	{
		final List<TreeNode<T>> nodes = this.getDepthFirstNodeList();
		final List<T> elements = new ArrayList<T>(nodes.size());
		for (final TreeNode<T> node : nodes)
		{
			elements.add(node.getElement());
		}
		
		return Collections.unmodifiableList(elements);
	}
 
	public List<TreeNode<T>> getDepthFirstNodeList()
	{
		final List<TreeNode<T>> nodes = new LinkedList<TreeNode<T>>();
		this.addDepthFirst(nodes, this.root);
		
		return Collections.unmodifiableList(nodes);
	}
 
	private void addDepthFirst(final List<TreeNode<T>> nodes, final TreeNode<T> node)
	{
		nodes.add(node);
		for (final TreeNode<T> child : node.getChildren())
		{
			this.addDepthFirst(nodes, child);
		}
	}
 
	public int depth()
	{
		return this.levels.size() - 1;
	}
 
	public int size()
	{
		int size = 0;
		for (List<TreeNode<T>> level : this.levels) {
			size += level.size();
		}
		
		return size;
	}
 
	public List<T> getList()
	{
		return this.getBreadthFirstList();
	}
 
	public List<TreeNode<T>> getNodeList()
	{
		return this.getBreadthFirstNodeList();
	}
}
  • Tree.jar를 java1.4 환경에서 활용하기 위해서 소스코드를 java1.4 스팩에 맞도록 수정하였다.
  • Iterable 클래스와 GenericType <>은 사용하지 않도록 모두 제거하였고 T와 같이 Type이 선언된 부분은 Object로 변경하였다.
  • java1.5용 for문을 java1.4에 맞도록 수정하였다.
interface Tree extends Serializable
{
	public abstract TreeRoot getRoot();
	public abstract Iterator iterator();
	public abstract Iterator nodeIterator();
	public abstract List getBreadthFirstList();
	public abstract List getBreadthFirstNodeList();
	public abstract List getDepthFirstList();
	public abstract List getDepthFirstNodeList();
	public abstract List getList();
	public abstract List getNodeList();
	public abstract int size();
	public abstract int depth();
}
public class ArrayTree implements Tree
{
	private static final long serialVersionUID = 7161315168915445688L;
	private TreeRoot root;
	private final List levels = new ArrayList();
 
	public ArrayTree()
	{
		this(null);
	}
 
	public ArrayTree(final Object element)
	{
		super();
		this.root = new ArrayTreeRoot(this);
		this.root.setElement(element);
		this.saveNode(this.root, 0);
	}
 
	private void addLevel(final TreeNode node) {
		List level = new ArrayList();
		level.add(node);
		this.levels.add(level);
	}
 
	protected void saveNode(final TreeNode node, final int depth) {
		if (depth >= this.levels.size()) {
			this.addLevel(node);
		}
		else {
			((ArrayList) this.levels.get(depth)).add(node);
		}
	}
 
	protected void removeNode(final TreeNode node, final int depth) {
		if (depth < this.levels.size()) {
			((ArrayList) this.levels.get(depth)).remove(node);
		}
	}
 
	protected List getNodes(final int depth) {
		if (depth < this.levels.size()) {
			return (List) this.levels.get(depth);
		}
 
		return null;
	}
 
	public TreeRoot getRoot()
	{
		return this.root;
	}
 
	public Iterator iterator()
	{
		return this.getDepthFirstList().iterator();
	}
 
	public Iterator nodeIterator()
	{
		return this.getBreadthFirstNodeList().iterator();
	}
 
	public List getBreadthFirstList()
	{
		final List nodes = this.getBreadthFirstNodeList();
		final List elements = new ArrayList(nodes.size());
		for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
			TreeNode node = (TreeNode) iterator.next();
			elements.add(node.getElement());
		}
 
		return Collections.unmodifiableList(elements);
	}
 
	public List getBreadthFirstNodeList()
	{
		final List nodes = new LinkedList();
		for (Iterator iterator = this.levels.iterator(); iterator.hasNext();) {
			List level = (List) iterator.next();
			nodes.addAll(level);
		}
 
		return Collections.unmodifiableList(nodes);
	}
 
	public List getDepthFirstList()
	{
		final List nodes = this.getDepthFirstNodeList();
		final List elements = new ArrayList(nodes.size());
		for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
			TreeNode node = (TreeNode) iterator.next();
			elements.add(node.getElement());
		}
 
		return Collections.unmodifiableList(elements);
	}
 
	public List getDepthFirstNodeList()
	{
		final List nodes = new LinkedList();
		this.addDepthFirst(nodes, this.root);
 
		return Collections.unmodifiableList(nodes);
	}
 
	private void addDepthFirst(final List nodes, final TreeNode node)
	{
		nodes.add(node);
		for (Iterator iterator = node.getChildren().iterator(); iterator.hasNext();) {
			TreeNode child = (TreeNode) iterator.next();
			this.addDepthFirst(nodes, child);
		}
	}
 
	public int depth()
	{
		return this.levels.size() - 1;
	}
 
	public int size()
	{
		int size = 0;
		for (Iterator iterator = this.levels.iterator(); iterator.hasNext();) {
			List level = (List) iterator.next();
			size += level.size();
		}
 
		return size;
	}
 
	public List getList()
	{
		return this.getBreadthFirstList();
	}
 
	public List getNodeList()
	{
		return this.getBreadthFirstNodeList();
	}
}
  • 소스 수정이 끝나고 j2sdk1.4.2_17과 jre1.4.2_17로 컴파일을 한 후, Tree-1.0-jdk14.jar로 패키징하였다.
  • 패키징된 Tree-1.0-jdk14.jar 라이브러리는 Maven 저장소에 Artifact로 디플로이하여 Maven을 통한 활용이 가능하다.
Maven 저장소에 Artifact로 디플로이된 Tree-1.0-jdk14.jar 라이브러리
Maven 저장소에 Artifact로 디플로이된 Tree-1.0-jdk14.jar 라이브러리
  • Tree-1.0-jdk14.jar를 Maven에서 적용하기 위한 pom.xml
------ ARTIFACT EFFECTIVE METADATA BEGIN ------
<groupId>Tree</groupId>
<artifactId>Tree</artifactId>
<version>1.0</version>
------- ARTIFACT EFFECTIVE METADATA END -------
 
<?xml version="1.0" encoding="UTF-8"?><project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>Tree</groupId>
  <artifactId>Tree</artifactId>
  <version>1.0</version>
  <description>Auto generated POM</description>
</project>

[편집] 메뉴관리 모듈 다운그레이드하기

  • Java 개발환경을 jdk 및 jre를 1.4.2._17로 변경한다.
  • buildpath에 있는 Tree.jar를 Tree-1.0-jdk14.jar로 변경한다.
  • 메뉴모듈에 적용된 GenericType <>은 사용하지 않도록 모두 제거한다.
  • GenericType으로 설정된 부분은 Casting(Type명)으로 형변환 에러를 방지한다.
  • java1.5용 for문을 java1.4에서 사용할 수 있도록 수정한다.
  • Java1.4로 컴파일한다.