Apache Common httpclient를 쓴다는 의미는 대부분 로직단에서 OpenAPI 같은걸 호출하고 있다는 의미라서 String이나 Base64타입의 파라메터들을 사용하게 일반적이다.

부끄럽지만 나도 그런편이라 처음으로 파일을 파라메터로 날려야 할 상황이 생겨서 조금은 난감했다.

결과적으로 파일 객체를 FilePart 객체에 넣어서 PostMethod객체의 RequestEntry에 넣어주면 된다.

말이 어려우니깐 쉽게 소스로 풀어보자.


import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;

public class TestPost {
		
	public void sendPostFile(){
		String url = "http://localhost:8080/testblabla/acceptFile.do"; //걍 테스트용으로 대충 만든 URL
		
		PostMethod post = new PostMethod(url); //Post 객체 하나 만듬. 
		HttpClient client = new HttpClient();
		int statusCode;
		String resposeMessage = null;
		
		try {
			List parts = new ArrayList(); // Paramater들을 넣을 리스트 객체 하나 만들고~
			parts.add(new StringPart("saveDirectory", "shared")); //대충 파일외에 String Param이 있다고 가정.......

			File file = new File("./test.txt"); // 날릴 파일 
			parts.add(new FilePart("saveFile", "test.txt", file)); //객체생성자는 param명, 파일이름, 파일 객체 순으로...
			
			post.setRequestEntity(new MultipartRequestEntity((Part[])parts.toArray(new Part[parts.size()]), post.getParams())); 
			//파일을 전송하야 하니 당연히 Multipart타입으로~
			
			client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); //접속~
			statusCode = client.executeMethod(post); //http 응답 Status값 받기(200, 404, 500등등)
			resposeMessage = post.getResponseBodyAsString(); // 요청에 대한 응답 메시지가 있다고 가정 
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			post.releaseConnection();
		}
	}
}

 


 

 


 


Posted by 오달봉
,

vim -b {filename}

이렇게 파일을 열어

:%s/^M//g

입력하여 지운다. 하지만 ^M이렇게 입력하는 것이 아니라 CTRL+V, CTRL+M 을 순서대로 입력하여 넣어야 된다는 점이다.

Posted by 오달봉
,

 

 

출처 가비의 블로그 | 가비
원문 http://blog.naver.com/neptune4781/90002644797
IMAP COMMOND 정리
 
1. 접속
 telnet XXX.XXX.XXX.XXX 143
 
2. 로그인
 확인할 사용자 확인
 a LOGIN [사용자] 0000
 
3. 박스 선택하기
 a SELECT INBOX
 
4. 리스트 보기
 a FETCH 0:[최대UID|*] (UID RFC822.SIZE FLAGS BODY[HEADER.FIELDS (FROM TO SUBJECT DATE MESSAGE-ID)])
 
5. 메시지 가져오기
 a UID FETCH [해당 UID] BODY.PEEK[]
 
 
유용한 COMMAND
1. 전체 메시지의 X-MMS-MESSAGE-ID 출력
  a fetch 0:* (BODY[HEADER.FIELDS (X-MMS-MESSAGE-ID)])
 
2. 특정 X-MMS-MESSAGE-ID를 가진 UID 검색
  a search HEADER "X-MMS-MESSAGE-ID" "검색하려고 하는값"
 
3. 메일 삭제
  a store [UID] +flags (\deleted)
  a expunge
 
4. 첨부 컨텐츠만 확인
  a fetch [UID] rfc822.text
 
5. 메일의 모든 헤더값 출력
  a fetch [UID] BODY[HEADER]
 
 

1.       SELECT Command

A.      설명

메일 박스를 선택 한다. ( <-> CLOSE )

B.      사용예

A1 SELECT INBOX

<-> A1 CLOSE

 

2.       EXAMINE Command

A.      설명

SELECT 명령과 같다. 그러나 the selected mailbox is identified as read-only.

B.      사용예

A1 EXAMINE INBOX

 

3.       CREATE Command

A.      설명

메일 박스를 생성 한다.

B.      사용예

A1 CREATE OUTBOX1

 

4.       DELETE Command

A.      설명

메일 박스를 삭제 한다.

B.      사용예

A1 DELETE OUTBOX1

 

5.       RENAME Command

A.      설명

메일박스의 이름을 변경한다.

B.      사용예

A1 RENAME OUTBOX1 OUTBOX3

 

6.       SUBSCRIBE Command

A.      설명

LSUB Command에 의해 리턴되는 메일박스의 서버측 세팅인 ACTIVE, SUBSCRIBED 명시된 메일박스의 이름을 이 명령으로 추가 한다. (등록)

B.      사용예

A1 SUBSCRIBE OUTBOX1

 

7.       UNSUBSCRIBE Command

A.      설명

SUBSCRIBE의 반대 작업 (등록해제).

B.      사용예

A1 UNSUBSCRIBE OUTBOX1

 

8.       LIST Command

A.      설명

리스팅 기능.

B.      사용예

A1 LIST “” *

 

 

9.       LSUB Command

A.      설명

LIST와 기능이 비슷함

B.      사용예

a1 lsub "#news." "comp.mail.*"

a1 OK LSUB completed

 

10.   STATUS Command

A.      설명

메일박스의 상태 정보를 리턴 함.

Parameter

MESSAGES : 메일박스에 메세지의 수를 리턴    

RECENT : 최근에 등록된 메시지의 수 리턴

UIDNEXT : 새로운 메시지에 부여될 UID의 번호 리턴

UIDVALIDITY : 메일박스에서 unique identifier validity value 리턴

UNSEEN : The number of messages which do not have the \Seen flag set.

 

B.      사용예

A1 STATUS INBOX (MESSAGES)

A1 STATUS INBOX (MESSAGES UIDNEXT UIDVALIDITY)

 

11.   APPEND Command

A.      설명

명시된 메일박스의 끝에 새로운 메시지를 추가 할 수 있는 명령이다.

B.      사용예

A003 APPEND outbox1 (\Seen) {310}

Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)

From: Fred Foobar <foobar@Blurdybloop.COM>

Subject: afternoon meeting

To: sjjung@mdminc.net

Message-Id: <B27397-0100000@Blurdybloop.COM>

MIME-Version: 1.0

Content-Type: TEXT/PLAIN; CHARSET=US-ASCII

C:

Hello Joe, do you think we can meet at 3:30 tomorrow?

C:

C:

C:

S: A003 OK APPEND completed

 

12.   CHECK Command

A.      설명

현재 선택된 메일박스의 체크포인트를 요구 한다.

B.      사용예

a1 check

a1 OK CHECK completed

 

13.   CLOSE Command

A.      설명 (좀더 읽어 봐야 함)

현재 선택된 메일박스의 close, 메시지중 \Deleted flag 로 세팅 되어 있는 것들은 영구적으로 삭제 해버린다.

B.      사용예

a1 close

 

14.   EXPUNGE Command

A.      설명

현재 선택된 메일박스의 메시지중 \Deleted flag 로 세팅 되어 있는 것들은 영구적으로 삭제 해버린다.

B.      사용예

a1 expunge

 

15.   SEARCH Command

A.      설명 (argument가 많음 다시 읽어 보기)

메일박스에서 given searching criteria 를 찾는다.

Searching criteria consist of one or more search keys.

B.      사용예

A282 SEARCH FLAGGED SINCE 1-Feb-1994 NOT FROM "Smith"

 

16.   FETCH Command

A.      설명

fetch 명령은 메일박스안의 메시지에 첨부된 데이터를 가져온다.

Fetch data single atom 또는 parenthesized list 로 할 수 있다.

사용해본 결과 아래와 같이도 됨

* 7 FETCH (FLAGS (\Seen) BODY[HEADER.FIELDS ("DATE" "FROM" "SUBJECT")] {118}

Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)

From: Fred Foobar <foobar@Blurdybloop.COM>

Subject: afternoon meeting

B.      사용예

A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])

A654 FETCH 1:7 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])

A654 FETCH 1:7 (FLAGS BODY[HEADER.FIELDS (DATE FROM SUBJECT)])

 

17.   STORE Command

A.      설명

메일박스안의 메시지에 첨부된 데이터를 바꾼다.

STORE가 플래그의 설정을 할 수 있음

B.      사용예

A003 STORE 2:4 +FLAGS (\Deleted)

 

18.   COPY Command

A.      설명

명시된 목적지 메일박스의 끝에 명시된 메시지를 복사 할 수 있다.

Flag internal date는 복사본 에서도 유지 된다.

B.      사용예

A003 COPY 2:4 inbox

 

19.   UID Command

A.      설명

UID는 두개의 폼을 가지고 있다.

첫번째

복합 명령을 위해 적당한 argument copy, fetch, store 명령과 함께 쓸수 있다. 그러나 message set argument 의 수는 message sequence numbers 대신에 유일하게 인식 한다.

두번째

search 폼과 같이 쓸 수 있다. Argument의 해석은 SEARCH 명령과 같다. 그러나 UID SEARCH command를 위해 SEARCH 응답안데 돌려 보내는 수는 message sequence numbers 대신에 유일하게 인식 한다.

For example, the command UID SEARCH

1:100 UID 443:557 returns the unique identifiers corresponding to

the intersection of the message sequence number set 1:100 and the

UID set 443:557.

B.      사용예

A999 UID FETCH 2:6 FLAGS

* 1 FETCH (UID 4 FLAGS (\Seen))

A999 OK UID FETCH completed

 


 

/* (0) call login - Login ID, Login Password, Login Prompt */
cmd_struct tel_login[] = {
 {"* OK", "login login %s %s", NULL, NULL},
 {"login OK", "~", NULL, NULL},
};

/* (1) call logout*/
cmd_struct tel_logout[] = {
 {"~", "logout logout", NULL, NULL},
 {"logout OK", "~", NULL, NULL},
};

/* (2) close message sequence of MMBox */
cmd_struct close_mmbox_cmd_list[] = {
 {"~", "MMBox close", NULL, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (3) noop MMBox */
cmd_struct noop_mmbox_cmd_list[] = {
 {"~", "MMBox noop", NULL, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (4) create MMBox */
cmd_struct create_mmbox_cmd_list[] = {
 {"~", "MMBox create %s", NULL, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (5) remove MMBox */
cmd_struct remove_mmbox_cmd_list[] = {
 {"~", "MMBox delete %s", NULL, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (6) upload MMBox */
cmd_struct upload_mmbox_cmd_list[] = {
 {"~", "MMBox append %s (\\Seen) {%s}", NULL, NULL},
 {"+ OK", "%s", append_proc, NULL},
// {"+ Ready", "%s", append_proc, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (7) move Mail in MMBox to other MMBox */
cmd_struct move_mmbox_cmd_list[] = {
 {"~", "MMBox select %s", NULL, NULL},
 {"MMBox ", "MMBox search HEADER Message-ID %s", NULL, parse_error_detect},
 {"MMBox ", "MMBox copy %s %s", NULL, parse_search_sqn},
 {"MMBox ", "MMBox store %s +FLAGS (\\Deleted)",
   NULL, parse_error_ignore},
 {"MMBox ", "MMBox expunge", NULL, NULL},
 {"MMBox ", "MMBox close", NULL, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (8) copy Mail in MMBox to other MMBox */
cmd_struct copy_mmbox_cmd_list[] = {
 {"~", "MMBox select %s", NULL, NULL},
 {"MMBox ", "MMBox search HEADER Message-ID %s", NULL, parse_error_detect},
 {"MMBox ", "MMBox copy %s %s", NULL, parse_search_sqn},
 {"MMBox ", "MMBox close", NULL, parse_error_ignore},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (9) del Mail in MMBox */
cmd_struct del_mmbox_cmd_list[] = {
 {"~", "MMBox select %s", NULL, NULL},
 {"MMBox ", "MMBox search HEADER Message-ID %s", NULL, parse_error_detect},
 {"MMBox ", "MMBox store %s +FLAGS (\\Deleted)",
   NULL, parse_search_sqn},
 {"MMBox ", "MMBox expunge", NULL, NULL},
 {"MMBox ", "MMBox close", NULL, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (10) get Mail in MMBox */
cmd_struct get_mmbox_cmd_list[] = {
 {"~", "MMBox select %s", NULL, NULL},
 {"MMBox ", "MMBox search HEADER Message-ID %s", NULL, parse_error_detect},
 {"MMBox ", "MMBox fetch %s RFC822.TEXT", NULL, parse_search_sqn},
 {"MMBox ", "MMBox close", NULL, parse_get_mm},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (11) get Mail header in MMBox */
cmd_struct get_header_cmd_list[] = {
 {"~", "MMBox select %s", NULL, NULL},
 {"MMBox ", "MMBox search HEADER Message-ID %s", NULL, parse_error_detect},
 {"MMBox ", "MMBox fetch %s BODY[HEADER]", NULL, parse_search_sqn},
 {"MMBox ", "MMBox close", NULL, parse_get_mm},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (12) view Mail list in MMBox */
cmd_struct view_mmbox_cmd_list[] = {
 {"~", "MMBox select %s", NULL, NULL},
 {"MMBox ", "MMBox fetch 1:* (FLAGS BODY[HEADER])", NULL, parse_error_detect}, /* UID FETCH 1:* (FLAGS) */
 {"MMBox ", "MMBox close", NULL, parse_fetch_mmbox_list},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (13) status MMBox */
cmd_struct status_mmbox_cmd_list[] = {
 {"~", "MMBox status %s (MESSAGES)", NULL, NULL},
 {"MMBox ", "~", NULL, parse_error_detect},
};

/* (14) store flags of MM of MMBox */
cmd_struct set_status_mmbox_cmd_list[] = {
 {"~", "MMBox select %s", NULL, NULL},
 {"MMBox ", "MMBox search HEADER Message-ID %s", NULL, parse_error_detect},
 {"MMBox ", "MMBox store %s flags %s", NULL, parse_search_sqn},
 {"MMBox ", "MMBox close", NULL, parse_error_detect},
 {"MMBox ", "~", NULL, parse_error_detect},
};

Posted by 오달봉
,

정말 잘되어 있었다. 완전 강추


http://blog.beany.co.kr/archives/3198

Posted by 오달봉
,

int a=0;

a++

System.out.println(a);

이러면 a값은 당연히 1이다.

이유는 a++ 을 풀어서 얘기하자면 a = a+1;

이기 때문이다. 절대 a+1이 아니라는 것의 명심하자

그래서 한가지 재밌는것은

a = a++;
이라고 정의했을때 이 값을 찍어보면 0이 나온다. 변수대입이 먼저 이루어지고 ++연산이 일어나기 때문이다.

하지만 a = ++a;
인 경우에는 1이다. ++연산이 이루어지고 변수를 대입하기 때문이다.

가끔 이런 기초적인 것을 잊는 경우가 있으니 햇갈리지 말도록.

 

Posted by 오달봉
,

원문 주소 : http://fiaa.net/aqua/archives/244 

하지만 페이지로 접속이 되지 않아 구글 저장 페이지를 열어 보았습니다.

http://webcache.googleusercontent.com/search?q=cache:YaaoufhV-UYJ:fiaa.net/aqua/archives/244+&cd=1&hl=ko&ct=clnk&gl=kr&lr=lang_ko

자바메일로 IMAP 폴더 사이즈 계산이 느린 이유

메일이 52,630통 정도 되는 INBOX가 있다.
개별 메일의 사이즈는 945bytes 정도 된다.

자바메일로 folder size를 요청하면 대략 1분 정도가 소요된다.
하지만 펄로 folder size를 요청하면 4~5초 정도가 소요된다.

둘의 차이는?
당연히 라이브러리에서 IMAP Query 차이가 자바가 느리게 실행된 이유다.

먼저 에서 날린 쿼리를 보자.

1 LOGIN username password
2 EXAMINE INBOX
3 UID SEARCH ALL
4 UID FETCH 145,147:183,186,190:194,197:244,251:253,256:52785,52806:52810 (RFC822.SIZE)

다음으로 자바에서 날린 쿼리를 보자.

A1 LOGIN username password
A2 CAPABILITY
A3 LIST “” INBOX
A4 EXAMINE INBOX
A5 FETCH 1 (ENVELOPE INTERNALDATE RFC822.SIZE)
A6 FETCH 2 (ENVELOPE INTERNALDATE RFC822.SIZE)
A7 FETCH 3 (ENVELOPE INTERNALDATE RFC822.SIZE)


A52640 FETCH 52810 (ENVELOPE INTERNALDATE RFC822.SIZE)

[차이점 1]
FETCH명령을 사용하는 방법이 다르다.
펄은 연속된 UID는 147:183 이런식으로 쿼리를 사용했지만,
자바는 UID 마다 각각의 쿼리를 날렸다.

[차이점 2]
FETCH 명령을 쓸 때 옵션이 다르다.
펄에서는 RFC822.SIZE만 쓴 반면에 자바에서는 ENVELOPE INTERNALDATE까지 썼다.
사이즈만 계산하는데 굳이 ENVELOPE INTERNALDATE를 붙일 필요가 없다.

[결론]
1. 자체 라이브러리를 만들어야 한다.
2. 자바메일은 잘못된 IMAP Query 방법 때문에 서버의 불필요한 IO만 증가 시켜서 처리 속도를 느리게 했다.

Posted by 오달봉
,

이글은 테이블 스페이스가 날아가고 해당 데이터 베이스를 복구하지 않는다는 전제하에 쓴 글이다.

안쓰는 DB서버에 실수로 테이블 스페이스 파일 (dbf파일)을 날리고 서버에서

ora-01034 ORACLE not availableORA-27101 요딴 메세지나 나온다.

아무리 개발연차가 늘어도 DB서버에서 문제가 나면 작아지는 기분이다.

방법은 이렇게

ALTER DATABASE DATAFILE '{dbf파일}' OFFLINE DROP;
ex) ALTER DATABASE DATAFILE '/home/oracle/db_files/workflow.dbf' OFFLINE DROP;

RECOVER DATABASE;

alter database open;

이런식으로

이런 후 oracle을 내렸다가 다시 올린다.

다들 알겠지만 그래도 내렸다가 올리는 법은

shutdown immediate;

startup;

이러니깐 잘 되더라~~~ ㅋㅋㅋ 

Posted by 오달봉
,

본인이 재직중인 핸디소프트에는 다양한 제품들이 존재한다. 이중 현재 회사에서 주력하고 있는 제품이 SNS인데

전부터 열풍이 불던 SNS열풍의 후광을 업고 기업 소셜네트워크 구축에 일조를 하고 있다.

그런데 한가지 아쉬운건 유용한 기사나 블로그의 주소를 붙여 넣으면 페이스북 처럼 썸내일과 기사 요약을 보여주는 기능이 누락되어 있었다. 그래서 사내 이런 기능을 요청하였는데 겁없이 간단히 구현 할 수 있을꺼란 말을 넣어버렸다. ㅜㅜ

내 생각으론 간단할꺼 같은데 실제 구현단으로 들어가면 이래저래 예외가 발생할 수 있기 때문에 많은 부분을 고려해야 할 지도 모른다. 


요딴 식으로 올렸는데 정말 구현이 쉬울지는 나도 한번 겪어봐야 알겠다는 생각이 들었다. 그래서 봄날의 오후 근처 스타벅스에 들려 노트북을 이용해 공부도 해 볼 겸 겸사겸사 한번 구현해 보기로 했다.

1. 분석

페이스북에서 제공하는 요약의 이미지는 다음과 같으며 분석해본 결과는 다음과 같다.


1. 처음에 보이는 링크는 해당 기사의 title태그를 가져와 url을 링크로 걸었다.
2. www.bloter.net은 해당 사이트의 대표 url이다.
3. 본문 내용은 해당 웹페이지에 있는 contents라는 아이디의 div내의 text를 가져왔다.
4. 좌측은 썸내일은 아이디 contents내에 있는 img태그들중 첫번째 이미지이다.

재밌는점은 해당 샘플페이지인 블로터 닷넷외에도 티스토리 이글루스 그외 언론사이트 역시 해당 룰데로 페이스 북에서 데이터를 파싱하고 있다는 점이다. (무슨 규약인지 아시는 분은 댓글 좀 부탁 드릴께요 ㅜㅜ rss관련 뭔가인가?)

 이런 전제로 내가 구현할 로직에 대해서 구체화를 하였다.

1. 아파치 common library 중 HttpClient패키지를 사용해 웹의 본문 데이터를 가져온다.
2. Jsoup으로 해당 페이지를 파싱하여, 요구사항에 언급된 내용을 데이터화한다. (물론 jsoup에서 connect메소드를 사용하여 본문 내용을 긁어 올수 있다. 걍 여러 라이브러리 써보는 연습차 1번 사항을 추가로 했다. 비효율적인거 나도 안다. ㅋㅋㅋ )

두가지 룰을 지키기로 하고, 이 포스트에서 자바 로직단 만을 보여주기로 한다. 하지만 전체적인 플로우는 다음과 같을 꺼라 생각한다.

1. 클라이언트에서 주소 붙여넣기 이벤트 혹은 url타이핑이 감지되면 ajax를 이용하여 해당 기사의 요약을 생성하는 로직을 요청(파라미터는 url)
2. 서버에서는 해당 url을 이용해 데이터를 프로세싱 결과값을 콜백(json형태로 리턴)
3. 클라이언트는 콜백받은 데이터를 이용해,  웹화면을 구성한다.

웹을 개발하는 사람들에게 1,3번은 어렵지 않은 부분으로 2번에 대해 소스코드를 구현해보자. 간단히 테스트 형태의 구조이며, 예외처리를 따로 감안하지는 않았다.

1. 먼저 이클립스를 이용해 apache common라이브러리와 jsoup라이브러리를 import한다. 내가 포함한 라이브러리는 이미지를 참고 부탁한다.(commons-httpclient-3.0.1이 실제적인 라이브러리지만 해당 jar는 logging과 codec에 대한 의존성을 가지고 있으며, jsoup은 html 파싱라이브러리이다. css 셀렉터를 활용할 수 있어, jquery에 익숙한 사람들에게는 유용한 라이브러리이다. 마치 python의 beautiful soup을 연상쾌 한다.)

 


2. 메인 함수에서 순서를 정리한다.(이미지 형태로 보여드립니다. 소스코드를 첨부하오니 복사& 붙여넣기는 하단에 첨부된 소스코드를 이용해 주세요.)

3. downloadContent 메소드는 웹에서 본문을 가져오기 위해 사용되는 메소드이며 다음과 같이 구현한다.

4.  downloadContent메소드에서 가져온 내용을 바탕으로 parseDate메소드에서 요약에 필요한 내용을 만든다. 보시는 바와 같이 jsoup은 jquery셀렉터와 같이 html엘리먼트들을 파싱해 낼 수 있다. (참고로 본문 내용을 요약한다는 가정하에 전체문장에서 100자만 짜른다. 그리고 이미지들을 다양하게 구성할 수 있어 대표이미지 하나가 아닌 배열 형식으로 전체를 저장하는 방법을 선택하였음.)

5. 이것대로 구성하여 본문을 만들면 다음과 같은 결과가 출력될 것이다.

이 데이터를 response단에 넣으면 될 것이다. 자세한 것은 첨부한 소스코드를 확인해 보길 바란다.

하나는 해당 내용에 대한 순수자바 파일이고 다른 하나는 바로 이클립스에서 넣고 확인해 볼 수 있는 이클립스 project 압축 파일이다.



ArticleTest.java


test.zip


Posted by 오달봉
,

이거 때문에 아주 밤을 샐 뻔 했다.

사내 그룹웨어 서버를 업그레이드 하면서, 타 시스템과 연계를 하는 과정에, 뷰를 생성하면서 이 해당 문제가 생겨서

대략 난감이 난무하는 멘붕 상태가 오고 말았다.

'아놔 실 시스템인데 ㅜㅜ........... 시말서 써야 하나 ㅜㅜ'

네이버님과 구글신을 검색하니 이런 말이 나온다.

뷰테이블을 생성한 권한이 없습니다. select * from user_role_privs; 쿼리로 확인 후 grant create view to
[계정명];
으로 해결하시면 그대 인생이 샤방해 집니다. *^.^*

해도 안된다. -_-;; 다른데를 검색했더니 이런 말이 나온다.

오라클이 이상한거임, 오라클을 재시작해 보셈.

아놔 해당 DB서버엔 여러가지 시스템이 물려있다. 오라클 내렸다 올리면 다른 시스템도 재시작해야 하는데~~~~

그런 시말서를 유도하는 행위는 하기 싫다.

먼저 select * from user_role_privs;로 확인해본 결과 권한은 다 있다. 심지어 DBA권한두 있었다. -_-;;

Oracle Developer에서 뷰생성 기능을 이용해 기존 뷰를 생성해 질의 테스트를 통해 무엇이 문제인가 했더니

타테이블스페이스에 있는 테이블에 대한 접근권한이 없었다.

음...... DBA권한임을 알고 그쪽 테이블 스페이스에 있는 테이블에 grant를 주지 않은 초보적인 실수를 한게

화근이었다.

자 정리해보자 위에 내용은 과감하게 무시해도 좋다.

1. 아무리 관리자 권한이 있더라도 SYNONYM을 주고자 할때는 대상 테이블 스페이스의 권한을 반드시 주는 것이
갑이다. GRANT SELECT ON [대상계정].[해당테이블] TO [권한받고자 하는 계정];

2. 이후 권한을 받고자 하는 계정에서 SYSNONYM을 생성한다. CREATE OR REPLACE SYNONYM
[권한을 받고자 하는계정].[해당테이블명] for [대상계정].[해당테이블];

3. 이후 뷰를 생성하면 제목에서 언급한 오류가 나지 않는다.

여담으로  

뷰 생성시 Oracle developer에서 뷰생성기에 질의 테스트 혹은 구문 확인 기능을 쓰면 쿼리 문법을 확인 할 수 있다.

멘붕이 난무하던 DB삽질기~~~ 끗~!!

Posted by 오달봉
,

package jeyun.test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestClass {

 static String Reg(String str, String pstr) {
     StringBuffer sb = new StringBuffer();
     Pattern p = Pattern.compile(pstr);
     Matcher m = p.matcher(str);
     while( m.find() ) {      
         m.appendReplacement(sb, "");      
     }
     m.appendTail(sb);
     return sb.toString();
    }
  
 
 public static void main(String[] args) {
  String str = "<li style=\"height:100px\"><a href=http://xxx><img src='/image/list/20110325.jpg' border=0><img src='/image/list/20110325.jpg' border=0></a><p>~~~~~</p></li>";
  
  
  System.out.print( Reg(str, "<img.*?>") );
  
  
 }
 
}

Posted by 오달봉
,