부제 : System Clipboard는 멋지지만 멋지지 않다.


부제가 섹시하다.


오늘은 OS의 System Clipboard를 자바스크립트로 다룰때의 몇가지 이슈에 대해 정리하고자 한다.


브라우저는 OS의 System Clipboard를 Access하기 위한 방법으로 clipboardData 개체를 지원한다.



clipboardData(DataTransfer) 개체

documentation

개요

clipboardData개체는 기본적으로 read-only 개체이며 DataTransfer interface의 구현체이다.


IE의 경우 window개체를 통해 window.clipboardData로 접근이 가능하며

다른 브라우저의 경우 copy, cut, paste 이벤트 리스너에 전달되는 event 개체의 clipboardData 속성으로 접근이 가능하다.


제공하는 메소드

setData(format, data)

clipboardData개체의 값을 설정하는 함수이다.

format은 mime-type이며 text 타입과 url타입을 지정할 수 있다.

data는 text의 경우 일반 text와 blob(@see HTML5의 File API 관련)데이터를 지정할 수 있다.

return value는 성공/실패값으로 boolean 값을 반환한다.


getData(format)

clipboardData개체의 값을 얻어오는 함수이다.

format은 setData와 같으며 정상적으로 동작시 클립보드에 저장되어 있는 데이터값이 반환된다.


clearData(format)

clipboardData개체의 값을 지우는 함수이다.

format은 test, url, file, html, image를 지정할 수 있다.




대충,,, 간단한 설명은 이쯤하고 자세한건 위의 documentation을 참고하는 걸로 한다.



테스트하려는 이슈는 다음과 같다.

  • 시스템 클립보드의 setData, getData를 이용하여 복사/붙여넣기 기능을 구현하고 싶다.
    1. 단축키(Ctrl+c,x,v)와 브라우저 contextmenu를 통한 방법
    2. 특정한 UI를 제공(복사/잘라내기/붙여넣기 버튼) 하는 방법



단축키(Ctrl+c,x,v)와 브라우저 contextmenu를 통한 방법

  1. document.body 또는 원하는 element에 copy, cut, paste 이벤트 리스너를 할당 한다.
  2. 이벤트 리스너 함수에서 event개체의 clipboardData 또는 window.clipboardData개체에 접근하여 제공되는 메소드를 통해 데이터를 설정하거나 얻어온다.
  3. 이렇게 설정하거나 값을 얻어와 복사/잘라내기/붙여넣기 기능을 구현할 수 있다.
  4. github source 참고 (테스트한 소스이며 간단히 clipboardData와 execCommand만 테스트)
테스트 해본 결과로는 별다른 문제가 없다.
단축키나 컨텍스트 메뉴를 통한 방식은 매우 깔끔하며 딱히 문제될 만한 부분이 없다.
(다만,,, 실제 크로스브라우징 처리를 하며 이 기능 개발을 하려면 당연히 고민해야 될 부분은 많다. 특히 IE 버전별 처리...)




특정한 UI를 제공(복사/잘라내기/붙여넣기 버튼) 하는 방법 (execCommand를 이용)

  1. 준비
    1. 임의의 iframe을 생성해 놓는다.(copy,cut,paste를 수행할 document)
    2. document.body의 contenteditable 속성을 true로 설정한다.
  2. copy, cut, paste 등의 button element를 만들어 mouse click 이벤트 리스너를 할당한다.
  3. copy or cut
    1. copy or cut 버튼의 mouse click 이벤트 리스너 함수에서 복사하거나 붙여넣기할 값을 iframe의 document.body에 innerHTML로 설정한다.
    2. 이벤트 리스너 함수에서 iframe의 document.execCommand('copy' or 'cut')를 사용하여 강제로 clipboard 액션을 트리거한다.
      1. 이때 복사하고자 설정한 iframe document.body의 값이 시스템 클립보드에 복사된다.
  4. paste
    1. paste 버튼의 mouse click 이벤트 리스너 함수에서 iframe의 document.execCommand('paste')를 사용하여 강제로 clipboard 액션 트리거한다.
      1. 이때 시스템 클립보드에 있는 값이 iframe의 document.body에 붙여넣어 진다.
    2. iframe의 document.body에 붙여넣어진 값을 가져온다.(innerHTML)
      1. 이 값을 붙여넣기 기능에 사용할 수 있다.
  5. 이렇게 설정하거나 값을 얻어와 복사/잘라내기/붙여넣기 기능을 구현할 수 있다.
  6. github source 참고 (테스트한 소스이며 간단히 clipboardData와 execCommand만 테스트)

바이너리 데이타인 이미지등을 복사/붙여넣기 하는 방법은 조금 다르다.
그 부분은 다음 기회에 따로 포스팅.


테스트 해본 결과로는 일단 브라우저별로 동작이 다르다.
이 부분이 문제이다.

Internet Explorer (가능)
  • execCommand를 호출하면 브라우저 자체에서 보안 프롬프트를 띄워 사용자에게 이 액션을 허용할 것인지를 묻는다.
  • 허용하게 되면 해당 웹페이지가 새로고침될때까지 다시 보안 프롬프트를 띄우지 않으며 execCommand가 제약 없이 실행된다.
    • copy, cut, paste 모두 동일
Chrome (불가능)
  • execCommand를 통한 copy, cut은 IE와 동일하게 잘 동작한다.
    • IE와 같이 보안 프롬프트 메시지는 뜨지 않는다.
    • Chrome 42+ version 부터 지원한다.
  • execCommand를 통한 paste는 동작하지 않는다.
    • 아예 동작하지 않으며 크롬 documentation에는 보안상 이유로 지원하지 않는다고 나와있다.
FireFox (불가능)
  • execCommand를 통해서는 copy, cut, paste 모두 보안상의 이유로 강제 트리거는 불가능하다.
Opera, Safari (모름)
  • 안해봄...



결론
위의 테스트가 완벽하다고 할 순 없으나 적당한 시간을 투자하여 나온 결론은
크롬이나 파이어폭스 브라우저에서 execCommand의 지원 한계로 인해 커스텀한 UI를 만들어 시스템 클립보드에 접근할 수 있는 방법은 찾지 못하였다.
popular한 웹에디터나 웹오피스들을 살펴보아도 위와 같이 IE에서는 시스템 클립보드를 이용한 복사/잘라내기/붙여넣기 기능을 제공한다.
물론, 단축키를 이용한 방식은 모든 브라우저에서 잘 동작한다.

etc...
그런데 Google Docs는 지원한다....OTL...
과연 API에도 지원안한다고 했는데 어떻게 했을까 싶어서 디버깅도 해보고 별짓을 다해봤지만 방법을 찾을 수 없었다...

오늘도 뭔가 멋진걸 되게하는 포스팅이 아닌 안되는걸 증명하는 포스팅이 되어버린 느낌적인 느낌에 기분이 좋지만은 않다 ..










이 내용은 지극히 경험적인 내용을 정리한 것입니다.

잘못된 내용이 있거나 문제가 될만한 부분이 있다면 댓글 또는 페이스북(https://www.facebook.com/vamalboro)으로 연락주시면 당장! 고치도록 하겠습니다.

저작자 표시 비영리 변경 금지
신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

Euclidean Distance

사용자 삽입 이미지

위 공식은 유클리드라는 사람이 만든 N차원에서의 두 점간의 거리를 구하는 공식이다.

재미있는 문제를 풀어보다 이 공식으로 문제를 풀어야 해서 찾아보았고 역시나.

기초 수학이 부족해 루트부터 다시 개념잡고 공부!

일단 p와 q는 점을 나타낸다.

p1, q1은 각 점들의 좌표다. 예를 들어 2차원공간에서의 좌표를 나타낼때

우리는 보통 x, y로 좌표를 표현하는데 이 것을 위의 공식으로 나타내면

첫번째 점의 x, y좌표는 p1, p2로 나타낼수 있고, 두번째 점의 x, y좌표는 q1, q2로 나타낼 수 있다.

3차원이라면 x, y, z, p1, p2, p3이다.

2차원을 예로 들어 보자.

첫번째 점 p의 좌표는 (x=3, y=4)이고 두번째 점 q의 좌표가(x=2, y=11)이라고 할때 위의 공식으로 식을 만들어 풀어보면 아래와 같다.

1. 루트 ( (3 - 2)^2 + (4 - 11)^2 )
2. 루트 ( 1 + -7^2)
3. 루트 ( 1 + 49 )
4.  7.0710...


이 공식은 2차원 공간에서 1사분면뿐 아니라 4사분면으로 나누어진 2차원공간에서도 유효하다.

내 친구이자 나의 프로그래밍 스승인 쏭겐님께서 피타고라스의 정리를 이용해서 설명을 해주는데.

참 그넘 잘한다.ㅎㅎ

어쨌든 친구 덕분에 더욱 확고히 이해할 수 있었고 까먹기도 쉽지 않을정도가 되었다. (땡큐)


이대로 그냥 끝내면 재미없으니까 자바스크립트로 예제 코드를 한번 짜 보았다.

------------------------------------------------------------------------------------------------
function Point(x, y) {
	this.x = x || 0;
	this.y = y || 0;
}
Point.prototype.equals = function(point) {
	if (!point || point.constructor != Point) {
		return false;
	}
	
	return this.x === point.x && this.y === point.y;
}
Point.prototype.xPoint = function(x) {
	if (typeof x == "undefined") {
		return this.x;
	} else {
		this.x = x;
	}
}
Point.prototype.yPoint = function(y) {
	if (typeof y == "undefined") {
		return this.y;
	} else {
		this.y = y;
	}
}

먼저 위와 같은 2차원상에서의 좌표를 나타내는 객체를 하나 정의하고 이를 이용해 2차원상에서의

두 점간의 거리를 구하는 유클리디안 함수를 만들어 보면 아래와 같다.


function EuclideanDistance(point1, point2) {	
	return point1.equals(point2) ? 0 : 
		Math.sqrt(
			Math.abs(
				Math.pow(point1.xPoint() - point2.xPoint(), 2) +
				Math.pow(point1.yPoint() - point2.yPoint(), 2))
		);
}


신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

Google Closure Tools라는게 오픈소스로 나왔다.

오~~~~ 멋지다.와와와~

우리팀 모선임님께서 친히 svn 레포지토리에서 다운로드 받아서 테스트 개발서버에 배포까지 해주셨다.

난 그냥 편하게 데모 구경.

뭐 소감으로 말하자면 괜찮다.

아직 코드는 자세히 보진 못했는데 개인적으로 블로그에 포스팅좀 하면서 공부좀 해야겠다.

이유는!

먼가 멋져보여서 Google에서 만든거라니 한번 보고 싶은 마음.

오픈소스공부를 제대로 해본적이 한번도 없는데 관심이 생기는 이참에 한번 분석해보자는 마음.

그리고 현재 자바스크립트를 80%이상 사용하며 프로젝트를 수행중이므로 ~ ㅋㅋ


일단, Google Closure Tools라는게 도대체 무엇인지 알기 위해 나름 번역페이지 띄워 놓고 봤지만..

역시 이해는 30%...

결국 검색을 하다보니 간단하지만 설명이 잘 되어 있는 포스트를 발견!*_*

Google Closure Tools란?  <- 요기요기~

난 Compiler와 Templates는 일단 제쳐놓고 Library에 대해 급 관심이 가기 시작.

일단 안되는 영어라도 현재는 번역으로 잘 알려주는 책이 있는 것도 아니고 어쩔 수 없이 직접 사이트를 뒤적이는 수 밖에 방법이 없다.


일단 Google Closure Library 링크를 따라가보면 화면 오른쪽에 "How do I start?" 라고 쓰여 있는 곳을 보자.

목록에 보면 아래와 같이 쓰여있다. 옆에는 친절한 나의 설명.

  • Download Closure. - 소스코드 다운로드가 120%맞습니다.
  • Read Finding Your Way around Closure. - Closure Library의 규칙과 코드베이스에 대해 설명한다.
  • Do the Closure Hello World exercise. - 다른거 볼 필요없이 Hello World나오면 무조건 연습 튜토리얼임.
  • Work through the Building an Application with the Closure Library tutorial. - 이것두 튜토리얼.
  • Explore the project's source code. - 뭐 API문서나 Issue, 등을 볼 수 있는 Closure Library 프로젝트 홈인듯 하다.(웹에서 소스도 직접 볼 수 있다.)



소스를 다운로드 받자(이클립스같은 IDE를 사용하면 편하다.SVN 플러그인 제공한다.)

소스를 모두 다운로드 받았으면 (이클립스의 경우[java] Dynamic Web Project를 구성해 소스를 위치시키고)

/closure/goog/demos/index.html을 실행시키면 데모를 볼 수 있다.



신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

Transaction 이란.
  : 컴퓨터 프로그램에서 트랜잭션의 일반적인 의미는 정보의 교환이나 데이터베이스 갱신 등
    연관되는 작업들에 대한 일련의 연속을 의미한다. (http://www.terms.co.kr/transaction.htm)

이번 프로젝트에 ORM이 무엇인지도 처음 들었고 또한 ORM프레임워크중에 한 종류인 Hibernate또한
처음 사용해보면서 느꼈던 점은 ..

어렵다 이다.-_-; 마냥 어려운거임.

뭐 어찌됐든 프로그래머로써 Transaction을 무시할 수 있는 프로그래머는 없을터.

프로젝트를 진행하던 도중 org.hibernate.TransactionException: Transaction not successfully started의

예외상황이 자꾸 발생하길래 디버깅 고고.

(사실은 무시하려했지만 심각 :
 Servlet.service() for servlet default threw exception이라는 메세지만 내가 보지 못했더라면...ㅋㅋ)

현재 MVC 프레임워크로 Struts2를 사용하고 있는데 이 에러가 나는 페이지들을 검사해 보았더니

Action이 Chain으로 묶여있는(연쇄호출되는) 요청들은 다 이 예외를 뱉어내고 있었다.

트랜잭션 begin -> 커밋 or 롤백 -> 트랜잭션 close의 정상적인 과정이 아닌 중간에 커밋하지 않고 begin을 두번 수행하는걸 발견 (커밋이 두번이였던가.-_-;; 뭐어쨌든 발견했다는게 중요한거 아니겠음?)

현재 트랜잭션의 코딩 패턴은 OSIV패턴(Open session in view)으로 구현되어있었고.
(최범균저 (Hibernate3 프로그래밍) 책에 나와있는 패턴)

책에는 Servlet Filter로 구현되어있었지만 현재 프로젝트에선 Interceptor로 구현.

정확하고 자세한 건 Struts2의 Interceptor의 아키텍쳐를 다시 한번 봐야겠지만

Chain으로 또 다른 Action을 수행할때에 다시 한번 Interceptor를 타기때문에 commit하기도 전에 또다시

Transaction을 begin하는것 같았다.

결국 Interceptor로 구현되어있는 Transaction처리 로직을 Servlet Filter로 재구현해서 테스트해서

다행히 이 문제를 해결.

(또 나면 어쩌지?ㅠㅠ)




이 포스팅을 100% 전적으로 믿지 마세요.(나중에 또 이상황이 발생했을때 참고하려고 적는 글입니다.)







신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

Out Of Memory

language/java 2009.06.12 20:49
이클립스로 웹프로젝트 개발을 하다보면 사용하는 클래스의 양이 늘어남에 따라 간간히 PermGen Space라는 메세지와 함께 Out Of Memory Error가 뜨면서 서버가 다운되는 경우가 있다.

그동안은 그냥 서버를 재시작하면서 개발을 해왔지만 이번프로젝트에서는 위 상황이 상당히 많이 발생하여서

검색해보니 PermGen이란 Permanent generation이라는 JVM의 메모리영역이며 이 메모리영역에 클래스의 정보가 로드되어진다고 나와있다.

대략 계산해보니 이번프로젝트에 쓰이는 클래스파일이 대략 3500개정도 되는데 아마도 자주 발생한 이유가
Permanent 영역을 기본으로 잡아주어서 그런것같다.

그러다 검수를 앞두고 이번엔 java heap space 메세지의 Out Of Memory Error가 발생..

보안테스트 도중 발생하였는데 테스트를 직접 고객사 담당자가 해서 통보받았으니 정말 진땀이 나던 상황이었다.

일단 이 문제를 해결하기 위해 검색을 하던도중. 지금까지 내가 발로 개발을 했구나 라는 생각이 스물스물...

그냥 저냥 돌아가기만 하면 되지. 라는 생각으로 만들었던 생각이 들며 나 자신에게 참 부끄러운 하루였다.

또한 자바에 대한 조금의 지식을 더 얻고 이해하는 시간이기도..

일단 서론은 여기에서 접고.

난 문제점이 Memory Error이기때문에 프로그램의 실행중 JVM영역의 메모리상태를 프로파일링하고자 이리저리 검색하던도중 블로그를 운영하시는 어떤 개발자분의 http://www.tuning-java.com/248  게시물에서 좋은 정보를 얻었다.

jdk\bin\jvisualvm.exe 라는 파일인데 실행중인 모든 JVM을 모니터링 하는 프로그램이다.

이번개발은 JDK6 버젼으로 하고있어서 기본으로 들어있다.

일단 이 프로그램(Java VisualVM)을 실행시킨후 톰캣을 실행.

Java VisualVM 에서 톰캣이 실행이되면 알아서 톰캣을 실행하는 JVM을 catch~

catch된 JVM을 오른쪽버튼 OPEN한다.

아래 그림과 같이 나온다.


위는 현재 내가 검사하고 있는 화면이라 초기화면이랑은 조금 틀리지만 현재 실행중인 톰캣의 JVM의 상태를 확인할 수 있다.

OverView는 여러가지 환경정보들이 있다. JVM arguments, System properties등등..

다음으로 Monitor탭을 보자.



현재 JVM 의 Heap영역의 상태를 보여주고 있다.

위 그림을 보면 현재 약 3시간이 넘게 톰캣을 실행중이며 시간대별로 Heap영역의 메모리점유율 상태를

그래프와 수치로 보여준다. 또한 우상단에 Heap Dump버튼을 클릭하면 클릭하는 시점의 Heap영역의 메모리점유율 덤프가 생성된다.(객체의 instance갯수, 현재 차지하고 있는 메모리용량(%, 수치) 를 볼 수 있다.

덤프된 화면은 아래와같다.


이것을 보고 문제점이 무엇인지 대략 유추할 수 있었고.

몇시간의 테스트끝에 99% 확실한 문제점을 찾아낼 수 있었다.

개발을 하면서 간과했던점이 웹어플리케이션 전체에서 코드값을 사용하는데 이값을 어플리케이션 속성에 담아놓고 쓰지 않고 세션에 담아서 쓰고 있었다.

세션은 웹페이지를 요청하는 사용자 한명당(요청수가아니다.) 한개식 생성이되며 현재 session timeout 시간은 7일이다.......-_-

스트레스툴로 여러번의 XSS공격과 SQL Injection공격등등을 하며 테스트를 하는걸 상상해보면 계속해서 쌓여가는 세션때문에 결국엔 메모리의 한계가와 Out Of Memory를 토해내는 것이었더랬지..

뭐 톰캣의 JVM Heap메모리 설정을 기본으로 잡고 했던것도 문제점이긴하다.

일단 해결법은 JVM 메모리영역을 늘려주고 Session TimeOut시간을 30분에서 1시간정도를 잡아주면 될것같다.

다음부턴 절대 세션에 코드값을 담는 일은 하지 않도록 다짐하면서..



2009년 6월 더운 초여름날 두달째 야근을 하며 폐인의 모습으로







아참!오픈소스 스트레스툴로 Jmeter라는것도 있다. (좋드만 ㅋ)
저작자 표시 비영리 변경 금지
신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

얼마전 nhn에서 스마트베이직에디터를 오픈소스로 발표해서 한번 써봤는데.

깔끔하고 심플하고 뭐 나쁘진 않았다.

다른분들처럼 API사용하여 플러그인만들어서 기능추가도 해보고 싶지만..

일단 자바스크립트에서 좀 딸리고.

혼자 공부삼아 하는게 아니라 프로젝트에 반영해야되서 다른걸 찾다가 보니. (시간이 없다능..변명변명변명;;)

FCKeditor라는걸 찾게되었다. (많은 분들이 쓰시는듯하다. 나만 몰랐던건가.-_-)

나중에 또 써먹기위해.. 그리고 검색하여 이블로그를 찾아주신 분들에게 조금이라도 보답하기위해

간단히 사용법을 적는다.

http://www.fckeditor.net/

사이트 접속 후 데모페이지도 볼 수 있다.

우상단에 보면 Download 메뉴가 있다.

Download 페이지 하단에 FCKeditor.Java에 "Click here to download the latest version" 를 클릭.

이동하는 화면에서 보면 버젼별로 다운로드 받을 수 있다.

현재 가장 최신버젼(2.4.1 - 2008-10-14)인  fckeditor-java-demo-2.4.1.war파일을 다운로드 받는다.

톰캣루트의 webapp폴더에 파일을 이동한 후 톰캣을 가동시키면 자동으로 파일이 압축해제되면서 데모사이트가 가동된다.

http://localhost/컨텍스트로 접속하면

샘플페이지를 볼 수 있다.

현재 테스트하는 나의 개발환경은 다음과 같다.

WAS : apache-tomcat-6.0.18
Charset : UTF-8

jsp폴더안에 샘플페이지들이 있으니 참고하여 자신의 상황에 맞게 커스터마이징하여 사용하면된다.

이 샘플페이지의 코드를 이용하여 간단히 에디터를 불러오는 소스를 만들어보면 아래와 같다.



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="net.fckeditor.*" %>
<%@ taglib uri="http://java.fckeditor.net" prefix="FCK" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow" />
<title>FCKeditor Example</title>
<link rel="shortcut icon" href="fckeditor.gif" type="image/x-icon" />
<script type="text/javascript">
    function FCKeditor_OnComplete(editorInstance) {
        window.status = editorInstance.Description;
    }
    function sendForm(frm) {
        var oEditor = FCKeditorAPI.GetInstance('content');
        var div = document.createElement("DIV");

        div.innerHTML = oEditor.GetXHTML();
        if (isNull(div.innerHTML)) {
            alert("내용을 입력하세요.");
            oEditor.Focus();
            return false;
        }
        return true;
    }
    function isNull(text) {
        if (text == null)
            return true;
        var result = text.replace(/(^\s*)|(\s*$)/g, "");
        if (result)
            return false;
        else
            return true;
    }
</script>
</head>
<body>
<ul>
    <li><FCK:check command="CompatibleBrowser" /></li>
    <li><FCK:check command="FileBrowsing" /></li>
    <li><FCK:check command="FileUpload" /></li>
</ul>
<form name="frmFckEditor" action="sampleposteddata.jsp" method="post" onsubmit="return sendForm(this)">
<FCK:editor instanceName="content" toolbarSet="MyToolbar" width="750" height="350">
    <jsp:body>
        <FCK:config SkinPath="skins/silver/"/>
    </jsp:body>
</FCK:editor>
<br />
<input type="submit" value="Submit" /></form>
</body>
</html>


  1. <FCK:editor> 태그는 editor를 로딩하는 태그이다. instanceName은 HTML Element의 name속성으로 생각하고 원하는 이름을 설정하여 준다. 위는 content이다. toolbarSet속성은 MyToolbar라는 이름으로 커스터마이징한 툴바이름을 설정해 주었다. 넓이와 높이도 px단위로 설정해 주었다.
    1. 원하는 툴바설정은 fckeditor/fckconfig.js파일을 열어 FCKConfig.ToolbarSets["Default"]라고 되있는 부분을 먼저 찾는다. 기본설정이므로 삭제하지말고 복사한후 이름을 MyToolbar로 정한후 JSON형식으로 정의된 툴바들을 원하는 대로 정의한다.(자세한 내용은 사이트를 참조).
    2. 그외의 폰트, 사이즈, 업로드 등등 여러가지 설정을 할 수 있다.
  2. <FCK:config>태그안의 SkinPath속성은 총 3가지의 스킨중 실버스킨을 적용한 것이다.
  3. form의 action의 sampleposteddata.jsp파일은 jsp폴더안에 존재한다. 자신의 경로에 맞게 설정을 해주면 되며(아니면 샘플페이지를 jsp폴더로 이동) 폼으로 전송한 editor의 내용값을 확인할 수 있다.
    한글은 깨지니 sampleposteddata.jsp파일을 열어 상단에 request.setCharacterEncoding("UTF-8");를 추가하여 준다. EUC-KR환경이라면 EUC-KR로 변경.

이로서 기본적으로 editor의 설정은 해보았지만. 이미지 업로드 같은 경우 한글이미지는 깨지게 된다.

한글이미지를 업로드 하려면 WEB-INF/lib/에 있는 java-core-2.4.1.jar파일안에 있는 소스를 직접수정하여야 한다. (수정을 하지 않고도 하는 방법을 아시는 분은 댓글좀 남겨주세요.ㅠㅋ )

fckeditor download사이트로 가서 fckeditor-java-2.4.1-src.zip를 다운받으면 소스코드가 있다.

변경할 소스는 net.fckeditor.connector.ConnectorServlet파일에 243라인에
ServletFileUpload upload = new ServletFileUpload(factory); 이 부분이 있다.
이 밑에 upload.setHeaderEncoding("UTF-8");를 추가한다.(자신의 환경에 맞는 Charset으로)
그리고 이미지업로드를 해보면 한글파일이 깨지지 않고 업로드가 정상적으로 된다.

대략적인 사용방법 끝.

아. 블로그에 글쓰기 힘들다...


저작자 표시 비영리 변경 금지
신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

<?php
$currentPage = $_REQUEST["page"];
if(!$currentPage) $currentPage = 1;

$totalRecord = 151;  // 전체 레코드수
$recordPerPage = 10; // 페이지 당 뿌릴 레코드 수
$pagePerBlock = 10; // [1] ~ [10] 까지 한번에 10개씩

function handlePage($totalRecord,$recordPerPage,$pagePerBlock,$currentPage){ // 전체레코드,  페이지당 레코드수(10) , 블럭당페이지수(10), 현재페이지

    $totalNumOfPage = ceil($totalRecord/$recordPerPage); //16page
    $totalNumOfBlock = ceil($totalNumOfPage/$pagePerBlock); //2block
    $currentBlock = ceil($currentPage/$pagePerBlock); // 1page
        
    $startPage = ($currentBlock-1)*$pagePerBlock+1;  // 1page
    $endPage = $startPage+$pagePerBlock -1; // 10page
    if($endPage > $totalNumOfPage) $endPage = $totalNumOfPage;
    
    //NEXT,PREV 존재 여부
    $isNext = false;
    $isPrev = false;
    
    if($currentBlock < $totalNumOfBlock)    $isNext = true;
    if($currentBlock > 1)                     $isPrev = true;
    
    if($totalNumOfBlock == 1){
        $isNext = false;
        $isPrev = false;
    } 
    
    if($isPrev){
        $goPrevPage = $startPage-$pagePerBlock; // 11page
        echo "<a href=\"$PHP_SELF?page=$goPrevPage\">[PREV]</a>";        
    }    
    for($i=$startPage;$i<=$endPage;$i++){
        echo "<a href=\"$PHP_SELF?page=$i\">[".$i."]</a>";
    }
    if($isNext){
        $goNextPage = $startPage+$pagePerBlock; // 11page
        echo "<a href=\"$PHP_SELF?page=$goNextPage\">[NEXT]</a>";
    }        
}

handlePage($totalRecord,$recordPerPage,$pagePerBlock,$currentPage);

?>


신고

'language > PHP' 카테고리의 다른 글

간단한 게시판 페이징 함수  (0) 2008.12.06
[펌] PHP 코드를 최적화하는 40가지 팁 (번역)  (0) 2008.02.12
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

java의 java.awt패키지는 이미지처리시 운영체제의 자원을 사용한다.

윈도우즈의 경우에는 아무설정을 해주지 않아도 잘돌아가지만(그래서 어떤방식인지는 아직 잘모르겠다.)

유닉스나 리눅스 시스템 환경에서는 X11이라는 흔히 말하는 X-window가 설치되어있고 데몬이 구동되고 있을시에

패키지사용이 가능하다.

보통 웹상에서 JSP & SERVLET을 이용 이미지 썸네일을 구현할시에 여러가지 방식이 있겠지만

나는 JAI를 사용한다.

JAI(Java Advanced Imaging ) 는 SUN에서 발표한 이미지 처리를 위해 만들어 진 API이다.

필요한 jar파일은 jai_core.jar, jai_codec.jar가 필요하다.(sun 홈피에서 다운받을수 있다.)

JAI또한 내부에선 java.awt.를 사용한다.

대략적인 설명을 마치고

================================================================================================

어제부터 썸네일 생성시 에러가 나면서 로그파일에

java.lang.NoClassDefFoundError: sun/awt/X11GraphicsEnvironment
 at java.lang.Class.forName1(Native Method)
 at java.lang.Class.forName(Class.java(Compiled Code))
 at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:91)
 at java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1073)
 at com.nowonplay.hover.image.ImageConverter.create(ImageConverter.java:295)
 at com.nowonplay.hover.image.ImageConverter.create(ImageConverter.java:254)
 at com.nacf.util.ImageUtil.createThumbnail(ImageUtil.java:32)
 at jeus_jspwork._media._vodRrcCenter._photo._403_write._jspService(_403_write.java:346)
 at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:54)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:269)
 at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:102)
 at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:63)
 at jeus.servlet.engine.WebtobRequestProcessor.run(WebtobRequestProcessor.java:175)
[2008.08.28 12:25:28][1] [SRVL-2456] [E] (/media/vodRrcCenter/photo/write.jsp) fail to execute servlet

이러한 메세지가 남아있다..

검색해보니 X11자원을 찾기 못하는것 같았다..아니면 설치되어 있지 않던가.

첫번째 방법은 일단 X11이 설치되어 있지 않다면 설치해야한다.

설치가 되어있는 상태라면 웹서버의 설정파일에서

jvm구동 옵션에 -Djava.awt.headless=true 을 포함해서 웹서버를 재시작 하면 X11데몬을 띄우지 않고

X11의 자원을 사용할 수 있다.


신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

Commons-Lang




IV. org.apache.commons.lang.StringUtils


java api의 String을 보면 문자열 처리하기에는 제공하는 기능들이 너무 빈약합니다.

그래서 프로그래머들은 자기 나름데로의 독특한 Utils를 만들어 사용하지요.

하지만 Commons-lang에서 제공하는 StringUtils를 사용한다면 더이상 자신만의 Utils를 사용할 필요가 없습니다. 여기 모두 ㄷ ㅏ ~ 있기 때문이지요 ^^

한가지 더 장점이 있다면 String의 null 값때문에 더이상 NullPointerException을 생각하지 않아도 된다는 것입니다. StringUtils에서 ㄷ ㅏ ~ 알아서 해주기 때문입니다.


그럼 어떠한 기능들의 함수가 있는지 알아봅시다


반환값 함수명 파라미터
String abbreviate String str, int maxWidth
"…"를 포함한 지정한 사이즈로 문자열을 축소한다 maxWidth은 4보다 커야한다
String abbreviate String str, int offset, int maxWidth
"…"를 포함한 지정한 사이즈로 문자열을 앞/뒤로 축소한다 offset은 7보다 커야한다
String capitalise String str
deprecated
String capitaliseAllWords String str
deprecated
String capitalize String str
문자열중 첫번째 문자를 대문자로 만든다
String center String str, int size
str의 길이가 size가 되도록 문자열 좌우에 공백문자를 하나씩 추가한다 (우측부터 시작한다)
String center String str, int size, char padChar
str의 길이가 size가 되도록 문자열 좌우에 padChar를 하나씩 추가한다 (우측부터 시작한다)
String center String str, int size, String padStr
str의 길이가 size가 되도록 문자열 좌우에 padStr을 하나씩 추가한다 (우측부터 시작한다)
String chomp String str
문자열 맨 끝에있는 '\n' , '\r', '\r\n'을 제거한다
String chomp String str, String separator
문자열 맨 끝에 separator가 있으면 이를 제거한다
String chompLast String str
deprecated
String chompLast String str, String sep
deprecated
String chop String str
문자열 맨 끝에있는 문자 하나를 제거한다
String chopNewline String str
deprecated
String clean String str
deprecated
String concatenate Object array[]
deprecated
boolean contains String str, char searchChar
str이 searchChar를 포함하고 있으면 true
boolean contains String str, String searchStr
str이 searchStr을 포함하고 있으면 true
boolean containsNone String str, char invalidChars[]
str이 invalidChars의 각 문자를 모두 포함하고 있지 않으면 true
boolean containsNone String str, String invalidChars
str이 invalidChars를 모두 포함하고 있지 않으면 true
boolean containsOnly String str, char valid[]
str이 valid의 각 문자들만 포함하고 있어야 true
boolean containsOnly String str, String validChars
str이 validChars 들만을 포함하고 있어야 true
int countMatches String str, String sub
str중에 sub가 포함되어있는 갯수를 반환한다
String defaultString String str
str이 null이면 ""를 반환하고 아니면 str을 반환한다
String defaultString String str, String defaultStr
str이 null이면 defaultStr을 반환하고 아니면 str을 반환한다
String deleteSpaces String str
deprecated
String deleteWhitespace String str
문자열중 공백문자가 있으면 모두 제거한다
String difference String str1, String str2
str1과 str2를 비교하여 다른부분을 반환한다 (str2의 부분을 반환)
boolean equals String str1, String str2
str1이 null이면 str2가 null인지 유무를 반환하고 str1이 null이 아니면 str1과 str2의 equals를 반환
boolean equalsIgnoreCase String str1, String str2
equals와 동일하며 대소문자를 무시하고 비교한다
String escape String str
deprecated
String getChomp String str, String sep
deprecated
String getNestedString String str, String tag
deprecated
String getNestedString String str, String open, String close
deprecated
String getPrechomp String str, String sep
deprecated
int indexOf String str, char searchChar
str에서 첫번째 searchChar의 인덱스를 반환한다
int indexOf String str, char searchChar, int startPos
str의 startPos 인덱스부터 첫번째 searchChar의 인덱스를 반환한다
int indexOf String str, String searchStr
str에서 첫번째 searchStr의 인덱스를 반환한다
int indexOf String str, String searchStr, int startPos
str의 startPos 인덱스로부터 첫번째 searchStr의 인덱스를 반환한다
int indexOfAny String str, char searchChars[]
str에서 searchChars중 포함하고 있는 문자의 첫번째 인덱스를 반환한다
int indexOfAny String str String searchChars
str에서 searchChars중 포함하고 있는 문자열의 첫번째 인덱스를 반환한다
int indexOfAny String str, String searchStrs[]
str에서 searchStr중 포함하고 잇는 문자열의 첫번째 인덱스를 반환한다
int indexOfAnyBut String str char searchChars[]
str에서 searchChars중 포함되지 않은 문자 첫번째 인덱스를 반환한다
int indexOfAnyBut String str, String searchChars
str에서 searchChars중 포함되지 않은 문자 첫번째 인덱스를 반환한다
int indexOfDifference String str1, String str2
str1과 str2를 비교하여 문자열이 틀려지기 시작하는 인덱스를 반환한다
boolean isAlpha String str
문자열이 모두 Character.isLetter 이면 true (모두 문자이면 true)
boolean isAlphanumeric String str
문자열이 모두 Character.isLetterOrDigit 이면 true (문자거나 숫자이면 true)
boolean isAlphanumericSpace String str
문자열이 모두 Character.isLetterOrDigit 이거나 공백이면 true
boolean isAlphaSpace String str
문자열이 모두 Character.isLetter 이거나 공백문자이면 true
boolean isBlank String str
문자열이 공백문자이거나 길이가 0이거나 null인경우 true
boolean isEmpty String str
문자열이 길이가 0이거나 null인경우 true
boolean isNotBlank String str
문자열이 공백문자도 아니고 길이가 0도 아니고 null도 아니면 true
boolean isNotEmpty String str
문자열이 길이가 0이 아니고 null도 아니면 true
boolean isNumeric String str
문자열이 모두 Character.isDigit 이면 true (모두 숫자이면 true)
boolean isNumericSpace String str
문자열이 모두 Character.isDigit 이거나 공백문자이면 true
boolean isWhitespace String str
문자열이 모두 Character.isWhitespace 이면 true (모두 공백이면 true)
String join Object array[]
array에서 문자열을 읽어와 모두 연결시킨다
String join Object array[], char separator
array에서 문자열을 읽어와 separator를 구분자로 연결시킨다
String join Object array[], String separator
array에서 문자열을 읽어와 separator를 구분자로 연결시킨다
String join Iterator iterator, char separator
iterator에서 문자열을 읽어와 separator를 구분자로 연결시킨다
String join Iterator iterator, String separator
iterator에서 문자열을 읽어와 separator를 구분자로 연결시킨다
int lastIndexOf String str, char searchChar
str에서 마지막 searchChar의 인덱스를 반환한다
int lastIndexOf String str, char searchChar, int startPos
str의 startPos 인덱스부터 마지막 searchChar의 인덱스를 반환한다
int lastIndexOf String str, String searchStr
str에서 마지막 searchStr의 인덱스를 반환한다
int lastIndexOf String str, String searchStr, int startPos
str의 startPos 인덱스부터 마지막 searchStr의 인덱스를 반환한다
int lastIndexOfAny String str, String searchStrs[]
str에서 searchStr의 문자열들중 포함하고 있는 문자열의 마지막 인덱스를 반환한다
String left String str, int len
str의 좌측에서 len 길이만큼 문자열을 구한다
String leftPad String str, int size
str의 길이가 size가 되도록 문자열 왼쪽에 ' '을 추가한다
String leftPad String str, int size, char padChar
str의 길이가 size가 되도록 문자열 왼쪽에 padChar를 추가한다
String leftPad String str, int size, String padStr
str의 길이가 size가 되도록 문자열 왼쪽에 padStr을 추가한다
String lowerCase String str
str을 소문자로 변환한다
String mid String str, int pos, int len
str의 pos 인덱스부터 len 길이만큼의 문자열을 구한다
String overlay String str, String overlay, int start, int end
str의 start부터 end까지overlay로 변환한다
String overlayString String text, String overlay, int start, int end
deprecated
String prechomp String str, String sep
deprecated
String repeat String str, int repeat
str을 repeat만큼 반복하여 반환한다
String replace String text, String repl, String width
text에서 모든 repl을 width로 변환한다
String replace String text, String repl, String width, int max
text에서 모든 repl을 width로 변환하는데 최대 max개만큼 변환한다
String replaceChars String str, char searchChar, char replaceChar
str에서 searchChar를 replaceChar로 모두 변환한다
String replaceChars String str, String searchChars, String replaceChars
str에서 searchChars를 replaceChars로 모두 변환한다
String replaceOne String text, String repl, String width
text에서 repl를 width로 변환하는데 첫번째 하나만 변환한다
String reverse String str
문자열을 앞뒤 순서를 바꾼다
String reverseDelimited String str, char separatorChar
separatorChar를 구분으로 문자열을 나눈 후 나눠진 단어들을 역순으로 바꾼다
String reverseDelimitedString String str, String separatorChars
deprecated
String right String str, int len
str의 len길이만큼 우측에서 문자열을 구한다
String rightPad String str, int size
str의 길이가 size가 되도록 문자열 오른쪽에 ' '을 추가한다
String rightPad String str, int size, char padChar
str의 길이가 size가 되도록 문자열 오른쪽에 padChar를 추가한다
String rightPad String str, int size, String padStr
str의 길이가 size가 되도록 문자열 오른쪽에 padStr을 추가한다
String[] split String str
공백문자를 구분자로 사용하여 분리한다
String[] split String str, char separatorChar
separatorChar를 구분자로 사용하여 분리한다
String[] split String str, String separatorChars
separatorChars를 구분자로 사용하여 분리한다
String[] split String str, String seperatorChars, int max
separatorChars를 구분자로 사용하여 분리한며 최대 max개 만큼한다. 배열의 크기는 max가 된다
String strip String str
문자열 좌우에 있는 공백문자를 제거한다 trim과 동일하다
String strip String str, String stripChars
문자열 좌우에 stripChars에 존재하는 문자를 제거한다
String[] stripAll String strs[]
배열에 있는 모든 문자열 좌우에 있는 공백문자를 제거한다
String[] stripAll String strs[], String stripChars
배열에 있는 모든 문자열 좌우에 stripChars에 존재하는 문자를 제거한다
String stripEnd String str, String stripChars
문자열 우측에만 strip 한다
String stripStart String str, String stripChars
문자열 좌측에만 strip 한다
String stripToEmpty String str
str이 null이면 ""를 반환하고 아니면 strip 한다
String stripToNull String str
str이 null이면 null을 반환하고 아니면 strip 한다
String substring String str, int start
str의 start 인덱스부터 문자열을 구한다
String substring String str, int start, int end
str의 start 부터 end 인덱스 까지 문자열을 구한다
String substringAfter String str, String separator
str의 처음 separator 부분부터 문자열을 구한다
String substringAfterLast String str, String separator
str의 마지막 separator부분부터 문자열을 구한다
String substringBefore String str, String separator
str의 처음 separator 부분까지 문자열을 구한다
String substringBeforeLast String str, String separator
str의 마지막 separator부분까지 문자열을 구한다
String substringBetween String str, String tag
str에서 tag 사이에 있는 문자열을 구한다
String substringBetween String str, String open, String close
str에서 open부터 close 까지 사이에 있는 문자열을 구한다
String swapCase String str
대문자는 소문자로 변환하고 소문자는 대문자로 변환한다
String trimToNull String str
str이 null이거나 length가 0이면 null을 반환하고 그렇지 않으면 좌우 공백문자를 제거한다
String trim String str
문자열 좌우 공백문자를 제거한다
String trimToEmpty String str
str이 null이면 ""를 반환하고 그렇지 않으면 좌우 공백문자를 제거한다
String uncapitalise String str
deprecated
String uncapitalize String str
문자열의 첫문자를 소문자로 변환한다
String upperCase String str
str을 대문자로 변환한다

사용법

모두 static 함수이기때문에 다음과 같이 사용하면 됩니다.

String text = StringUtils.replace(str, repl, width);


=============================================

저자 : GoodBug (unicorn@jakartaproject.com)

최초 : http://www.jakartaproject.com 

=============================================

신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.

http://jonggyu.com/blog/tag/eclipse?TSSESSION=2263d701401abfef3b614c1e5ff6bcdc#entry_13

http://tomcat.apache.org/tomcat-5.5-doc/jndi-datasource-examples-howto.html

http://kwon37xi.egloos.com/2852803

아주. 어젯밤부터 지금까지 캐삽질끝에...겨우 연결성공...

근데...좌절...

나 바보? ㅠ_ㅠmysql jdbc jar파일을 ...WEB-INF/lib에 놔서 된줄알았는데...

결국엔 그것때문에 안먹었다는..분명히 이클립스에서 빌드패스도 잡혔었는데...

이거 뭥미.-_-

결국엔 tomcat5.5/common/lib에 갔다놓고 실행했더니 바로되는..쿨럭;

아...완전 삽질..정말...

그덕에 한 1년간은 이 설정하는건 절대 까먹지 않겠군..-_-
신고
블로그 이미지

웹오피스 개발자 피스티스

사이냅소프트에서 웹오피스를 개발하고 있습니다.