'분류 전체보기'에 해당되는 글 2491건

  1. 2009.06.19 tomcat5.0 에서 datasource 설정하기
  2. 2009.06.19 Tomcat 5.5 에서 JNDI Datasource 사용하기
  3. 2009.06.19 eclipse 3.3 europa + mysql Connection Pool 설정시 오류 및 설정 방법
  4. 2009.06.18 html textarea 에서 엔터 값을 자동 줄바꿈으로 처리하는 방법
  5. 2009.06.18 [Tip] 오라클 CLOB 데이터 입출력 (oracle clob 2번 연속 넣기)
  6. 2009.06.18 java.lang.ClassCastException: oracle.sql.CLOB 에러
  7. 2009.06.16 우분투를 개발 머신으로 만들기 - JSP 환경 구축 -
  8. 2009.06.16 multipart form parser - http file upload, database 저장 java class 연재2
  9. 2009.06.16 multipart form parser - http file upload 기능 java class 연재1
  10. 2009.06.16 JSP 파일의 동작구조
  11. 2009.06.16 java 디렉토리 만들기 예제
  12. 2009.06.15 oracle TRUNC 원하는 소수점 자리수 만큼 보여주기, 소수점 자리 자르기
  13. 2009.06.13 Teach Your Self Java Programming In 21 Days
  14. 2009.06.13 Java Performance Tuning 2000
  15. 2009.06.13 beginning-jsp-jsf-and-tomcat-web-development-from-novice-to-professional
  16. 2009.06.13 Apress Pro Apache Tomcat 6
  17. 2009.06.13 apache_java_tomcat_mod_jk
  18. 2009.06.13 oracle-sql-tuning pocket reference (오라클 튜닝) 2
  19. 2009.06.13 oracle 공인교재 9i 한글판. 4
  20. 2009.06.11 이클립스 Ctrl + space(code assist) 안될 때 해결방법
  21. 2009.06.11 Eclipse 내, tomcat work디렉토리 위치. 1
  22. 2009.06.09 oracel : xdb 8080 Changing XML DB Default Ports
  23. 2009.06.09 oracle : xdb 8080 변경
  24. 2009.06.09 oracle XDB 8080 충돌시 포트 변경하는 거
  25. 2009.06.08 Java에서 HTML 태그를 제거하는 정규식 적용 1
  26. 2009.06.08 CLOB COLUMN 또는 CLOB VARIABLE를 REPLACE, SEARCH하는 방법
  27. 2009.06.08 jstl에서 clob 처리 하기..
  28. 2009.06.07 java enum - enum의 메쏘드
  29. 2009.06.04 오라클 에러코드별 처리..
  30. 2009.06.04 oracle 0917
98..Etc/Tomcat2009. 6. 19. 15:44
반응형
  1. tomcat5.0 에서 datasource 설정하기

강좌보기

Posted by 1010
05.JSP2009. 6. 19. 15:28
반응형
Tomcat 5.5 에서 JNDI Datasource 사용하기
JSP 프로그래밍에서 쉽게 볼 수 있는 DB를 사용하는 방법대신 왜 DBCP, JNDI Datasource 같은 복잡한 것들을 왜 해야할까요?

DBCP, JNDI에 대한 자세한 정의는 따로 위키등에서 참고하세요.

- DBCP는 데이터베이스 커넥션풀링으로 접속객체를 풀에 넣어두고 필요할때 꺼내서 사용하여 성능을 향상시키기 위함입니다.
- JNDI(Java Naming and Directory Interface)는 분산된 자원을 디렉토리 형태로 이름지어 검색할 수 있게 하는 것입니다.
- 톰캣의 JNDI Datasource 라는 것은 데이터소스를 JNDI를 이용, 찾아서 연결해 사용하자는 것입니다.

JNDI Datasource를 이용하면 웹어플리케이션 자체에 DB접속을 위한 잡다한 코드를 넣지 않아도 되므로 환경변화에 유연합니다.

우선 컨텍스트(Context)에 데이터소스를 적어줘야 합니다.
컨텍스트 파일의 작성에 대해서는 Tomcat 5.5에서의 <Context>를 참고하시기 바랍니다.
컨텍스트에 아래와 같이 Resource를 자신의 환경에 맞게 적어줍니다.
<?xml version="1.0"?>
<Context docBase="yourapp" path="/yourapp">
<Resource description="Test database connection"
name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="yourid" password="yourpw" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb?autoReconnect=true"/>
</Context>
위에서 driverClassName은 로드할 드라이버를 설정하는 부분입니다.
driverClassName와 url의 값은 Java에서 일반적인 DB 접속시 많이 쓰던 것임을 알 수 있습니다.
name은 프로그램 코드에서 이 데이터소스를 참조하기 위한 이름입니다.

위에서 com.mysql.jdbc.Driver를 사용하였는데 이런 jdbc 드라이버는 톰캣의 기본 라이브러리가 아니므로 $CATALINA_HOME/common/lib 디렉토리에 mysql-connector-java-버전-bin.jar 파일을 넣어줘야 합니다.
DBCP를 위해 필요한 라이브러리는 톰캣에 기본으로 존재하며 naming-factory-dbcp.jar 입니다.

DB 드라이버를 로드하고 DBCP에 대한 복잡한 설정을 하는 프로그램 코딩 없이 설정파일에 기술하는 것만으로 JNDI Datasource로 DBCP를 이용하는데 필요한 준비는 끝났습니다.

이제 간단한 소스를 실행하여 문제없이 동작하는지 테스트 해보겠습니다.

import javax.naming.InitialContext;
import javax.sql.DataSource;

try {
    InitialContext initContext = new InitialContext();
    Context envContext = (Context)initContext.lookup("java:/comp/env");
    DataSource ds = (DataSource)envContext.lookup("jdbc/TestDB"); //위에서 설정한 데이터소스의 name
   
    Connection conn = ds.getConnection();
    System.out.println(conn);
    conn.close();
} catch(Exception e) {
    e.printStackTrace();
}

위의 코드에 문제가 없다면 org.apache.tomcat.dbcp.dbcp.PoolableConnection@15d4de6 와 같은 결과가 출력됩니다.
이제 Connection 객체를 이용해서 기존과 똑같이 데이터베이스 관련 코딩을 하면 됩니다.

JNDI를 이용하여 DataSource를 가져오는 방법은 톰캣만이 가능한것이 아니라 다른 WAS들도 가능합니다. 참조하는 name을 일치시켜주면 기존 프로그램의 코드수정 없이 WAS의 설정파일만 수정하면 됩니다.

* Name [jdbc/TestDB] is not bound in this Context 에러가 발생하면 jdbc/TestDB(해당이름)를 JNDI가 찾을 수 없다는 것으로써 설정의 name이 틀리지 않았는지 확인해보고 문제가 없다면 컨텍스트 파일을 못읽는 것일 수 있으므로 컨텍스트 파일의 위치와 파일명을 확인합니다.

* web.xml의 <resource-ref> 설정에 대한 자료도 봤는데 설정하지 않더라도 동작에 문제가 없었습니다.
Posted by 1010
98..Etc/Etc...2009. 6. 19. 15:18
반응형
책만 보고 설정을 하다 보니 아래 오류가 나와서 알아보니 tomcat 버젼 별 설정과

eclipse 는 설정이 다르더라 .

javax.naming.NameNotFoundException: Name jdbc is not bound in this Context

블로그를 한 100여개 넘도록 알아보니 대충 문제는 알겠는데

문제 해결은 안되고 이것저것 해보다가 6시간만에 문제 해결 ;;



우선 톰켓 5.5* 이상 부터는 Connection Pool 설정시에 server.xml 과 web.xml 에

별도로 내용을 설정할 필요없이 context.xml 설정만 하면 된다 .

eclipse europa 를 쓰면서 답답한 것은 기존 것과 패턴이 많이 바뀌면서

인터넷에 자료가 너무 없다. 해서 다른이에게 도움이 될까해서 남겨놓는다.




일단 http://commons.apache.org/ 사이트에서 아래 commons 파일을 다운 받아서

1. commons-pool-1.4.jar
2. commons-dbcp-1.2.2.jar
3. commons-collections-3.2.jar

C:\workspace\study\WebContent\WEB-INF\lib 에 복사한다.

나는 eclipse 3.3 europa wtp all-in-one 를 설치해서 사용한다.

europa 에서 Dynamic Web Project 로 jsp 파일을 만들게 되면

WebContent 에 jsp 파일이 저장된다.

 
C:\tomcat\conf 안에 보면 context.xml 파일이 있다.

이 파일을 복사해서

C:\workspace\Servers\Tomcat v5.5 Server at localhost-config 안에 복사한다.

현재 나는 eclipse + tomcat 5.5 + mysql 를 설치하여 사용한다.

자신이 사용하는 편한 편집기로 context.xml 을 연 후에

각자의 설치 사항에 맞게 설정하면 된다. 나는 editplus를 사용했다.

그림을 클릭하면 크게 보임

사용자 삽입 이미지


위와 같이
 
<Resource name="jdbc/jsptest"
                  auth="Container"
                  type="javax.sql.DataSource"
                  driverClassName="com.mysql.jdbc.Driver"
                  loginTimeout="10"
                  maxWait="5000"
                  username="jspid"
                  password="0310"
                  testOnBorrow="true"
                  url="jdbc:mysql://localhost:3306/jsptest"
        ></Resource>

를 추가하고 저장하면 설정은 끝이다.

매우 간단한 방법인데 기존 방법대로 설정을 하면서 현재 패치에 적용이 안되는

문제로 참 많은 고생을 하였다.

더더군다나 내가 초보자라 더 어려웠는지도 모르겠다
Posted by 1010
반응형
 \n만 치환하면 안된다 \r\n 전부다 해줘야 한다.--(이것 때문에 고생했슴)

1. textarea 에 엔터값을 그냥 DB에 넣어서 처리 할 경우

---------------------------------------------------

DB상에는 엔터값이 먹힌 상태로 들어간다. 그 값을 나중에 html 코드에 가져오면

그냥 한줄로 출력이 된다.

이 때 <pre>태그를 써서 줄바꿈이 먹게 만들면 될것이다.

하지만 잘 살펴보면 DB상에 저장된 데이터에서 맨 마지막에 엔터가 한번 더 들어가 있는 것을 볼 수 있을 것이다. 따라서 내가 원하는 이쁜 배열은 안나온다..


2. textarea에서 엔터값을 치환<권장하는 방법이다>

----------------------------------------------------

이 부분은 여러 문서가 있다. asp,php,jsp의 처리 방법이 같지 않은거 같다.

여기서 사용하는 함수는 replace 함수이다(함수에 대한 설명은 찾아보삼)

textarea의 name 값이 contents 라 한다면,

그 값을 받는 부분에서 변환을 한다.

(실질적인 JSP 코드가 들어가있는 부분을 말한다.)


String content = request.getParameter("contents");

 전페이지에서 DB쿼리 실행하는 페이지에서 쓴다.

이 부분을 통해 textarea 값을 받아올 수 있따.

textarea 상에서 엔터는 어떤문자로 인식이 되냐면

\r\n 으로 표시가 된다.

이것을 치환을 한다!


contents = contents.replace("\r\n","<br>");

이렇게 하면 엔터가 DB상에 <br>로 바껴서 저장이 되고, html 코드에 가져올 때 자동적으로 <br>태그가 먹혀서 줄바꿈이 된다.


이 방법을 쓴다면, 이 값을 불러오는 페이지에서 아무 처리를 안해도 원하는 결과를

얻을 수 있다

Posted by 1010
01.JAVA/Java2009. 6. 18. 18:43
반응형
[Tip] 오라클 CLOB 데이터 입출력

/**
 CLOB 자료를 오라클 DB에 넣기 위한 자바 소스 파일
 
 1. CLOB 자료형인 column을 오라클의 empty_clob()을 이용해 초기화를 해야 한다.
    : 또는 CLOB column의 기본값을 empty_clob()으로 하던가..
   
 2. setAutoCommit(false)를 꼭 해야 한다.
 
 3. select clob_column from table where pk = value for update
    : for update를 이용해 CLOB column을 lock한다.
    : stream을 이용해 CLOB column을 업데이트 하는동안 다른 process의 접근을 막는다.
    : 또한 stream을 이용해 자료를 넣기 전까지는 실제로 commit되지 말아야 하기 때문에
      2번의 auto commit을 false로 했던 것이다. (이것때문에 하루 보냄 ㅜㅜ;;)
    : 모두 쓰고 나서는 commit() <-- 옵션
    : setAutoCommit(true) <-- 옵션
     
 4. 여기서 특이한 점은 오라클의 jdbc 드라이버의 OracleResultSet과 CLOB을 이용한다는 것이다.
    : java.sql.ResultSet과 java.sql.Clob을 이용하면 오라클 JDBC 드라이버가 해석시에 에러를 발생시킨다.
    : 아마도 오라클 jdbc 드라이버의 문제점이 아닐까 하는 생각이 든다.
    : 아니면 표준과 싸우는 오라클인가? ㅡㅡ;;
   
 5. 나머지 부분은 Stream을 이용한 input과 output이므로 언급을 생략하겠다.
*/

import java.io.*;
import java.net.*;
import java.sql.*;

import oracle.sql.*;
import oracle.jdbc.driver.*;

public class ClobTest {
 public static void main(String[] argv) {
 
  String drv = "oracle.jdbc.driver.OracleDriver";
  String dburl = "jdbc:oracle:thin:@192.168.3.30:1521:GRDB21";
  String user = "scott";
  String password = "tiger";
 
  Connection conn = null;
  Statement st;
  ResultSet rs;
 
  try {
         Class.forName(drv);         
         System.out.println("Drive Loading...");
            conn = DriverManager.getConnection(dburl, user, password);
            System.out.println("Connecting...");
            st = conn.createStatement();
           
            // 입력할 텍스트 만들기
            StringBuffer sb = new StringBuffer();
            String clobTest = "한글 테스트입니다\nIt is difficult\n";
            for (int i = 0; i < 300; i++)
    sb.append(clobTest);
   
   
   
   // 1. CLOB 데이터 입력하기 위해, empty_clob() 생성
            try {
             st.executeUpdate("insert into test_clob values ('02', empty_clob())");
            } catch (Exception ee) {
             ee.printStackTrace(System.out);
            }
   
   // 2. setAutoCommit을 false로 꼭 해야 한다.
   conn.setAutoCommit(false);
   
   
   // 3. CLOB column에 대한 lock을 얻는다.
   rs = st.executeQuery("select desc2 from test_clob where code = '02' for update");
   if (rs. next()) {
   
    // 4. 오라클의 함수들을 사용하기 위해 cast 하였다.
    CLOB cl = ((OracleResultSet)rs).getCLOB("desc2");
   
    // 스트림을 이용한 값 저장
    BufferedWriter writer = new BufferedWriter(cl.getCharacterOutputStream());
    writer.write(sb.toString());
    writer.close();
   }
   conn.commit();
   conn.setAutoCommit(true);
               
   // 입력한 값 읽어 오기    
   rs = st.executeQuery("select * from test_clob where code = '02'");
   
   if (rs.next()) {
    String code = rs.getString("code");
   
    // CLOB column에 대한 스트림을 얻는다.
    Reader rd = rs.getCharacterStream("desc2");
   
    sb = new StringBuffer();
    char[] buf = new char[1024];
    int readcnt;
    while ((readcnt = rd.read(buf, 0, 1024)) != -1) {
     // 스트림으로부터 읽어서 스트링 버퍼에 넣는다.
     sb.append(buf, 0, readcnt);
    }
    rd.close();
   
    System.out.println("code : " + code);
    System.out.println("desc2 : " + sb.toString());
   }
 
 
  }
  catch (Exception e) {
   e.printStackTrace(System.out);
  }
 }
}

Posted by 1010
01.JAVA/Java2009. 6. 18. 14:12
반응형
java.lang.ClassCastException: oracle.sql.CLOB 에러

exception message
oracle.sql.CLOB
exception stack trace
java.lang.ClassCastException: oracle.sql.CLOB
	at project.web.pds.PdsDAOOracle.write(PdsDAOOracle.java:169)

-----------------------------------------------------------------------


시기 : 오라클 CLOB타입으로 DB인서트할때

원인 : tomcat common lib과 WEB-INF lib에 동시에 오라클 드라이버 라이브러리가 들어 있었음.

odbc14.jar


해결책 : tomcat common lib에만 오라클 드라이버를 남기고 나머지는 다 지운다.

Posted by 1010
05.JSP2009. 6. 16. 20:33
반응형
출처 : http://passion818.tistory.com/84

정말 오랜만에 글을 쓰네요..일본에서 돌아오고는 완전히 초 귀차니즘이..;;;
요즘은 우분투를 프로그램 개발용으로 쓰려고 별 짓을 다하고 있는 덕에 이렇게 블로그 등에 기록해 두지 않으면 좋지 않은 머리로 다 기억 못할거 같아 지금까지 삽질하며 구축한 내용을 글로 남기려고 합니다.

일단 시작은 본편인 JSP 환경 구축부터 해서 C/C++, Flex3, APM 설치 등의 순으로 글을 쓰려고 합니다.
우분투 버전은 9.04 Jauty이고 제가 참고 한 자료들이 대부분 8.04이후의 글들을 참고 하였으므로 8.04나 8.10도 잘 될거라고 예상됩니다.
그럼 본 내용으로 들어가보도록 하지요..

[ 참고한 글들 ]

1. JDK 6 설치

JSP 환경을 구축하는데 JDK는 당연히 빠질 수 없겠지요..ㅎㅎ. 여기서 사용할 JDK 패키지는 sun-java6-jdk 패키지로 시냅틱에서 jdk로 검색을 하여 설치하면 아주 간단히 설치가 가능합니다. 예외적인 상황으로는 오픈오피스의 의존성 관계로 OpenJDK가 설치되어 있을것인데 위의 패키지를 설치한 후엔 다음 명령으로 기본 Java를 변경해 주시거나 OpenJDK를 삭제하시면 됩니다.
$ sudo update-alternatives --config java
jdk-doc은 무슨 이유에서인지 에러를 뿜으며 설치가 안되는군요..뭐..api는 자바 사이트에서 보면서 해도 되니 doc은 패스..ㅡㅡ;

JAVA 환경변수 등록
$ sudo gedit /etc/profile

다음 내용을 추가하고 저장
export JAVA_HOME=/usr/lib/jvm/java-6-sun

source명령으로 수정한 profile를 반영합니다.
$ source /etc/profile

2. Tomcat 설치

이제 Java 구동 환경은 구축 되었으니 JSP파일을 구동 시킬 서버를 구축해줘야 하는데 그 역할을 하는 것 이 톰캣 서버이지요.ㅎㅎ 윈도우는 그냥 냅다 다운받아 설치하고 실행시키면 되지만 우분투는 쪼끔 귀찮게 하더군요..ㅡㅡ;;
원 래는 시냅틱에서 검색하여 패키지로 설치하려 했으나..이게 이클립스와 연동시키려니 이래저래 해줘야할 것도 많고 구글 검색을 통해 제가 해본 방법으로는 잘 안되서 결국 리눅스용 톰캣을 인터넷으로 다운받아 설치했습니다. 실제로 서버를 구축해서 서비스를 한다면 추천하고 싶지 않은 방법이지만 단지 공부등의 이유로 간단히 자신의 컴에 JSP구동 환경을 구축하려고 한다면 이방법이 제일 간편할 듯 싶군요.
 
우선 톰캣을 다운로드 합니다. 저의 경우에는 Tomcat 6 버전을 다운로드하였습니다.(교육 과정에서 이 버전을 써서요..ㅎㅎ;;)

다운로드한 디렉토리에서 다음 명령을 입력해 압축을 해제합니다.
$ tar xvfz apache-tomcat-6.0.20.tar.gz

압축 해제한 톰캣 디렉토리를 적당한 위치로 옮깁니다. 저의 경우엔 /usr/local/tomcat6이란 디렉토리를 만들어 옮겼습니다.
$ sudo mkdir /usr/local/tomcat6
$ sudo mv ./apache-tomcat-6.0.20/* /usr/local/tomcat6/

이것으로 톰캣의 설치는 끝났습니다. 이제 톰캣을 구동시키고(Start) 정지시키고(Stop) 재시작(Restart)시킬 스크립트를 작성합니다.
$ sudo gedit /etc/init.d/tomcat6

다음 내용을 입력 후 저장합니다.
export JAVA_HOME=/usr/lib/jvm/java-6-sun
case $1 in
start)
sh /usr/local/tomcat6/bin/startup.sh
;;
stop)
sh /usr/local/tomcat6/bin/shutdown.sh
;;
restart)
sh /usr/local/tomcat6/bin/shutdown.sh
sh /usr/local/tomcat6/bin/startup.sh
;;
esac
exit 0

만든 스크립트 파일을 실행 가능하도록 권한을 부여하면 시냅틱으로 설치한 톰캣 서버처럼 구동이 가능합니다.
$ sudo chomod 755 /etc/init.d/tomcat6
$ sudo /etc/init.d/tomcat6 start
       stop
       restart 이런식의 구동이 가능하게 됩니다.

저 같은 경우에는 이클립스에서 구동하고 정지 시킬 것이기에 톰캣이 우분투가 시작하면서 자동으로 실행 될 필요가 없지만 혹시나 자동으로 실행되길 바라신다면 다음 명령을 추가로 입력하여 링크를 겁니다.
$ sudo ln -s /etc/init.d/tomcat /etc/rc1.d/K99tomcat
$ sudo ln -s /etc/init.d/tomcat /etc/rc2.d/S99tomcat

3. Oracle 10g XE 설치

오라클의 경우엔 저장소가 있기 때문에  소스리스트에 저장소를 추가 후 시냅틱이나 터미널에서 apt-get install 명령으로 간단히 설치가 가능합니다. 원래는 데비안용 패키지인것 같지만 우분투 자체가 데비안을 기반으로 만든 것이여서 그런지 아무 문제 없이 설치가 가능합니다.

시스템 > 관리 > 소프트웨어 소스에서 써드 파티 소프트웨어 탭에서 다음 저장소를 추가합니다.
deb http://oss.oracle.com/debian unstable main non-free #Oracle 10g Express Edition

8.10부터 저장소를 추가하면 해당 저장소의 인증키가 있어야 되는데 오라클의 경우 터미널에서 다음 명령으로 키를 얻어옵니다.
$ sudo wget http://oss.oracle.com/el4/RPM-GPG-KEY-oracle  -O- | sudo apt-key add -
$ sudo aptitude update

이제 오라클을 설치하면 되는데 다국어 지원을 위해 universal버전을 설치합니다. ( 시냅틱에서 oracle로 검색하여 설치하셔도 무방합니다. )
$ sudo aptitude install oracle-xe-universal

설치가 끝나면 이제 본인의 컴에 맞게 설정을 해야겠죠? 다음 명령으로 설정을 합니다.
$ sudo /etc/init.d/oracle-xe configure

다음은 설정 화면으로 [Enter]라고 쓰인 부분에서 엔터키를 치면 기본 설정값을 쓰겠다는 의미입니다. 포트 설정의 경우 톰캣이 8080포트를 사용해야 하므로 포트 충돌을 막기 위해 8087로 설정합니다.
Oracle Database 10g Express Edition Configuration
-------------------------------------------------
This will configure on-boot properties of Oracle Database 10g Express
Edition.  The following questions will determine whether the database should
be starting upon system boot, the ports it will use, and the passwords that
will be used for database accounts.  Press <Enter> to accept the defaults.
Ctrl-C will abort.

Specify the HTTP port that will be used for Oracle Application Express [8080]: 8087

Specify a port that will be used for the database listener [1521]: [ENTER]

Specify a password to be used for database accounts.  Note that the same
password will be used for SYS and SYSTEM.  Oracle recommends the use of
different passwords for each database account.  This can be done after
initial configuration:
Confirm the password:

Do you want Oracle Database 10g Express Edition to be started on boot (y/n) [y]: [ENTER]

Starting Oracle Net Listener...Done
Configuring Database...Done
Starting Oracle Database 10g Express Edition Instance...Done
Installation Completed Successfully.
To access the Database Home Page go to "http://127.0.0.1:8087/apex"
pcandme@behemoth:/etc/apt$ sudo /etc/init.d/oracle-xe configure
Oracle Database 10g Express Edition is already configured

설정이 끝났으면 오라클도 역시 환경변수를 등록합니다.
$ sudo gedit /etc/profile

다음 내용을 추가합니다.
ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
PATH=$PATH:$ORACLE_HOME/bin
export ORACLE_HOME
export ORACLE_SID=XE
export NLS_LANG='KOREAN_KOREA.AL32UTF8'

source명령으로 수정한 profile를 반영합니다.
$ source /etc/profile

여기까지 끝났으면 웹브라우저에 다음 주소를 입력하여 제대로 설치가 되었는지 확인합니다. 올바르게 설치가 되었다면 로그인 페이지가 나올 것입니다.
http://127.0.0.1:8087/apex


4. Eclipse 설치

금방 끝날줄 알았더니 이거..상당히 길어지네요..;; 이제 JSP구동 환경도 구축 되었고 데이터베이스를 구축할 오라클도 설치가 끝났으니 JSP 개발을 위한 IDE인 이클립스를 설치하도록 하지요. 설치할 버전은 3.4 Ganymede 입니다. 우분투의 기본 저장소에 있는 이클립스는 이상하게 아직도 3.2버전을 고집하고 있더군요..ㅡㅡ;; 나중에 플렉스도 설치해야 하므로 전 이클립스 공시 홈페이지에서 Eclipse J2EE버전을 다운로드하였습니다.( 플렉스 설치할 때 알았지만..3.4버전이..버그가 많더군요..;; 뭐 심각한건 없었으므로 괜찮았지만 쪼금 삽질을 했다는..;;; )

톰캣이 정상적으로 설치가 되었다면 이클립스와의 연동은 간단합니다. 다운로드한 이클립스를 압축해제 후 적당한 위치로 옮깁니다. 저는 홈 디렉토리로 옮겼습니다.( 권한 설정등이 귀찮아서..ㅡㅡ;; )


이클립스를 구동하면 퍼스펙티브가 J2EE로 기본 설정되어있어 아래와 같이 화면 하단에 보면 서버탭이 보이실겁니다.


저는 이미 설정을 해서 위와 같이 나왔지만 처음 설정할 때는 위의 서버 탭에서 오른쪽 클릭 > new를 해주시면 다음과 같은 창이 뜨는데 서버 목록에서 Apache를 누르면 연동 가능한 톰캣 목록이 뜹니다.


Tomcat 6버전을 선택하고 Next를 누르면 톰캣이 설치된 경로와 JRE버전을 선택하는 화면이 나오는데 JRE는 기본 그대로 놔두셔도 되지만 JDK를 여러버전이 설치가 되어있다면 사용할 JDK버전에 맞는 JRE를 선택해주셔야 합니다. 톰캣은 아까 설치한 경로를 입력해주시면 됩니다.


문제가 없다면 다음과 같이 서버가 추가 된 화면을 보실 수 있습니다. 서버 구동은 우측에 있는 플레이 버튼처럼 생긴 아이콘을 클릭해주시면 톰캣이 구동 됩니다.


이제 테스트를 위해 JSP 프로젝트를 하나 생성하여 테스트 페이지를 작성한 후 서버를 구동해 실제로 작동하는지 확인하면 되겠군요..
테스트 페이지 작성까지 글을 쓰면 너무 길어지므로( 이미 여기까지도 길지요..;; ) 생략하겠습니다.
이상으로 우분투에서 JSP환경 구축편을 마칩니다. 오랜만에 장문의 글을 쓰려니..힘드네요..@.@

Posted by 1010
01.JAVA/Java2009. 6. 16. 20:16
반응형
multipart form parser - http file upload, database 저장 java class 연재2

이번글에서는 업로드된 파일을 저장할때 database에 record를 함께 insert 하는 기능에 대해서 
설명하겠습니다. 설명하기 전에 이전 글에서 대용량 파일 업로드 기능에 대해서 다시 한번 review하고
다시 자세히 설명하겠습니다.

1. 대용량 파일 업로드 기능 (1G 이상 파일 업로드에도 문제가 없는 기능)
2. 파일 업로드시 upload 진행 상황을 Internet Explorer에서 볼수 있을것 (다음번 글에서 올리겠습니다.)

WCPage.java : JSP page context와 request parameter를 저장하는 java class
WCMultipartFormParser.java : http request stream을 parsing하는 java class
WCMultipartFormElement.java : multipart form lement를 저장하는 java class

// form html 일부분 시작
<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>
// form html 일부분 끝

form을 javascript에서 서버로 submit하면 
아래와 같은 http request stream이 서버로 전달됩니다.

// http request stream 시작
-----------------------------7d82efc203cc
Content-Disposition: form-data; name="_cmd"

uploadFile
-----------------------------7d82efc203cc
Content-Disposition: form-data; name="file"; filename="C:\test.txt"
Content-Type: text/plain

test
-----------------------------7d82efc203cc--
// http request stream 끝

위의 request stream을 parsing하는 pseudo code 입니다.

// pseudo code 시작
JSP page
  -> WCPage.initCtrl
    -> WCPage.initCtrl
      -> WCPage.isMultipart()
      -> WCMultipartFormParser.init()
        -> WCMultipartFormParserparseContent(oRequest)
          -> WCMultipartFormParserparseContentEx(oRequest)
            -> WCMultipartFormParserfindBoundary() : -----------------------------7d82efc203cc 이 부분을 parsing합니다.
            -> WCMultipartFormParserfindHeader() : Content-Disposition: form-data; name="_cmd" 이 부분을 parsing 합니다.
              -> WCMultipartFormElement.setHeader : header 정보를 element에 저장합니다.
            -> WCMultipartFormParser.procContent() : content body를 parsing 합니다.
              -> 임시파일에 파일 저장 : content type이 file인경우
              -> parameter인경우 WCProperties m_rParam 에 parameter 이름과 value를 저장
      -> WCMultipartFormParser.saveFile(sDir)
        -> WCMultipartFormElement.saveFile(sPathFile)
// pseudo code 끝

대용량 파일을 서버에 업로드 하기 위해서는 업로드 되는 파일을 임시 directory에
임시 파일로 저장을 하고 다시 개발자가 원하는 디렉토리로 파일을 이동하는 방식을 
사용합니다. (임시로 저장하는 이유는 memory에 파일을 모두 load하고 있을 수 없기
때문입니다.)
위의 코드에서 procContent에서 파일 내용을 임시 디렉토리에 저장합니다.
WCMultipartFormParser.procContent

사용자가 파일을 임시 디렉토리에서 운영용 file directory로 이동하고자 하면
WCMultipartFormParser.saveFile(sDir) 을 호출합니다.

이 함수를 form에 있는 element들 중에서 file인 경우 이 파일을 사용자가 지정한 sDir로 
이동을 합니다.

// WCMultipartFormParser.saveFile code 시작
public void saveFile(String sDir)
{
    try
    {
        Vector vElement = this.getElements();
        int nCount = WCVector.size(vElement);
        for (int i=0;i<nCount;i++)
        {
            WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
            if (oElmt == null)
            {
                continue;
            }
            if (!oElmt.isFile())
            {
                continue;
            }
            String sTempFileName = oElmt.getCloneFileName();
            if (WCString.isEmpty(sTempFileName))
            {
                continue;
            }
            String sUserDirectoryFile = WCString.buildFilePath(sDir,sTempFileName,"/");
            oElmt.saveFile(sUserDirectoryFile);
        }
    }
    catch (Exception ex)
    {
        WCLog.getInstance().printLog("exception at WCMultipartFormParser.saveFile "+ex.toString());
    }
}        
// WCMultipartFormParser.saveFile code 끝

WCMultipartFormParser.saveFile 에서
WCMultipartFormElement.saveFile을 호출합니다.
WCMultipartFormElement.saveFile 함수는 임시로 저장된 file을 사용자가 지정한 path의 file로
copy한 다음 임시 파일을 삭제하는 코드입니다.

// WCMultipartFormElement.saveFile code 시작
public int saveFile(String sPathFile)
{
    try
    {
        if (sPathFile == null)
            return -1;
        String sDir = WCString.getPath(sPathFile);
        WCSystem oSys = WCSystem.getInstance();
        oSys.CreateDir(sDir);
        String sSaveFileName = sPathFile;
        setSaveFileName(sSaveFileName);
        File oSrcFile = new File(getTempFileName());
        File oDestinationFile = new File(sSaveFileName);
        FileInputStream oFIS = null;
        FileOutputStream oFOS = null;
        try
        {
            oFIS = new FileInputStream(oSrcFile);
            oFOS = new FileOutputStream(oDestinationFile);
            byte[] oBuffer = new byte[1024 * 4];
            int nRead = 0;
            while ((nRead = oFIS.read(oBuffer)) != -1) 
            {
                oFOS.write(oBuffer, 0, nRead);
            }
            oFIS.close();
            oFOS.close();
            oFIS = null;
            oFOS = null;
            oSrcFile.delete();
        }
        catch (Exception e) 
        {
            WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+e.toString());
            if (oFIS != null)
            {
                oFIS.close();
            }
            if (oFOS != null)
            {
                oFOS.close();
            }
            e.printStackTrace(); 
        }
    }
    catch(IOException ioe)
    {
        WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+ioe.toString());
        ioe.printStackTrace();
    }
    return 0;
}
// WCMultipartFormElement.saveFile code 시작

파일을 사용자가 원하는 디렉토리로 복사를 하면서 file 관련 정보를 database에 insert하기 위해서는
WCMultipartFormParser 로 부터 상속받은 class를 정의합니다.
그리고 saveFile method를 재 정의합니다.
그리고 아래와 같이 함수를 정의합니다.

// WCMultipartFormParser에서 상속받은 MyFormParser java class sample 시작
public class MyFormParser extends WCMultipartFormParser 
{
    public void saveFile(String sDir)
    {
        try
        {
            super.saveFile(sDir);
            
            Vector vElement = this.getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                {
                    continue;
                }
                if (!oElmt.isFile())
                {
                    continue;
                }
                String sPhyFile = oElmt.getSaveFileName();
                String sOrgName = oElmt.getName();
                WCStmt oStmt = new WCStmt();
                oStmt.executeUpdate("insert into tb_file (xxx) values(xxx,'"+sFile+"')",null,"WDLDatabasePool");
            }
        }
        catch (Exception ex)
        {
            WCLog.getInstance().printLog("exception at MyFormParser.saveFile "+ex.toString());
        }
    }
}
// WCMultipartFormParser에서 상속받은 MyFormParser java class sample 끝

물론 이와 같이 OOP의 inheritance와 overriding 기법을 사용하지 않고

// inheritance와 overriding 기법을 사용하지 않고 직접 호출방식으로 구현한 소스 일부분 시작
    WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
    oFormParser.setDebug(true);
    oFormParser.init();
    oFormParser.saveFile(sDir);
    
    Vector vElement = this.getElements();
    int nCount = WCVector.size(vElement);
    for (int i=0;i<nCount;i++)
    {
        WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
        if (oElmt == null)
            continue;
        if (oElmt.isFile())
        {
            String sName = oElmt.getName();
            String sPhyFileName = oElmt.getSaveFileName();
            WCStmt oStmt = new WCStmt();
            oStmt.executeQuery("insert into table(xxx,xxx) values(xxx,'"+sPhyFileName+"')",null,sDsn);
        }
    }
// inheritance와 overriding 기법을 사용하지 않고 직접 호출방식으로 구현한 소스 일부분 끝
    
이와 같이 직접 호출하는 방식을 사용해도 됩니다.

아래의 소스는 Web Development Library(http://www.webdevlib.net)에서 소스의 일부분만을 추출하여
재구성한 sample입니다. 첨부한 소스만으로도 어느정도 동작이 가능하지만 WCProperties,WCVector,WCLog,WCSystem,WCEnv
등의 파일은 http://www.webdevlib.net에서 다운받아 사용하십시요
소스의 일부분은 고의로 누락한 것은 아닙니다. 모든 소스를 설명하려니 너무 많기때문에
중요한 부분을 추출하여 sample로 구성하면서 최대한 이해가 쉽도록 재구성을 하였습니다.

제공하는 sample code는 3개의 파일로 구성됩니다

file_upload_progress1.jsp
WCMultipartFormParser.java
WCMultipartFormElement.java

아래의 sample에서 개발자는 WCMultipartFormParser.java 이부분에서 multipart form을 parsing하는 부분만을
참고하여 사용할 수도 있을 것입니다.

아무튼 개발자에게 유용한 코드가 되길 바랍니다.

// file_upload_progress1.jsp 소스 시작
<%@ page language="java" import="wdl.*,java.util.*,java.sql.*,java.lang.*,java.io.*,java.io.File " contentType="text/html; charset=EUC-KR"%>
<%
    WCPage oPage = new WCPage();
    if (oPage.initCtrl(pageContext) > 0)
    {
        return;
    }
%>
<%@ include file="/wdl/src/java/WCMultipartFormParser.java"%>
<%@ include file="/wdl/src/java/WCMultipartFormElement.java"%>
<%!
public class WCPage
{
    public int initCtrl(javax.servlet.jsp.PageContext oPageContext)
    {
        return initCtrl(
            (javax.servlet.http.HttpServletRequest)oPageContext.getRequest()
            ,(javax.servlet.http.HttpServletResponse)oPageContext.getResponse()
            ,(javax.servlet.jsp.JspWriter)oPageContext.getOut()
            ,(javax.servlet.http.HttpSession)oPageContext.getSession()
            ,(javax.servlet.ServletContext)oPageContext.getServletContext()
            ,oPageContext
            ,(javax.servlet.ServletConfig)oPageContext.getServletConfig()
            );
    }
    public int initCtrl(
        javax.servlet.http.HttpServletRequest oRequest
        ,javax.servlet.http.HttpServletResponse oResponse
        ,javax.servlet.jsp.JspWriter oOut
        ,javax.servlet.http.HttpSession oSession
        ,javax.servlet.ServletContext oApplication
        ,javax.servlet.jsp.PageContext oPageContext
        ,javax.servlet.ServletConfig oConfig)
    {
        try
        {
            m_request = oRequest;
            m_response = oResponse;
            m_out = oOut;
            m_session = oSession;
            m_application = oApplication;
            m_pageContext = oPageContext;
            m_config = oConfig;
            
            if (isMultipart())
            {
                WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
                oFormParser.setDebug(true);
                oFormParser.init();
                byte[] btDebugBuf = oFormParser.getDebugBuf();
                String sDebug = new String(btDebugBuf);
                this.printOut("<pre>");
                this.printOut(sDebug);
                this.printOut("</pre>");
                
                WCProperties rParam = oFormParser.getParam();
                this.printOut(rParam.serializeOut());

                String sDir = "c:/tmp3";
                oFormParser.saveFile(sDir);
                return 1;
            }
        }
        catch (Exception ex)
        {
        }
        return 0;
    }
    public javax.servlet.http.HttpServletRequest m_request = null; 
    public javax.servlet.http.HttpServletResponse m_response = null; 
    public javax.servlet.jsp.JspWriter m_out = null; 
    public javax.servlet.http.HttpSession m_session = null; 
    public javax.servlet.ServletContext m_application = null; 
    public javax.servlet.jsp.PageContext m_pageContext = null; 
    public javax.servlet.ServletConfig m_config = null; 
    
    public javax.servlet.http.HttpSession getSession()
    {
        return m_session;
    }
    public javax.servlet.http.HttpServletRequest getRequest()
    {
        return m_request;
    }
    public javax.servlet.jsp.PageContext getPageContext()
    {
        return m_pageContext;
    }

    public boolean isMultipart()
    {
        HttpServletRequest oRequest = (javax.servlet.http.HttpServletRequest)m_request;
        String content_type = oRequest.getHeader("content-type");
        if (WCString.indexOf(WCString.toUpper(content_type),"MULTIPART") == 0)
        {
            return true;
        }
        return false;
    }
}
%>
<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>
<a href="javascript:uploadFile();">upload the file</a>
<iframe id="ifrmAction" name="ifrmAction" width="0" height="0"></iframe> 

<script>
function uploadFile()
{
    var fParam = window.document.fParam;
    fParam._cmd.value = "uploadFile";
    fParam.method = "post";
    fParam.target = "_blank";
    fParam.submit();
}
</script>
// file_upload_progress1.jsp 소스 끝



// WCMultipartFormParser.java 소스 시작
package wdl;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;
    public class WCMultipartFormParser 
    {
        public String m_sCharset;
        private HttpServletResponse resp;
        private ServletContext m_oApp;
        public Vector m_vElement = null;
        public WCProperties m_rParam = null;
        public WCPage m_oPage = new WCPage();
        public WCMultipartFormParser() 
        {
            refresh();
        }
        public WCMultipartFormParser(WCPage oPage) 
        {
            refresh();
            setPage(oPage);
        }
        public void init()
        {
            WCPage oPage = getPage();
            if (oPage == null)
                return;
            HttpServletRequest oRequest = (javax.servlet.http.HttpServletRequest)oPage.getRequest();
            parseContent(oRequest);
        }
        public void init(WCPage oPage)
        {
            setPage(oPage);
            init();
        }
        public int m_nContentLength = 0;
        public byte[] m_btBuf = null;
        public int m_nBufIdx = 0;
        public int m_nBoundaryLen = 0;
        public byte m_btBoundary[] = null;
        public int m_nBufReadSize = 0;
        public int m_nBufAllocSize = 1024*64;
        public int m_nCurrentBuffer = 0; 
        public int m_nBufferCount = 0;
        public int m_nAccumRead = 0;
        public InputStream m_oInputStream = null;
        public int m_nAccumBufIdx = 0;
        public String getEnvValue(String sProp)
        {
            WCEnv env = WCEnv.getInstance();
            if (env != null)
            {
                WCProperties rcd = env.getProperties();
                if (rcd != null)
                {
                    String sVal = rcd.getStrValue(sProp);
                    return sVal;
                }
            }
            return "";
        }
        public void refresh()
        {
            m_vElement = new Vector();
            m_rParam = new WCProperties();
            String sSrcCharset = getEnvValue("charset"); 
            if (WCString.isEmpty(sSrcCharset))
            {
                sSrcCharset = "KSC5601"; 
            }
            m_sCharset = sSrcCharset;
            m_nContentLength = 0;
            m_btBuf = null;
            m_nBufIdx = 0;
            m_nBoundaryLen = 0;
            m_btBoundary = null;
            m_nBufReadSize = 0;
            m_nBufAllocSize = 1024*64;
            m_nCurrentBuffer = 0; 
            m_nAccumRead = 0;
            m_oInputStream = null;
            m_nAccumBufIdx = 0;
            m_nBufferCount = 0;
            m_nPrevAccumBufIdx = 0;
        }
        public byte[] setByte(byte btBuf[],int nIdx,byte btChar)
        {
            {
                int nSize = 0;
                if (btBuf != null)
                    nSize = btBuf.length;
                if (nIdx >= nSize)
                {
                    int nMax = nIdx+32;
                    byte btNew[] = new byte[nMax];
                    for (int i=0;i<nMax;i++)
                    {
                        btNew[i] = 0;
                    }
                    for (int i=0;i<nSize;i++)
                    {
                        btNew[i] = btBuf[i];
                    }
                    btNew[nIdx] = btChar;
                    btBuf = btNew;
                }
                else
                {
                    btBuf[nIdx] = btChar;
                }
                return btBuf;
            }
        }
        public byte[] m_btDebugBuf = null;
        public byte[] getDebugBuf()
        {
            return m_btDebugBuf;
        }
        public byte[] append(byte btBuf[],byte btAppend[],int nLen)
        {
            try
            {
                if (btAppend == null)
                    return null;
                if (btBuf == null)
                {
                    btBuf = new byte[nLen];
                }
                int nSize = btBuf.length;
                int nNewSize = nSize+nLen;
                byte btNew[] = new byte[nNewSize];
                for (int i=0;i<nNewSize;i++)
                {
                    btNew[i] = 0;
                }
                for (int i=0;i<nSize;i++)
                {
                    btNew[i] = btBuf[i];
                }
                for (int i=0;i<nLen;i++)
                {
                    btNew[i+nSize] = btAppend[i];
                }
                btBuf = btNew;
                return btBuf;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.append "+ex.toString());
            }
            return null;
        }
        public byte[] copyBytes(byte btSrc[],int nStartIdx,int nEndIdx)
        {
            try
            {
                int nLen = nEndIdx-nStartIdx;
                if (nLen <= 0)
                    return null;
                int nAlloc = nLen;
                byte btNew[] = new byte[nAlloc];
                for (int i=0;i<nAlloc;i++)
                {
                    btNew[i] = 0;
                }
                for (int i=0;i<nLen;i++)
                {
                    btNew[i] = btSrc[i+nStartIdx];
                }
                return btNew;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.copyBytes "+ex.toString());
            }
            return null;
        }
        public void parseContent(HttpServletRequest oRequest) 
        {
            try
            {
                Vector vDataHeader = parseContentEx(oRequest);
            }
            catch(Exception crfe)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.parseContent "+crfe.toString());
                crfe.printStackTrace();
            }
        }
       
        public void setResponse(HttpServletResponse resp) 
        {
            this.resp = resp;
        }
        public void setContext(ServletContext oApp) 
        {
            this.m_oApp = oApp;
        }
        public boolean findBoundary()
        {
            try
            {
                m_btBoundary = null;
                m_nBoundaryLen = 0;
                int nLen = 0;
                m_btBoundary = setByte(m_btBoundary,nLen,(byte)13); 
                nLen ++;
                m_btBoundary = setByte(m_btBoundary,nLen,(byte)10); 
                nLen ++;
                boolean bBoundaryFound = false;
                while (isEof() != true)
                {
                    byte btByte = getByte();
                    if (btByte == 13)
                    {
                        bBoundaryFound = true;
                        m_nBoundaryLen = nLen;
                        getByte();
                        break;
                    }
                    m_btBoundary = setByte(m_btBoundary,nLen,btByte);
                    nLen ++;
                }
                if (bBoundaryFound == true)
                {
                    m_btBoundary = copyBytes(m_btBoundary,0,nLen);
                    return true;
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.findBoundary "+ex.toString());
            }
            return false;
        }
        public String findHeader()
        {
            try
            {
                int nLen = 0;
                byte btHeader[] = null;
                boolean bFound = false;
                byte btByte = 0;
                byte btByte2 = 0;
                while (isEof() != true)
                {
                    btByte = getByte();
                    btByte2 = getByte(); 
                    btByte2 = getByte(); 
                    putBackByte();
                    putBackByte();
                    if (btByte == 13 && btByte2 == 13) 
                    {
                        getByte();
                        getByte();
                        getByte(); 
                        bFound = true;
                        break;
                    }
                    btHeader = setByte(btHeader,nLen,btByte);
                    nLen ++;
                }
                btHeader = copyBytes(btHeader,0,nLen);
                String sDataHeader = new String(btHeader,m_sCharset); 
                return sDataHeader;    
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.findHeader "+ex.toString());
            }
            return null;
        }
        public boolean isBoundary()
        {
            try
            {
                int boundaryKeyPosition = 0;
                boundaryKeyPosition = 0;
                boolean binaryEndFound = false;
                binaryEndFound = false;
                byte btByte = (byte)0;
                int nLen = 0;
                while (isEof() != true)
                {
                    btByte = getByte();
                    nLen ++;
                    if (btByte == m_btBoundary[boundaryKeyPosition])
                    {
                        if (boundaryKeyPosition == m_nBoundaryLen-1 )
                        {
                            binaryEndFound = true;
                            getByte(); 
                            getByte(); 
                            break;
                        }
                        boundaryKeyPosition++;
                    }
                    else
                    {
                        for (int i=0;i<nLen;i++)
                        {
                            putBackByte();
                        }
                        break;
                    }
                }
                return binaryEndFound;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.isBoundary "+ex.toString());
            }
            return false;
        }
        public void putBackByte()
        {
            m_nBufIdx --;
            m_nAccumBufIdx --;
            if (m_nBufIdx < 0)
            {
                m_nCurrentBuffer --;
                if (m_nCurrentBuffer < 0)
                {
                }
                m_nBufIdx = (m_nBufAllocSize/2) - 1;
            }
        }
        public boolean m_bDebug = false;
        public void setDebug(boolean bDebug)
        {
            m_bDebug = bDebug;
        }
        public boolean isDebug()
        {
            return m_bDebug;
        }
        public boolean isEof()
        {
            if (m_nAccumBufIdx < m_nContentLength)
            {
                return false;
            }
            return true;
        }
        public byte getByte() throws Exception
        {
            byte btData = getByteEx();
            setProgress(m_nAccumBufIdx);
            return btData;
        }
        public byte getByteEx() throws Exception
        {
            try
            {
                if (m_oInputStream == null)
                {
                    m_oInputStream = m_oPage.getRequest().getInputStream();
                }
                if (m_btBuf == null)
                {
                    m_btBuf = new byte[m_nBufAllocSize+32];
                    if (m_btBuf == null)
                    {
                        return (byte)0;
                    }
                    for (int i=0;i<m_nBufAllocSize+32;i++)
                    {
                        m_btBuf[i] = (byte)0;
                    }
                }
                if (m_nBufIdx >= m_nBufReadSize && m_nAccumRead < m_nContentLength && m_nBufferCount == m_nCurrentBuffer)
                {
                    if (m_nBufReadSize == m_nBufAllocSize/2)
                    {
                        m_nBufReadSize = 0;
                        m_nCurrentBuffer ++;
                        m_nBufferCount ++;
                    }
                    int nMaxRead = m_nBufAllocSize/2 - m_nBufReadSize; 
                    if (nMaxRead > m_nContentLength-m_nAccumRead)
                    {
                        nMaxRead = m_nContentLength-m_nAccumRead;
                    }
                    int nRead = m_oInputStream.read(m_btBuf
                        ,(m_nCurrentBuffer%2)*(m_nBufAllocSize/2) + m_nBufReadSize
                        ,nMaxRead);
                    if (this.isDebug())
                    {
                        m_btDebugBuf = this.append(m_btDebugBuf,m_btBuf,nRead);
                    }
                    m_nBufReadSize += nRead;
                    m_nAccumRead += nRead;
                    if (m_nBufReadSize >= m_nBufAllocSize/2)
                    {
                    }
                    m_nBufIdx = m_nBufIdx % (m_nBufAllocSize/2);
                }
                byte btByte = m_btBuf[(m_nCurrentBuffer%2)*(m_nBufAllocSize/2) + m_nBufIdx];
                m_nBufIdx ++;
                if (m_nBufIdx == m_nBufAllocSize/2 && m_nCurrentBuffer < m_nBufferCount)
                {
                    m_nCurrentBuffer ++;
                    m_nBufIdx = 0;
                }
                m_nAccumBufIdx ++;
                return btByte;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.getByteEx "+ex.toString());
                setProgress(m_nContentLength);
                Exception oEx = new Exception("exception at getByte");
                throw oEx;
            }
        }
        public int procContent()
        {
            try
            {
                if (m_oCurElement.isFile())
                {
                    try
                    {
                        FileOutputStream oFileStream = m_oCurElement.createTempFile();
                        if (oFileStream == null)
                        {
                            return -1;
                        }
                        int nBufSize = 1024*4;
                        byte[] btBuf = new byte[nBufSize];
                        int nLen = 0;
                        byte btByte = 0;
                        while (isEof() != true)
                        {
                            btByte = getByte();
                            if (btByte == (byte)13) 
                            {
                                putBackByte();
                                if (isBoundary() == true)
                                {
                                    break;
                                }
                                btByte = getByte(); 
                            }
                            btBuf[nLen] = btByte;
                            nLen ++;
                            if (nLen >= nBufSize)
                            {
                                if (oFileStream != null)
                                {
                                    oFileStream.write(btBuf,0,nBufSize);
                                }
                                nLen = 0;
                            }
                        }
                        if (nLen > 0)
                        {
                            if (oFileStream != null)
                            {
                                oFileStream.write(btBuf,0,nLen);
                            }
                        }
                        m_oCurElement.closeTempFile();
                    }
                    catch (Exception ex)
                    {
                        WCLog.getInstance().printLog("exception at WCMultipartFormParser.procContent "+ex.toString());
                        m_oCurElement.closeTempFile();
                        m_oCurElement.deleteTempFile();
                        return -1;
                    }
                }
                else
                {
                    byte btContent[] = null;
                    int nLen = 0;
                    byte btByte = 0;
                    while (isEof() != true)
                    {
                        if (isBoundary() == true)
                            break;
                        btByte = getByte();
                        btContent = setByte(btContent,nLen,btByte);
                        nLen ++;
                    }
                    String sValue = null;
                    if (nLen > 0)
                    {
                        btContent = copyBytes(btContent,0,nLen);
                        sValue = new String(btContent,m_sCharset);
                    }
                    else
                    {
                        sValue = "";
                    }
                    String sProp = m_oCurElement.getFieldName();
                    if (btContent != null)
                    {
                    }
                    else
                    {
                    }
                    if (m_rParam == null)
                    {
                        m_rParam = new WCProperties();
                    }
                    m_rParam.addValue(sProp,sValue);
                    m_oCurElement.setValue(sValue);
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.procContent "+ex.toString());
                return -1;
            }
            return 0;
        }
        public WCMultipartFormElement m_oCurElement = null;
        public Vector parseContentEx(HttpServletRequest oRequest) 
        {
            int nLen = oRequest.getContentLength();
            setContentLength(nLen);
            m_nBufIdx = 0;
            m_btBoundary = null;
            m_nBoundaryLen = 0;
            int nState = 0; 
            try
            {
                m_nBufReadSize = 0;
                int nRead = 0;
                m_oInputStream = oRequest.getInputStream();
                while (isEof() != true)
                {
                    if (nState == 0)
                    {
                        findBoundary();
                        nState = 100;
                    }
                    else if (nState == 100)
                    {
                        String sHeader = findHeader();
                        if (sHeader != null)
                        {
                            nState = 200;
                            m_oCurElement = new WCMultipartFormElement(this);
                            m_oCurElement.setHeader(sHeader);
                            if (m_vElement == null)
                                m_vElement = new Vector();
                            m_vElement.addElement(m_oCurElement);
                        }
                        nState = 200;
                    }
                    else if (nState == 200)
                    {
                        int nRet = procContent();
                        if (nRet < 0)
                        {
                        }
                        nState = 100;
                    }
                }
            }
            catch(IOException ioe)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.parseContentEx "+ioe.toString());
                ioe.printStackTrace();
            }
            setProgress(m_nAccumBufIdx);
            return m_vElement;
        }
        public Vector getElements()
        {
            return m_vElement;
        }
        public String getFileName()
        {
            Vector vElement = getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                    continue;
                if (oElmt.isFile())
                {
                    return oElmt.getName();
                }
            }
            return null;
        }
        public void deleteTempFile()
        {
            Vector vElement = getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                    continue;
                if (oElmt.isFile())
                {
                    oElmt.deleteTempFile();
                }
            }
        }
        public String getPathName()
        {
            Vector vElement = getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                    continue;
                if (oElmt.isFile())
                {
                    return oElmt.getPathName();
                }
            }
            return null;
        }
        
        public int getFileCount()
        {
            try
            {
                int nRet = 0;
                Vector vElement = getElements();
                int nCount = WCVector.size(vElement);
                for (int i=0;i<nCount;i++)
                {
                    WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                    if (oElmt == null)
                        continue;
                    if (oElmt.isFile())
                    {
                        nRet ++;
                    }
                }
                return nRet;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.getFileCount "+ex.toString());
            }
            return 0;
        }
        public void setCharset(String sCharset)
        {
            m_sCharset = sCharset;
        }        
        public String getCharset()
        {
            return m_sCharset;
        }
        public WCProperties getParam()
        {
            if (m_rParam == null)
                m_rParam = new WCProperties();
            return m_rParam;
        }
        public WCPage getPage()
        {
            return m_oPage;
        }
        public void setPage(WCPage oPage)
        {
            m_oPage = oPage;
        }
        public int getContentLength()
        {
            return m_nContentLength;
        }
        public int getRead()
        {
            return m_nAccumBufIdx;
        }
        public void setContentLength(int nLen)
        {
            m_nContentLength = nLen;
            if (m_oPage != null)
            {
                String sLen = new String(""+m_nContentLength);
                HttpSession oSession = m_oPage.getSession();
                if (oSession != null)
                {
                    oSession.putValue("wdl.WCMultipartFormParser.contentLength",sLen);
                }
            }
        }
        public int m_nPrevAccumBufIdx = 0;
        public void setProgress(int nParam)
        {
            int nRead = nParam;  
            m_nAccumBufIdx = nRead;
            if (m_nAccumBufIdx - m_nPrevAccumBufIdx < 1024 && (m_nAccumBufIdx < m_nContentLength))
            {
                return;
            }
            m_nPrevAccumBufIdx = m_nAccumBufIdx;
            if (m_oPage != null)
            {
                String sLen = new String(""+m_nAccumBufIdx);
                HttpSession oSession = m_oPage.getSession();
                if (oSession != null)
                {
                    oSession.putValue("wdl.WCMultipartFormParser.read",sLen);
                }
            }
        }        
        public void saveFile(String sDir)
        {
            try
            {
                Vector vElement = this.getElements();
                int nCount = WCVector.size(vElement);
                for (int i=0;i<nCount;i++)
                {
                    WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                    if (oElmt == null)
                    {
                        continue;
                    }
                    if (!oElmt.isFile())
                    {
                        continue;
                    }
                    String sTempFileName = oElmt.getCloneFileName();
                    if (WCString.isEmpty(sTempFileName))
                    {
                        continue;
                    }
                    String sUserDirectoryFile = WCString.buildFilePath(sDir,sTempFileName,"/");
                    oElmt.saveFile(sUserDirectoryFile);
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.saveFile "+ex.toString());
            }
        }        
    }
// WCMultipartFormParser.java 소스 끝

// WCMultipartFormElement.java 소스 시작
package wdl;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;
    public class WCMultipartFormElement 
    {
        private boolean m_bFile = false;
        private String fieldName = null;
        private String fullPathName = null;
        private String m_sFileName = null;
        private String fileExtension = null;
        private String pathName = null;
        private String contentType = null;
        private String contentDisposition = null;
        private String mimeType = null;
        private String mimeSubType = null;
        private String m_sValue = null;
        public WCMultipartFormParser m_oParser;
        public WCMultipartFormElement(WCMultipartFormParser oParser) 
        {
            setMultipartFormParser(oParser);
            m_sValue = null;
            m_rUserData = new WCProperties();
            m_oFileOutputStream = null;
        }
        public void setMultipartFormParser(WCMultipartFormParser oParser)
        {
            m_oParser = oParser;
        }
        public WCMultipartFormParser getMultipartFormParser()
        {
            return m_oParser;
        }
        public FileOutputStream createTempFile()
        {
            try
            {        
                String sSourceFileName = getFileName();
                if (WCString.isEmpty(sSourceFileName))
                {
                    return null;
                }
                java.io.File oFile = null;
                m_sTempFileName = getTempFile(sSourceFileName);
                oFile = new java.io.File(m_sTempFileName);
                m_oFileOutputStream = new FileOutputStream(oFile);
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.createTempFile "+ex.toString());
            }
            return m_oFileOutputStream;
        }
        public void closeTempFile()
        {
            try
            {
                if (m_oFileOutputStream != null)
                {
                    m_oFileOutputStream.close();
                }
                m_oFileOutputStream = null;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.closeTempFile "+ex.toString());
            }
        }
        public FileOutputStream getTempFileOutputStream()
        {
            FileOutputStream oRet = null;
            oRet = m_oFileOutputStream;
            return oRet;
        }    
        public void setHeader(String headerString) 
        {
            try
            {
                if (headerString == null)
                    return;
                this.m_bFile = headerString.indexOf("filename=\"") > 0;
                int startPosition = headerString.indexOf("name=\"") + "name=\"".length();
                int endPosition = headerString.indexOf("\"", startPosition);
                if( (startPosition > 0) && (endPosition > 0) )
                {
                    this.fieldName = headerString.substring(startPosition, endPosition);
                }
                if (this.isFile())
                {
                    startPosition = headerString.indexOf("filename=\"") + "filename=\"".length();
                    endPosition = headerString.indexOf("\"", startPosition);
                    if( (startPosition > 0) && (endPosition > 0) )
                    {
                        this.fullPathName = headerString.substring(startPosition, endPosition);
                    }
                    startPosition = headerString.indexOf("Content-Type: ") + "Content-Type: ".length();
                    if( startPosition > 0 )
                    {
                        this.contentType = headerString.substring(startPosition);
                    }
                    startPosition = headerString.indexOf("Content-Disposition: ") + "Content-Disposition: ".length();
                    endPosition = headerString.indexOf(";", startPosition);
                    this.contentDisposition = headerString.substring(startPosition, endPosition);
                    if ((startPosition = this.fullPathName.lastIndexOf(47)) > 0)
                    {
                        this.m_sFileName = this.fullPathName.substring(startPosition + 1);
                    }
                    else if((startPosition = this.fullPathName.lastIndexOf(92)) > 0)
                    {
                        this.m_sFileName = this.fullPathName.substring(startPosition + 1);
                    }
                    else 
                    {
                        this.m_sFileName = this.fullPathName;
                    }
                    if((startPosition = this.m_sFileName.lastIndexOf(46)) > 0 )
                    {
                    this.fileExtension = this.m_sFileName.substring(startPosition+1);
                    }
                    else
                    {
                    this.fileExtension = "";
                    }
                    if((startPosition = this.contentType.indexOf("/")) > 0)
                    {
                        this.mimeType = this.contentType.substring(0,startPosition);
                        this.mimeSubType = this.contentType.substring(startPosition+1);
                    }
                    else
                    {
                        this.mimeType = this.contentType;
                        this.mimeSubType = this.contentType;
                    }
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.WCMultipartFormElement "+ex.toString());
            }
        }
        public boolean isFile() 
        {
            return this.m_bFile;
        }
        public boolean isValidFile()
        {
            if (this.m_bFile == true && !WCString.isEmpty(getName()))
            {
                return true;
            }
            return false;
        }
        public String getFieldName() 
        {
            return this.fieldName;
        }
        public String getFullPathName() 
        {
            return this.fullPathName;
        }
        public String getFileName() 
        {
            return this.m_sFileName;
        }
        public String getName()
        {
            return getFileName();
        }
        public String getPathName()
        {
            return this.pathName;
        }
        public String getFileExtension() 
        {
            return this.fileExtension;
        }
        public String getContentType() 
        {
            return this.contentType;
        }
        public String getContentDisposition() 
        {
            return this.contentDisposition;
        }
        public String getMimeType() 
        {
            return this.mimeType;
        }
        public String getMimeSubType() 
        {
            return this.mimeSubType;
        }
        public void setValue(String sValue)
        {
            m_sValue = sValue;
        }
        public String getValue()
        {
            return m_sValue;
        }
        private int size = 0;
        private byte [] contents;
        public WCProperties m_rUserData = new WCProperties();
       
        public String m_sTempDirectory = "";
        public void setTempDirectory(String sVal)
        {
            m_sTempDirectory = sVal;
        }
        public String getTempDirectory()
        {
            if (WCString.isEmpty(m_sTempDirectory))
            {
                m_sTempDirectory = WCString.nullCheck(getEnvValue("tempdir"),getEnvValue("wdl.tempdir"));
                if (WCString.isEmpty(m_sTempDirectory))
                {
                    String sPath = getHome();
                    m_sTempDirectory = WCString.buildFilePath(sPath,"wdl/tmp","/");
                }
            }
            return m_sTempDirectory;
        }
        public String getHome()
        {
            String sHome = WCString.trim(getEnvValue("wdl.home"));
            if (WCString.isEmpty(sHome))
            {
                sHome = WCString.left(WCEnv.getInstance().getEnvFile(),"/WEB-INF");
            }
            return sHome;
        }
        public String getTempName()
        {
            try
            {
                java.util.Date dat = new java.util.Date();
                java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat ("yyyy");
                String sYear = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("MM");
                String sMonth = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("dd");
                String sDate = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("HH");
                String sHour = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("mm");
                String sMin = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("ss");
                String sSec = formatter.format(dat);            
                int nRand0 = (int)(Math.random()*10000);
                int nRand1 = (int)(Math.random()*10000);
                int nRand2 = (int)(Math.random()*10000);
                String sName = sYear+sMonth+sDate+sHour+sMin+sSec+"_"+nRand0+"_"+nRand1+"_"+nRand2;
                return sName;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.getTempName "+ex.toString());
            }
            return "";
        }
        public String getTempFile(String sSourceFileName)
        {
            try
            {
                String sExt = WCString.nullCheck(WCString.getFileExt(sSourceFileName),"");
                String sName = getTempName();
                if (!WCString.isEmpty(sExt))
                {
                    sName += "."+sExt;
                }
                String sDir = getTempDirectory();
                WCSystem oSys = WCSystem.getInstance();
                oSys.CreateDir(sDir);            
                String sRet = WCString.buildFilePath(sDir,sName,"/");
                return sRet;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.getTempFile "+ex.toString());
            }
            return null;
        }
        public String getEnvValue(String sProp)
        {
            WCEnv env = WCEnv.getInstance();
            if (env != null)
            {
                WCProperties rcd = env.getProperties();
                if (rcd != null)
                {
                    String sVal = rcd.getStrValue(sProp);
                    return sVal;
                }
            }
            return "";
        }
        public FileOutputStream m_oFileOutputStream = null;
        public String m_sTempFileName = null;
       
        public String getTempFileName()
        {
            return m_sTempFileName;
        }
        public int getSize() 
        {
            return this.size;
        }
           
        public void setSize(int size) 
        {
            this.size = size;
        }
           
        public byte [] getContents() 
        {
            return this.contents;
        }
           
        public byte getContentByte(int index) 
        {
            return this.contents[index];
        }
        public void setContents(byte[] contents) 
        {
            this.contents = contents;
        }
           
        public void setContentByte(int index, byte content) 
        {
            this.contents[index] = content;
        }
        public String m_sSaveFileName = null;
        public String getSaveFileName()
        {
            return m_sSaveFileName;
        }
        public void setSaveFileName(String sFileName)
        {
            m_sSaveFileName = sFileName;
        }
        public int saveFile(String sPathFile)
        {
            try
            {
                if (sPathFile == null)
                    return -1;
                String sDir = WCString.getPath(sPathFile);
                WCSystem oSys = WCSystem.getInstance();
                oSys.CreateDir(sDir);
                String sSaveFileName = sPathFile;
                setSaveFileName(sSaveFileName);
                File oSrcFile = new File(getTempFileName());
                File oDestinationFile = new File(sSaveFileName);
                FileInputStream oFIS = null;
                FileOutputStream oFOS = null;
                try
                {
                    oFIS = new FileInputStream(oSrcFile);
                    oFOS = new FileOutputStream(oDestinationFile);
                    byte[] oBuffer = new byte[1024 * 4];
                    int nRead = 0;
                    while ((nRead = oFIS.read(oBuffer)) != -1) 
                    {
                        oFOS.write(oBuffer, 0, nRead);
                    }
                    oFIS.close();
                    oFOS.close();
                    oFIS = null;
                    oFOS = null;
                    oSrcFile.delete();
                }
                catch (Exception e) 
                {
                    WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+e.toString());
                    if (oFIS != null)
                    {
                        oFIS.close();
                    }
                    if (oFOS != null)
                    {
                        oFOS.close();
                    }
                    e.printStackTrace(); 
                }
            }
            catch(IOException ioe)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+ioe.toString());
                ioe.printStackTrace();
            }
            return 0;
        }
        public WCProperties getUserData()
        {
            return m_rUserData;
        }
        public void setUserData(String sProp,String sValue)
        {
            if (m_rUserData == null)
                m_rUserData = new WCProperties();
            m_rUserData.setValue(sProp,sValue);
        }
        public void setUserData(String sProp,int nValue)
        {
            if (m_rUserData == null)
                m_rUserData = new WCProperties();
            m_rUserData.setValue(sProp,nValue);
        }
        public void deleteTempFile()
        {
            try
            {
                File oFile = new File(m_sTempFileName);
                boolean bSucc = oFile.delete(); 
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.deleteTempFile "+ex.toString());
            }
        }
        public String getCloneFileName()
        {
            String sFullPathName = this.getFullPathName();
            if (WCString.isEmpty(sFullPathName))
        {
            return null;
        }
        String sExt = WCString.getFileExt(sFullPathName);
            String sTempName = this.getTempName();
            String sTempFileName = sTempName+"."+sExt;
            return sTempFileName;
        }
        public long m_nFileSize = -1;
        public long getFileSize()
        {
            if (m_nFileSize > (long)0)
                return m_nFileSize;
            String sFileName = getSaveFileName();
            try
            {
                File oFile = new File(sFileName);
                if (oFile != null)
                {
                    m_nFileSize = oFile.length();
                    return m_nFileSize;
                }
            }
            catch (Exception ex)
            {
            }
            sFileName = m_sTempFileName;
            try
            {
                File oFile = new File(sFileName);
                if (oFile != null)
                {
                    m_nFileSize = oFile.length();
                    return m_nFileSize;
                }
            }
            catch (Exception ex)
            {
            }
            return 0;
        }
    }
// WCMultipartFormElement.java 소스 끝

첨부파일 : file_upload_progress1.zip

file_upload_progress1.jsp
WCMultipartFormParser.java
WCMultipartFormElement.java

출처 : 고급 웹 UI 개발 라이브러리 Web Development Library 소스공개 : http://www.webdevlib.net
첨부파일 :  
multipart_form_parser2.zip   [7 KB]   다운로드 횟수 28 회
Posted by 1010
01.JAVA/Java2009. 6. 16. 20:15
반응형
출처 : http://www.javanuri.net/devforum/boardView.jsp?pg=4&menuId=12&Id=305711&gb=qna

multipart form parser - http file upload 기능 java class 연재1

다음과 같은 기능의 file upload 프로그램을 java code를 소개하겠습니다.

1. 대용량 파일 업로그 기능 (1G 이상 파일 업로드에도 문제가 없는 기능)
2. 파일 업로드시 upload 진행 상황을 Internet Explorer에서 볼수 있을것

위의 기능 중에서 이번 글에서는 1번 기능에 대해서 설명을 하겠습니다.
2번 기능은 AJAX 기능을 이요하여 구현이 가능하며 이후 글에서 차차 설명하겠습니다.
첨부하는 소스코드는 실제 프로젝트에서 사용하는데 무리가 없는 소스입니다.
(많은 시스템에서 실제 운영중인 코드 입니다.)

ActiveX를 제외한 일반적인 파일 업로드 프로그램은 클라이언트에서 서버로 전달된
multipart form 형식의 input stream을 parsing하여 어떤 값이 파일이고 어떤 값이
form의 input 값인지를 결정하여 파일은 file system에 저장하는 방식입니다.

다음과 같은 html form을 submit하겠습니다.
선택한 파일은 c:\test.txt 파일입니다.

<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>

서버에 전달되는 stream은 다음과 같습니다.

-----------------------------7d82efc203cc
Content-Disposition: form-data; name="_cmd"

uploadFile
-----------------------------7d82efc203cc
Content-Disposition: form-data; name="file"; filename="C:\test.txt"
Content-Type: text/plain

test
-----------------------------7d82efc203cc--

이와 같은 stream을 parsing하는 java class인
WCMultipartFormParser,WCMultipartFormElement를 소개합니다.
위와 같은 stream을 parsing하면 form element가 2개이고 하나는 
parameter(_cmd)이고 하나는 파일(c:\test.txt)입니다.

WCMultipartFormParser
  -> WCMultipartFormElement : _cmd=uploadFile
  -> WCMultipartFormElement : file c:\test.txt

WCMultipartFormParser(parser라고 간략히 부르겠습니다.)
WCMultipartFormElement(element라고 간략히 부르겠습니다.)
의 구조를 설명하겠습니다.

대용량 파일을 서버에 업로드 하려면 input stream으로 부터 전달된 file의 data를
memory에 모두 loading하면 안됩니다. 만약 5G file을 uploading한다면 이를 memory에 올릴 수가 
없기때문입니다. 따라서 upload된 내용을 parsing하면서 임시 directory에 저장을 합니다.

다음과 같은 순서로 설명을 하겠습니다.

1. input stream을 buffering하는 방법
2. parser에서 호출되는 순서
3. file을 임시파일로 저장(다음번 글에서 설명)
4. 임시로 저장된 파일을 사용자가 정의하는 directory로 복사(다음번 글에서 설명)

parser는 input stream으로부터 읽어들인 내용을 double buffering하여 관리합니다.
double buffering에 대해서 간단히 설명드리겠습니다.
하나의 buffer를 반으로 나누고 한쪽 부분에 input stream에서 읽은 내용을 임시로 저장합니다.
그리고 이 내용을 parsing을 합니다.
한쪽 부분 buffer를 모두 parsing을 하면 buffer의 나머지 반쪽에 다시 input stream에서 읽은
내용을 임시로 저장합니다.
이렇게 double buffering을 하는 이유는 한쪽의 buffer를 parsing하다가 parsing이 잘못되어
rollback을 하는 경우 한쪽 buffer에서만 rollback해서 안되는 경우가 있습니다.
예를 들어 보이겠습니다.
buffer size = 20이고 반으로 나눈 한쪽 버퍼는 10 size가 됩니다.
1234567890 1234567890
abcdefghij kl
아래와 같이 kl까지 parsing을 했는제 잘못 parsing을 해서 rollback 즉 gh부터 parsing을 다시
해야 하는 경우 double buffering 기법을 사용합니다.
그러면 buffer size를 크게 하면 되지않느냐 라고 질문 할 수 있습니다. 그렇지 않습니다.
buffer size가 아무리 커도 rollback에 대한 여분을 충분히 확보할 수가 없습니다.
즉 이전에 사용하던 buffer를 지우지 말고 보유하고 있어야 충분한 rollback을 확보할 수 있습니다.
첨부한 source 코드에서 getByte는 하나의 input stream에서 1 byte 씩 읽어들입니다.
getByte에서 호출하는 getByteEx에서 double buffering 처리를 합니다.

public byte getByte() throws Exception

input stream을 parsing 하는 부분에서는 이제 byte단위로 parsing하다가 문제가 있으면
rollback을 할 수 있습니다.
위에서 sample로 보여드린 form 즉 _cmd,file을 parsing하는 방법에 대해 설명하겠습니다.

WCMultipartFormParser.init()
  -> parseContent(oRequest)
    -> parseContentEx(oRequest)
      -> findBoundary() : -----------------------------7d82efc203cc 이 부분을 parsing합니다.
      -> findHeader() : Content-Disposition: form-data; name="_cmd" 이 부분을 parsing 합니다.
        -> WCMultipartFormElement.setHeader : header 정보를 element에 저장합니다.
      -> procContent() : content body를 parsing 합니다.
        -> 임시파일에 파일 저장 : content type이 file인경우
        -> parameter인경우 WCProperties m_rParam 에 parameter 이름과 value를 저장

위와 같은 구조로 form을 parsing합니다.

<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>

이 form을 submit할때 request parameter 값은 WCMultipartFormParser.getParam()을 호출하면
parsing되어 저장된 request parameter값을 얻어올 수 있습니다.
그리고 아래의 소스에서 WCMultipartFormParser.saveFile(sDir)을 호출하여 임시 저장된
file들을 개발자가 원하는 directory로 이동을 합니다.

다음번 글에서는 file을 저장하는 구조에 대해서 설명하겠습니다.

아래의 소스 코드는 JSP 에서 WCPage의 object를 생성하고 WCMultipartFormParser의 기능을 호출하여
multipart form을  parsing하고 파일을 저장하는 sample code입니다.

WCPage.initCtrl
  -> WCPage.initCtrl
    -> WCPage.isMultipart : file을 submit한 겨우인지를 검사
      -> WCMultipartFormParser.init()

if (isMultipart())
{
    WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
    oFormParser.setDebug(true);
    oFormParser.init();
    byte[] btDebugBuf = oFormParser.getDebugBuf();
    String sDebug = new String(btDebugBuf);
    this.printOut("<pre>");
    this.printOut(sDebug);
    this.printOut("</pre>");
    
    WCProperties rParam = oFormParser.getParam();
    this.printOut(rParam.serializeOut());

    String sDir = "c:/tmp3";
    oFormParser.saveFile(sDir);
    return 1;
}
      
여기서 잠깐 WCPage에 대해서 설명하겠습니다.
WCPage는 JSP 혹은 Servlet에 대한 정보를 저장하고 있는 Object입니다.
WCMultipartFormParser 혹은 WCMultipartFormElement에서 request 혹은 response object를 access할때
WCPage를 통하여 access할 수 있습니다.
WCPage.initCtrl에서 pageContext를 넘김으로 WCPage에서 JSP 관련 context를 모두 저장하고
또한 page로 전달된 parameter를 WCPage가 모두 저장하고 있습니다.
여기서 sample로 제공하는 WCPage java class는 WDL(Web Development Library)에서 제공하는 WCPage.java에서
필요한 부분만 추출하여 새로 구성한 sample입니다.
(개발자들이 이해를 쉽게 하기 위해서 일부러 추출을 하였습니다. http://www.webdevlib.net 에서 
모든 소스코드는 무료로 다운로드 받을 수 있습니다.)

첨부한 소스만으로도 어느정도 동작이 가능하지만 WCProperties,WCVector,WCLog,WCSystem,WCEnv
등의 파일은 http://www.webdevlib.net에서 다운받아 사용하십시요
소스의 일부분은 고의로 누락한 것은 아닙니다. 모든 소스를 설명하려니 너무 많기때문에
중요한 부분을 추출하여 sample로 구성하면서 최대한 이해가 쉽도록 재구성을 하였습니다.

첨부파일에는 3개의 파일이 zip으로 묶여있습니다.

WCMultipartFormParser.java
WCMultipartFormElement.java
file_upload_progress1.jsp

-- file_upload_progress1.jsp 소스 시작
<%@ page language="java" import="wdl.*,java.util.*,java.sql.*,java.lang.*,java.io.*,java.io.File " contentType="text/html; charset=EUC-KR"%>
<%
    WCPage oPage = new WCPage();
    if (oPage.initCtrl(pageContext) > 0)
    {
        return;
    }
%>
<%@ include file="/wdl/src/java/WCMultipartFormParser.java"%>
<%@ include file="/wdl/src/java/WCMultipartFormElement.java"%>
<%!
public class WCPage
{
    public int initCtrl(javax.servlet.jsp.PageContext oPageContext)
    {
        return initCtrl(
            (javax.servlet.http.HttpServletRequest)oPageContext.getRequest()
            ,(javax.servlet.http.HttpServletResponse)oPageContext.getResponse()
            ,(javax.servlet.jsp.JspWriter)oPageContext.getOut()
            ,(javax.servlet.http.HttpSession)oPageContext.getSession()
            ,(javax.servlet.ServletContext)oPageContext.getServletContext()
            ,oPageContext
            ,(javax.servlet.ServletConfig)oPageContext.getServletConfig()
            );
    }
    public int initCtrl(
        javax.servlet.http.HttpServletRequest oRequest
        ,javax.servlet.http.HttpServletResponse oResponse
        ,javax.servlet.jsp.JspWriter oOut
        ,javax.servlet.http.HttpSession oSession
        ,javax.servlet.ServletContext oApplication
        ,javax.servlet.jsp.PageContext oPageContext
        ,javax.servlet.ServletConfig oConfig)
    {
        try
        {
            m_request = oRequest;
            m_response = oResponse;
            m_out = oOut;
            m_session = oSession;
            m_application = oApplication;
            m_pageContext = oPageContext;
            m_config = oConfig;
            
            if (isMultipart())
            {
                WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
                oFormParser.setDebug(true);
                oFormParser.init();
                byte[] btDebugBuf = oFormParser.getDebugBuf();
                String sDebug = new String(btDebugBuf);
                this.printOut("<pre>");
                this.printOut(sDebug);
                this.printOut("</pre>");
                
                WCProperties rParam = oFormParser.getParam();
                this.printOut(rParam.serializeOut());

                String sDir = "c:/tmp3";
                oFormParser.saveFile(sDir);
                return 1;
            }
        }
        catch (Exception ex)
        {
        }
        return 0;
    }
    public javax.servlet.http.HttpServletRequest m_request = null; 
    public javax.servlet.http.HttpServletResponse m_response = null; 
    public javax.servlet.jsp.JspWriter m_out = null; 
    public javax.servlet.http.HttpSession m_session = null; 
    public javax.servlet.ServletContext m_application = null; 
    public javax.servlet.jsp.PageContext m_pageContext = null; 
    public javax.servlet.ServletConfig m_config = null; 
    
    public javax.servlet.http.HttpSession getSession()
    {
        return m_session;
    }
    public javax.servlet.http.HttpServletRequest getRequest()
    {
        return m_request;
    }
    public javax.servlet.jsp.PageContext getPageContext()
    {
        return m_pageContext;
    }

    public boolean isMultipart()
    {
        HttpServletRequest oRequest = (javax.servlet.http.HttpServletRequest)m_request;
        String content_type = oRequest.getHeader("content-type");
        if (WCString.indexOf(WCString.toUpper(content_type),"MULTIPART") == 0)
        {
            return true;
        }
        return false;
    }
}
%>

<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>

<a href="javascript:uploadFile();">upload the file</a>

<iframe id="ifrmAction" name="ifrmAction" width="0" height="0"></iframe> 

<script>
function uploadFile()
{
    var fParam = window.document.fParam;
    fParam._cmd.value = "uploadFile";
    fParam.method = "post";
    fParam.target = "_blank";
    fParam.submit();
}
</script>
-- file_upload_progress1.jsp 소스 끝

출처 : 고급 웹 UI 개발 라이브러리 Web Development Library 소스공개 : http://www.webdevlib.net

첨부파일 : multipart_form_parser1.zip
첨부파일 :  
multipart_form_parser1.zip   [7 KB]   다운로드 횟수 72 회
Posted by 1010
05.JSP2009. 6. 16. 20:02
반응형

JSP 가 실행되기 위해서는 JSP 파일을 서블릿 파일로 변환하는 과정을 거치게 된다.
이 작업은 클라이언트의 요청이 있을 경우, 또는 JSP 파일이 변경되었을 경우 변경된
JSP 파일을 로딩하기 위해서 이루어진다.

JSP 동작구조
 
1.클라이언트가 jsp 페이지 요청
2. 웹 서버가 요청한 페이지를 를 처리하기 위해 JSP 컨테이너에게 처리를 넘긴다.
3. 해당 JSP 파일이 처음 요청된 것이면 JSP 파일을 서블릿으로 변환.
(JSP 컨테이너가 수행) 이전에 요청되었던 페이지일 경우 5 단계 실행
4.서블릿 파일은 자바에서 실행 가능한 상태인 클래스 파일로 컴파일
5. 클래스 파일을 메모리에 적재 후 실행
6. 실행 결과가 웹 서버에게 넘겨짐
7. 웹 서버는 브라우저가 인식할 수 있는 HTML 형태로 결과를 웹 브라우저에 응답
 
* jsp가 servlet으로 변환된 소스는 WAS마다 다르다
 
tomcat은 변환된 서블릿 소스를
C:\apache-tomcat-5.5.26\work\Catalina\localhost웹 어플리케이션 디렉토리\org\apache\jsp\jspsrc 에 저장
 
eclipse에서는

C:\워크스페이스명\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\프로젝트명\org\apache\jsp 

사용자 삽입 이미지
Posted by 아돌
Posted by 1010
01.JAVA/Java2009. 6. 16. 19:59
반응형
mkdirs() 라는 메서드(함수)로, 디렉토리(폴더)를 만들 수 있습니다.

mkdirs() 는 디렉토리 생성에 성공하면 true 를 반환하기에, 실패시 에러를 출력하려면 if문 속에서 느낌표를 붙여, 논리값을 반전시켜 주어야 합니다.

같은 이름의 디렉토리가 이미 있을 때나

디렉토리명에 허용되지 않는 문자(*, ? 등)가 있을 때

에는 아래 예제의 경우, "디렉토리 생성 실패"라는 메시지가 출력됩니다.

여러 개의 중첩된 폴더를 한꺼번에 생성하려면 슬래시(/) 기호로 패스를 구분해 줍니다.

mkdir() 이라는 단수형 이름의 메소드로도 디렉토리를 만들 수 있지만, 여러개를 한꺼번에 만들 수는 없습니다.

디렉토리 만들기 예제


소스 파일명: Example.java
import java.io.*;

public class Example {
  public static void main(String[] args) {

    // MY_TEST_DIR 이라는 하위 폴더 만들기

    File f = new File("MY_TEST_DIR");
    if (!f.mkdirs())
      System.err.println("디렉토리 생성 실패");




    // MY_TEST_DIR 이라는 하위 폴더 밑에
    // 333 이라는 하위 폴더 또 만들기
    // 즉, MY_TEST_DIR/333 이렇게 중첩된 폴더 한꺼번에 생성

    f = new File("MY_TEST_DIR/333");
    if (!f.mkdirs())
      System.err.println("디렉토리 생성 실패");


  }
}


위의 자바 코드를 실행하면, 현재 디렉토리에 MY_TEST_DIR 이라는 폴더가 생기고, 그 안에 333 이라는 폴더가 또 들어 있을 것입니다.


▶▶ Java/자바] 파일 지우기, 디렉토리 삭제 방법; Delete File, Erase Directory

▶▶ Java 자바, 현재 날짜로 디렉토리 생성 예제; Current Date Directory Name

Posted by 1010
02.Oracle/DataBase2009. 6. 15. 00:59
반응형
- 원하는 소수점 자리수 만큼만 보여주고 나머지는 없애버린다.

- EX) TRUNC(12.345, 2)  => 12.34 (소수점 2자리만 보여준다)
         TRUNC(12.345)     => 12 (소수점 자릿수를 지정하지 않으면 정수만 보여준다.)
         TRUNC('2004-05-33', 'MONTH')  => '2004-05-01' (월을 기준으로 1일로 돌아온다)
         TRUNC('2004-05-12', 'YEAR')    =>  '2004-01-01' (년을 기준으로 1월 1일로 돌아온다)
Posted by 1010
01.JAVA/Java2009. 6. 13. 16:42
반응형
Posted by 1010
01.JAVA/Java2009. 6. 13. 16:20
반응형
Java Performance Tuning 2000
Posted by 1010
01.JAVA/Java2009. 6. 13. 16:12
반응형



beginning-jsp-jsf-and-tomcat-web-development-from-novice-to-professional
Posted by 1010
98..Etc/Tomcat2009. 6. 13. 16:11
반응형
Apress Pro Apache Tomcat 6


Posted by 1010
98..Etc/Tomcat2009. 6. 13. 16:09
반응형
Posted by 1010
02.Oracle/DataBase2009. 6. 13. 15:44
반응형






..오라클 sql 튜닝...포켓 가이드

뭐 대략 간단한거 같네요..

간단한 예제...

DELETE FROM
FROM ps_pf_ledger_f00
WHERE EXISTS
(SELECT 'x'
FROM ps_pf_led_pst2_t1 b
WHERE b.business_unit = ps_pf_ledger_f00.business_unit
AND b.fiscal_year = ps_pf_ledger_f00.fiscal_year
AND b.accounting_period= ps_pf_ledger_f00.accounting_period
AND b.pf_scenario_id = ps_pf_ledger_f00.pf_scenario_id
AND b.source = ps_pf_ledger_f00.source
AND b.account = ps_pf_ledger_f00.account
AND b.deptid = ps_pf_ledger_f00.deptid
AND b.cust_id = ps_pf_ledger_f00.cust_id
AND b.product_id = ps_pf_ledger_f00.product_id
AND b.channel_id = ps_pf_ledger_f00.channel_id
AND b.obj_id = ps_pf_ledger_f00.obj_id
AND b.currency_cd = ps_pf_ledger_f00.currency_cd);
Elapsed: 00:08:160.51

이건 8초 걸린다...

DELETE FROM ps_pf_ledger_f00
WHERE( business_unit,fiscal_year,accounting_period,
pf_scenario_id ,account,deptid ,cust_id ,
product_id,channel_id,obj_id,currency_cd)
IN
(SELECT business_unit,fiscal_year,accounting_period,
pf_scenario_id ,account,deptid ,cust_id ,
product_id,channel_id,obj_id,currency_cd
FROM ps_pf_led_pst2_t1 );
Elapsed: 00:00:00.30

이건 0.8 초 ...
----------------------


SELECT COUNT(*)
FROM trans
WHERE cost_center = 'MASS'
AND bmark_id = 9;
Response Time = 4.255 seconds


The index that has the column that is listed first in the WHERE CLAUSE will drive the query. In this statement, the indexed entries for COST_CENTER = `MASS' will return significantly more rows than those for BMARK_ID=9, which will return at most only one or two rows.
The following query reverses the order of the conditions in the WHERE clause, resulting in a much faster execution time.


SELECT COUNT(*)
FROM trans
WHERE bmark_id = 9
AND cost_center = 'MASS';
Response Time = 1.044 seconds


Posted by 1010
02.Oracle/DataBase2009. 6. 13. 10:26
반응형
Posted by 1010
56. Eclipse Etc.../Eclipse2009. 6. 11. 16:15
반응형
Posted by 1010
56. Eclipse Etc.../Eclipse2009. 6. 11. 16:10
반응형
tomcat 에 임시파일이 계속 남아있어 1시간 정도 삽질한 경험이 있다...
web.xml 에서
jsp compile refresh 설정을 했어야 했는데;;
안 했더니.... 꼬임 현상이 일어났던 것이다;; 아놔..  (추후 설정은 추가..)

재성 아저씨가 work 디렉토리를 알려 주셨는데..

대략 (뭐 거의 똑같겠지만...)

Workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work

이 위치에 존재 한다.. (tmp0 의 의미는 Eclipse 내 추가했던 서버의 index 여부 였던것 같다.. )
아무튼 이와 같은 삽질을 다시는 안했으면.. OTL....
Posted by 1010
02.Oracle/DataBase2009. 6. 9. 11:36
반응형

XML DB Port Assignments

by Jeff Hunter, Sr. Database Administrator

Portions of this article are written by Roby Sherman and Copyright 2002


Contents

  1. Introduction
  2. Repository Views and Default Ports
  3. Changing XML DB Default Ports
  4. Disabling the Port Assignment



Introduction

Oracle introduced the XML Database in release 9i. Along with this new feature, Oracle continues the practice of incorporating new, barely documented port assignments that often leave the DBA to search endlessly for possible configuration file(s) that define these port assignments. Well, when it comes to searching for where these port numbers related to XML DB are defined, you will not find them on the file system, but rather inside the database. This article will attempt to unravel some of the mysteries on managing port assignments related to Oracle XML DB.



Repository Views and Default Ports

The key XML DB technologies can be grouped into two major classes - a XMLType that provides a native XML storage and retrieval capability strongly integrated with SQL, and a XML Repository that provides foldering, access control, versioning etc. for XML resources. Users view and manage XML objects like files and schemas in the XML Repository as a hierarchy of folders. This repository aspect of XML DB involves access through standard protocols such as HTTP/WebDAV and FTP. These servers will bind to ports 8080 and 2100 respectively by default.

DBA's will sometimes wonder why their Web Server, that always used to work, has all of the sudden been hijacked after installing Oracle9i and creating a database using DBCA. After some research, they attempt to shutdown the Oracle TNS listener and notice that the port in question (mostly 8080) is no longer being utilized. Unfortunately, there is little to tell the DBA that these ports are going to be used until they find out the hard way: When the database starts and steals the ports away from another process that hasn't yet started or when the other process errors and/or is unreachable.



Changing XML DB Default Ports

The following section describes the syntax that can be used to alter XML DB configuration information from within SQL*Plus. Ensure that you are logged into the database from a DBA account. In the following example, the default HTTP/WebDAV and FTP ports are changed from 8080 and 2100 to 8081 and 2111 respectively:
  SQL> -- Change the HTTP/WEBDAV port from 8080 to 8081
  SQL> call dbms_xdb.cfg_update(updateXML(
    2        dbms_xdb.cfg_get()
    3      , '/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()'
    4      , 8081))
    5  /

  Call completed. 


  SQL> -- Change the FTP port from 2100 to 2111
  SQL> call dbms_xdb.cfg_update(updateXML(
    2         dbms_xdb.cfg_get()
    3       , '/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()'
    4       , 2111))
    5  /

  Call completed. 


  SQL> COMMIT;

  Commit complete. 


  SQL> EXEC dbms_xdb.cfg_refresh;

  PL/SQL procedure successfully completed.


  SQL> -- Verify the change
  SQL> set long 100000
  SQL> set pagesize 9000
  SQL> SELECT dbms_xdb.cfg_get FROM dual;

CFG_GET
--------------------------------------------------------------------------------
<xdbconfig xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd" xmlns:xsi="http://w
ww.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/x
db/xdbconfig.xsd                                     http://xmlns.oracle.com/xdb
/xdbconfig.xsd">
  <sysconfig>
    <acl-max-age>900</acl-max-age>
    <acl-cache-size>32</acl-cache-size>
    <invalid-pathname-chars>,</invalid-pathname-chars>
    <call-timeout>300</call-timeout>
    <max-session-use>100</max-session-use>
    <default-lock-timeout>3600</default-lock-timeout>
    <resource-view-cache-size>1048576</resource-view-cache-size>
    <protocolconfig>
      <common>
        <extension-mappings>
          <mime-mappings>
            <mime-mapping>
              <extension>au</extension>
              <mime-type>audio/basic</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>avi</extension>
              <mime-type>video/x-msvideo</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>bin</extension>
              <mime-type>application/octet-stream</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>bmp</extension>
              <mime-type>image/bmp</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>doc</extension>
              <mime-type>application/msword</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>eml</extension>
              <mime-type>message/rfc822</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>gif</extension>
              <mime-type>image/gif</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>htm</extension>
              <mime-type>text/html</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>html</extension>
              <mime-type>text/html</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>jpe</extension>
              <mime-type>image/jpeg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>jpeg</extension>
              <mime-type>image/jpeg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>jpg</extension>
              <mime-type>image/jpeg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>jsp</extension>
              <mime-type>text/html</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>mid</extension>
              <mime-type>audio/mid</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>mov</extension>
              <mime-type>video/quicktime</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>movie</extension>
              <mime-type>video/x-sgi-movie</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>mp3</extension>
              <mime-type>audio/mpeg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>mpe</extension>
              <mime-type>video/mpg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>mpeg</extension>
              <mime-type>video/mpg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>mpg</extension>
              <mime-type>video/mpg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>msa</extension>
              <mime-type>application/x-msaccess</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>msw</extension>
              <mime-type>application/x-msworks-wp</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>pcx</extension>
              <mime-type>application/x-pc-paintbrush</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>pdf</extension>
              <mime-type>application/pdf</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>ppt</extension>
              <mime-type>application/vnd.ms-powerpoint</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>ps</extension>
              <mime-type>application/postscript</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>qt</extension>
              <mime-type>video/quicktime</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>ra</extension>
              <mime-type>audio/x-realaudio</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>ram</extension>
              <mime-type>audio/x-realaudio</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>rm</extension>
              <mime-type>audio/x-realaudio</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>rtf</extension>
              <mime-type>application/rtf</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>rv</extension>
              <mime-type>video/x-realvideo</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>sgml</extension>
              <mime-type>text/sgml</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>tif</extension>
              <mime-type>image/tiff</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>tiff</extension>
              <mime-type>image/tiff</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>txt</extension>
              <mime-type>text/plain</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>url</extension>
              <mime-type>text/plain</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>vrml</extension>
              <mime-type>x-world/x-vrml</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>wav</extension>
              <mime-type>audio/wav</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>wpd</extension>
              <mime-type>application/wordperfect5.1</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>xls</extension>
              <mime-type>application/vnd.ms-excel</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>xml</extension>
              <mime-type>text/xml</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>zip</extension>
              <mime-type>application/x-zip-compressed</mime-type>
            </mime-mapping>
          </mime-mappings>
          <lang-mappings>
            <lang-mapping>
              <extension>en</extension>
              <lang>english</lang>
            </lang-mapping>
          </lang-mappings>
          <charset-mappings/>
          <encoding-mappings>
            <encoding-mapping>
              <extension>gzip</extension>
              <encoding>zip file</encoding>
            </encoding-mapping>
            <encoding-mapping>
              <extension>tar</extension>
              <encoding>tar file</encoding>
            </encoding-mapping>
          </encoding-mappings>
        </extension-mappings>
        <session-pool-size>50</session-pool-size>
        <session-timeout>6000</session-timeout>
      </common>
      <ftpconfig>
        <ftp-port>2111</ftp-port>
        <ftp-listener>local_listener</ftp-listener>
        <ftp-protocol>tcp</ftp-protocol>
        <session-timeout>6000</session-timeout>
      </ftpconfig>
      <httpconfig>
        <http-port>8081</http-port>
        <http-listener>local_listener</http-listener>
        <http-protocol>tcp</http-protocol>
        <session-timeout>6000</session-timeout>
        <server-name>XDB HTTP Server</server-name>
        <max-header-size>16384</max-header-size>
        <max-request-body>2000000000</max-request-body>
        <servlet-realm>Basic realm="XDB"</servlet-realm>
        <webappconfig>
          <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
          </welcome-file-list>
          <error-pages/>
          <servletconfig>
            <servlet-mappings>
              <servlet-mapping>
                <servlet-pattern>/Test</servlet-pattern>
                <servlet-name>TestServlet</servlet-name>
              </servlet-mapping>
              <servlet-mapping>
                <servlet-pattern>/oradb/*</servlet-pattern>
                <servlet-name>DBURIServlet</servlet-name>
              </servlet-mapping>
            </servlet-mappings>
            <servlet-list>
              <servlet>
                <servlet-name>TestServlet</servlet-name>
                <servlet-language>Java</servlet-language>
                <display-name>XDB Test Servlet</display-name>
                <description>A servlet to test the internals of the XDB Servlet API</description>
                <servlet-class>xdbtserv</servlet-class>
                <servlet-schema>xdb</servlet-schema>
              </servlet>
              <servlet>
                <servlet-name>DBURIServlet</servlet-name>
                <display-name>DBURI</display-name>
                <servlet-language>C</servlet-language>
                <description>Servlet for accessing DBURIs</description>
                <security-role-ref>
                  <role-name>authenticatedUser</role-name>
                  <role-link>authenticatedUser</role-link>
                </security-role-ref>
              </servlet>
            </servlet-list>
          </servletconfig>
        </webappconfig>
      </httpconfig>
    </protocolconfig>
  </sysconfig>
</xdbconfig>



Disabling the Port Assignment

One of the easist ways to disable Oracle from assigning both XML DB ports (FTP and HTTP/WebDAV) is to remove the following instance parameter from the database:
    dispatchers='(PROTOCOL=TCP) (SERVICE=<ORACLE_SID>XDB)'
This change would obviously require bouncing the database.

A second way to disable the XML DB ports is to simply change their port assignments to the value of zero (0). This is an attractive option since it uses code that can be incorporated directly into database creation scripts so that the value can be tweaked each time you create a new database.

Modifying these ports to zero can also be accomplished using a GUI; Oracle Enterprise Manager (version 9.2.0.1 or higher). Simply open OEM, select and expand the database. Next, expend the XML Database item and click on Configuration. You should be able to see and change any of the XML DB configuration parameters on the right-hand side of the OEM console. Simply make your changes and click APPLY to make them permanent.

For more information on Managing Oracle XML DB Using Oracle Enterprise Manager, click here.

Posted by 1010
02.Oracle/DataBase2009. 6. 9. 11:35
반응형

Tomcat 등의 웹컨테이너 설치 후 서비스 시작을 하려다보면
8080포트 충돌로 인해 서비스가 되지 않는 경우가 있다.

Oracle XDB가 바로 8080포트를 이미 사용하고 있기 때문이다
리스너의 서비스 상태를 점검해보고 Oralce XDB Port를 변경해보자.


C:\Documents and Settings\geenoo>netstat -ano

Proto  Local Address          Foreign Address        State           PID
 TCP    dozuq:8080             dozuq:0                LISTENING        884
 TCP    dozuq:2100             dozuq:0                LISTENING        884
:
:

PID로 프로세스를 찾는다.
C:\Documents and Settings\geenoo>tasklist /SVC /fi "PID eq 884"

이미지 이름                        PID     서비스
========================= ====== =============================================
TNSLSNR.EXE                    884      OracleOraHome92TNSListener


다음 명령으로 리스너의 서비스 상태를 보자.

D:\oracle\ora92\bin>lsnrctl status

.
.



Oracle XDB 가 8080(HTTP)와 2100(FTP) 포트를 쓴다는 걸 확인했다.
이제 포트(Port)를 변경해보자.



1. [시작] -> [프로그램] -> [Oracle - OraHome92]
-> [Configuration and Migration Tools] -> [Database Configuration Assistant] 선택

사용자 삽입 이미지



2. [다음] -> [데이터베이스의 데이이터베이스 옵션구성] 선택

사용자 삽입 이미지



3. 옵션을 구성하고자 하는 [사용 가능한 데이터베이스] 선택하고
DBA의 사용자 이름과 암호를 입력한 후 [다음]

사용자 삽입 이미지



4. [표준데이터베이스 기능...] 클릭

사용자 삽입 이미지



5. 표준데이터베이스 기능 팝업창에서 [사용자정의...] 클릭

사용자 삽입 이미지



6. 이 팝업창에서 FTP 및 WebDAV포트와 HTTP포트를 입력하고 [확인]한다.
만약 클라이언트에서 XML DB로의 접속을 원치 않을 경우엔 'XML DB프로토콜 비활성화'을 선택

사용자 삽입 이미지



7. "표준데이터베이스 기능" 팝업창(5.)의 [확인]을 선택하여 창을 닫는다.



8. 팝업창을 닫고 나면 "데이터베이스 기능"(4.) 화면으로 돌아간다. [다음] 클릭



9. [완료] 클릭

사용자 삽입 이미지


사용자 삽입 이미지



Posted by 1010
02.Oracle/DataBase2009. 6. 9. 11:34
반응형
2009-05-15 00:55

发布时间:2008.03.03 04:58    来源:赛迪网    作者:Alizze

从Oracle 9i开始,Oracle的安装缺省包含了XDB。在启动数据库后,Oracle XDB的http服务将会自动占用了8080端口,这给使用或JBoss、Tomcat进行java web开发的人造成了许多不必要的麻烦。

本文将主要介绍修改XDB的http和ftp服务端口的3种方法。

1.使用dbms_xdb包修改端口设置

使用sys登录sqlplus

sqlplus sys/syspassword as sysdba

执行如下的脚本:

============================ 
-- Change the HTTP/WEBDAV port from 8080 to 8081 
call dbms_xdb.cfg_update(updateXML( 
dbms_xdb.cfg_get() 
, '/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()' 
, 8081)) 
/ 
-- Change the FTP port from 2100 to 2111 
call dbms_xdb.cfg_update(updateXML( 
dbms_xdb.cfg_get() 
, '/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()' 
, 2111)) 
/ 
COMMIT; 
EXEC dbms_xdb.cfg_refresh;

2.使用OEM console

选择数据库,XML Database,Configuration。更改XDB的有关设置。

3.修改SPFILE[SID名].ORA文件,去掉数据库的初始化参数:

这个文件是Oracle的启动配置文件dispatchers='(PROTOCOL=TCP) (SERVICE=XDB)',将会禁止XDB的http和ftp服务。

下面我们来重启计算机,或者在服务中重启OracleService[SID名]这个服务。重启后可能无法使用Enterprise Manager Console和其他客户端连接,这时请大家使用Oracle的Configuration and Migration Tools/Net Configuration Assistant工具删除监听器,然后新建一个监听器,最后重启监听器。(责任编辑:卢兆林)

以下为个人原创:

另外,安装了oracle10g后,lomboz all in one不能正常启动,在日记文件中有如下语句:

!MESSAGE Product org.objectweb.lomboz.product.lomboz could not be found.

原因在于oracle添加的java环境变量。和当前lomboz使用的环境版本不同。

解决办法很简单:

将环境变量中path的值“C:\Program Files\Java\jdk1.7.0\bin;”(此值与你安装的JAVA版本、安装位置不同而有所不同)放在最前面,其它的置后(请务必注意分号的位置)。重新启动Eclipse,可以成功启动。经证实,修改后的环境变量对Oracle的使用没有影响,仍可正常使用。

希望可以帮到遇到这种问题的朋友们。

Posted by 1010
01.JAVA/Java2009. 6. 8. 18:03
반응형

Java에서 HTML 태그를 제거하는 정규식 적용

  1. private String getText(String content) {  
  2.     Pattern SCRIPTS = Pattern.compile("<(no)?script[^>]*>.*?</(no)?script>",Pattern.DOTALL);  
  3.     Pattern STYLE = Pattern.compile("<style[^>]*>.*</style>",Pattern.DOTALL);  
  4.     Pattern TAGS = Pattern.compile("<(\"[^\"]*\"|\'[^\']*\'|[^\'\">])*>");  
  5.     Pattern nTAGS = Pattern.compile("<\\w+\\s+[^<]*\\s*>");  
  6.     Pattern ENTITY_REFS = Pattern.compile("&[^;]+;");  
  7.     Pattern WHITESPACE = Pattern.compile("\\s\\s+");  
  8.       
  9.     Matcher m;  
  10.       
  11.     m = SCRIPTS.matcher(content);  
  12.     content = m.replaceAll("");  
  13.     m = STYLE.matcher(content);  
  14.     content = m.replaceAll("");  
  15.     m = TAGS.matcher(content);  
  16.     content = m.replaceAll("");  
  17.     m = ENTITY_REFS.matcher(content);  
  18.     content = m.replaceAll("");  
  19.     m = WHITESPACE.matcher(content);  
  20.     content = m.replaceAll(" ");          
  21.       
  22.     return content;  
  23. }  
정규식을 6개 정도 적용하고 있는 간단한 소스입니다.
각각 HTML의 스크립트 태그와 내용, 스타일 및 내용, 태그들, 엔터티, 공백문자들을 제거하는 정규식 표현입니다.

관심있는 분들은 한번씩 테스트 해보시기 바랍니다. ^^

아마도 곧 간단한 기능을 하는 것을 오픈해서 보여드릴건데요..
URL을 지정하면 해당 텍스트를 분석해서 자동으로 태깅 정보를 제공하는 겁니다.
마무리 단계이니 완료되는 대로 이 사이트를 통해서 보여드릴께요..

그럼.. 좋은 하루 되세요~~ from 미니(xmlmanager@gmail.com)
Posted by 1010
02.Oracle/DataBase2009. 6. 8. 15:17
반응형
CLOB COLUMN 또는 CLOB VARIABLE를 REPLACE, SEARCH하는 방법
Posted: 2007. 1. 29 오전 2:06
Click to report abuse...   Click to reply to this thread Reply
제품 : PL/SQL

작성날짜 : 2001-02-08

CLOB COLUMN 또는 CLOB VARIABLE를 REPLACE, SEARCH하는 방법
=========================================================

1. Table 및 Data 생성

SAL> CREATE TABLE test (key NUMBER,c CLOB);
SAL> INSERT INTO test VALUES (1,'aaa#~#bbb#~#ccc');
SAL> INSERT INTO test VALUES (2,'aaa#~#bbb#~#ccc');

2. 사용된 DBMS_LOB package routines :

- ISOPEN()
- CREATETEMPORARY()
- INSTR()
- GETLENGTH()
- COPY()
- TRIM()

3. 아래처럼 Clob를 handling하기 위한 PL/SQL Code 생성

CREATE OR REPLACE PROCEDURE Srch_N_Repl_Clob
(dest_lob IN OUT CLOB, search_str VARCHAR2,replace_str VARCHAR2)
AS
temp_clob CLOB;
end_offset INTEGER := 1;
start_offset INTEGER := 1;
occurence NUMBER := 1;
replace_str_len NUMBER := LENGTH(replace_str);
temp_clob_len NUMBER := 0;
dest_lob_len NUMBER := 0;

BEGIN
IF DBMS_LOB.ISOPEN(dest_lob) = 0 THEN
NULL;
END IF;
DBMS_LOB.CREATETEMPORARY(temp_clob,TRUE,DBMS_LOB.SESSION);
LOOP
end_offset := DBMS_LOB.INSTR(dest_lob,search_str,1,occurence);
IF end_offset = 0 THEN
temp_clob_len := DBMS_LOB.GETLENGTH(temp_clob);
dest_lob_len := DBMS_LOB.GETLENGTH(dest_lob) - start_offset + 1;
IF dest_lob_len > 0 THEN
DBMS_LOB.COPY(temp_clob,dest_lob,dest_lob_len,temp_clob_len+1,start_offset);
END IF;
EXIT;
END IF;
temp_clob_len := DBMS_LOB.GETLENGTH(temp_clob);
IF (end_offset - start_offset) > 0 THEN
DBMS_LOB.COPY(temp_clob,dest_lob,(end_offset - start_offset),temp_clob_len+1,start_offset);
END IF;
start_offset := end_offset + LENGTH(search_str);
occurence := occurence + 1;
IF replace_str IS NOT NULL THEN
DBMS_LOB.WRITEAPPEND(temp_clob,replace_str_len,replace_str);
END IF;
END LOOP;
IF LENGTH(search_str) > LENGTH(replace_str) THEN
DBMS_LOB.TRIM(dest_lob,DBMS_LOB.GETLENGTH(temp_clob));
END IF;
DBMS_LOB.COPY(dest_lob,temp_clob,DBMS_LOB.GETLENGTH(temp_clob),1,1);
END ;
/

4. Clob의 column 및 variable이 변경된 상태를 실행해보면

SQL>DECLARE
2 dest_lob CLOB;
3 BEGIN
4 SELECT c INTO dest_lob FROM test WHERE key = 1 FOR UPDATE;
5 Srch_N_Repl_Clob(dest_lob,'#~#',' Replaced ');
6 END;
7 /

SQL>SELECT * FROM test;

KEY C


--------------------------------------------------
1 aaa Replaced bbb Replaced ccc
2 aaa#~#bbb#~#ccc
Posted by 1010
98..Etc/JSTL2009. 6. 8. 14:43
반응형

http://flexdocs.kr/ 의 3D 방명록을 기반으로 게시판을 작성해 봤다.
php로 되어있는 게시판 소스를 보고 jstl로 바꿔보면 어떨가 해서 시작했는데
귀차니즘의 압박으로 인해 웹으로 운영되고 있는 현재 게시판 기능 중
조회기능만을 AIR로 구현하는데 만족.

작업하면서 얻게된 몇가지 팁을 공유해 보자.

첫째. JSTL, CLOB
jstl로 clob데이터 처리가 되지 않는다-_-;;; 결국 꽁수를 써야 하는데,
나는 오라클디벨로퍼 페이지에 게시된 내용을 참고했다.


<c:set value="${rs.rows[0].content}" var="content" scope="request"/>
<%
oracle.sql.CLOB clob=(oracle.sql.CLOB)request.getAttribute("content");
StringBuffer clobString = new StringBuffer();      
int y;          
char ac[] = new char[4096];          
java.io.Reader reader = clob.getCharacterStream();          
while ((y = reader.read(ac, 0, 4096)) != -1) {
 String buff = new String(ac,0,y);
 clobString.append(buff);
}
request.setAttribute("content1", clobString.toString());
%>
<contents><![CDATA[${content1}]]></contents>

1. clob을 request에 박아두고
2. jsp에서 clob코드를 이용하여 스트링생성
3. 생성된 스트링을 request에 새팅
4. el에서 request를 읽어옴

일련의 과정을 통해서 알게된 점은

1. 지저분 하지만 jstl과 jsp 간에 데이터 통신은 request객체를 사용한다.
2. html 데이터를 xml로 표현할때는 <!CDATA[]]>를 사용한다.
3. clob은 쓰기 어렵다 -_-

둘째, trace()를 적극 활용하자.
서버에서 던져준 xml을 클라이언트가 어떻게 처리하고 있는지 몰라서 상당히 애 먹었다.
변수에 trace 먹여서 디버그로 돌리면 그냥 죽죽 나오는데,
이걸몰라서 프로그래밍 상당히 곤란
xml 파싱을 trace를 통해 겨우 해결했다.


var xmlArticle:XMLList = e.result.articles.article;
    view_idx.text = xmlArticle.@idx;
    view_hname.text = xmlArticle.hname;
    view_contents.htmlText = xmlArticle.contents;
   
    var xmlComments:XMLList = xmlArticle.comments.comment;
    acdp.removeAll();
       
    for(i=0; i < xmlComments.length(); i++)
    {
     var xmlComment:XML = xmlComments[i];
     //trace(xmlComment);
     acdp.addItem({
      comments : xmlComment.contents
     });        
    } 
   

xml, xmllist 객체 두개가 아직도 헷갈린다.
이해하려 노력하지 말고 그냥 맘편히 trace에서 나오는거 보고 적당히 처리하자-_-


세째, reference
jstl은 처음 써봤는데 역시 j2ee튜토리얼이 가장 큰 도움이 됐다.
http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html

AIR도 처음인데 flex/air 한글화 문서를 참조했다.
http://flexdocs.kr/

NEXT.
spring, hibernate로 확장 -_-;;


reader.zip

Posted by 1010
01.JAVA/Java2009. 6. 7. 01:08
반응형

java enum - enum의 메쏘드

모든 예제는 지난 글에서 썼던 Gender를 그대로 사용합니다. 코드는 아래와 같습니다.

public enum Gender {
    MALE, FEMAIL
}

Static Methods

기본으로 정의되는 static method는 모두 3가집니다.

1. valueOf(String arg)

String 으로 넘긴 값을 기준으로 enum의 원소를 가져 옵니다. 즉, Gender.MALE 과 Gender.valueOf("MALE")은 같습니다.


2. valueOf(Class<T> class, String arg)

클래스를 넘겨서 받습니다. 즉, Gender.MALE 와 Gender.valueOf(Gender.class, "MALE"); 는 같습니다. 사실 valueOf(String arg)는 내부적으로 이 메쏘드를 호출합니다.


3. values()

이건 지난 시간에 설명한 그대로 enum의 요소들을 enum 타입의 배열로 리턴합니다. Gender.values() 는
new Gender[]{Gender.MALE, Gender.FEMALE} 와 같은 값을 가집니다.



Static이 아닌 Method

1. name()
호출된 값의 이름을 리턴합니다.
Gender.MALE.name() 은 "MALE" 이라는 String 값을 가져옵니다.

2. ordinal()
정의된 순서를 리턴합니다. 0부터 시작합니다.
즉, Gender.MALE.ordinal() 은 0을 Gender.FEMALE.ordinal()은 1을 리턴합니다.

3. compareTo(E o)
E는 자기 자신입니다. 예제로 쓴 Gender의 경우는 Gender가 될 겁니다.
이는 ordinal()을 호출해서 비교합니다. 요소들 간에 어떤 순서가 있을 때 쓰면 됩니다.(요일이 좋은 예가 되겠습니다.)
모든 enum은 Comparable을 구현하고 있습니다. Comparable 인터페이스에는 정의된 compareTo 메쏘드를 구현한 것입니다. 더 자세한 것은 다음 글에서 다루겠습니다.

기타 다른 메쏘드들은 java.lang.Object에 정의된 메쏘드들이거나 java.lang.Class에서 따온 메쏘드들이므로 설명하지 않겠습니다.


enum의 확장

Gender 별로 웃음 소리를 저장하려고 합니다. Gender를 다음과 같이 변경시킵니다.

public enum Gender {
    MALE("하하")
    , FEMAIL("호호");
   
    private String sound;
    Gender(String arg){
        this.sound = arg;
    }
    String getSound(){
        return sound;
    }

}

일반적인 class의 생성자나 메쏘드를 만들 듯이 만들면 됩니다.
위의 코드의 경우 Gender.MALE.getSound()는 "하하"를 리턴합니다
Posted by 1010
02.Oracle2009. 6. 4. 19:57
반응형
오라클 에라멧세지 정리.


-----
현상 : Oracle Stored Procedure 호출이 제대로 되지 않음
원인 : Stored Procedure에 입출력되는 VARCHAR 변수의 초기화가 되지 않음
조치 : Stored Procedure 입력, 출력 VARCHAR 변수의 Length를 반드시 설정
(TMS에 문제를 일으키는 것으로 보임)
-----
현상 : exec TMS_ORACLE7 -A: Failed.
원인 : ORACLE에서 DB 사용자에게 GRANT(사용허가권)가 없어서 발생하는 문제임.
ORACLE LIB에서 문제가 생길 수도 있다.
조치 : ORACLE의 VIEW중에 V$XATRANS$라는 VIEW를 GRANT시켜주면 조치됨.
ORACLE의 DBA권한에서 실행가능함.
방법: grant all on V$XATRANS$ TO SCRJPCS
여기서 SCRJPCS는 DB USER-ID임.
-----
현상 : DataBase에 연결하지 못한다.
원인 : 1.해당 DataBase에 필요한 환경 설정이 잘못되어 있다.(INVAL Error발생)
2.환경 파일에 환경 설정이 잘못되어 있다.(INVAL Error)
3.DataBase에 권한이 없다.
4.DataBase가 기동되지 않았다.
조치 : 1.set 명령으로 필요한 환경변수 설정을 확인한다.
- Oracle : ORACLE_HOME, ORACLE_SID, ORA_NLS
- Informix : INFORMIXDIR, INFORMIXSERVER
2.구성파일에 설정되어 있는 ENVFILE을 확인한다.
3.해당 User에게 DataBase 권한을 부여한다.
- ORACLE : "v$xatrans$"라는 VIEW에 대하여 해당 User에게 권한을 부여한다.
- INFORMIN : 해당 DB를 사용할 수 있는 권한을 User에게 부여한다.
4.DataBase를 기동하고 Server를 새로 띄운다.
-----
현상 : LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 PLS-00801: Message 801 not found; product=PLSQL; facility=PCM
22/9 PL/SQL: SQL Statement ignored
28/17 PLS-00201: identifier 'JWONRYO.JWONMAS' must be declared
62/9 PL/SQL: SQL Statement ignored
원인 : 현 Database의 Domain 밖에 있는 Table을 Handling하는 경우에 권한이 없는
경우에 발생
조치 : 접근할 수 있는 권한을 부여한다.
-----
현상 : LINE/COL ERROR
-------- -----------------------------------------------------------------
135/5 PL/SQL: Statement ignored
135/9 PLS-00365: 'AVSQLCODE' is an OUT parameter and cannot be read
원인 : OUT parameter를 IN parameter로 사용하고 그 값을 읽은 경우.
조치 : OUT parameter를 IN OUT parameter로 선언.
-----
현상 : ORA-0020
원인 : 프로세스 수를 프로세스를 초과한 경우.
조치 : 프로세스 수를 들여줌.
-----
현상 : ORA-00023: session references process's private memory; cannot detach session
원인 : XA library를 사용하는데 Oracle이 dedicator server로 설치된 경우 발생
조치 : XA library를 사용할려면 Oracle을 MTS mode로 설치되어야 한다.
-----
현상 : 1.ORA-0054 resource busy and acquire with NOWAIT specified
2.ORA-0054 WHEN DROP A TABLE(SESSION KILL)
원인 : 1.Oracle 사용자가 어떤 Row을 Lock를 했는데, 다른 Oracle 사용자가 NOWAIT문을 이용하여
동일한 Row를 Lock를 한 경우에 발생
2.TABLE에 LOCK이 걸려 DML 및 DDL 명령 사용시
조치 : LOCK을 걸고있는 SESSION들을 KILL
-----
현상 : ORA-0059
원인 : DB_FILES 값에 도달한 경우
조치 : init.ora 의 DB_FILES 를 늘려주고 DB 를 Restartup 하면 해결
-----
현상 : ORA-00210: cannot open control file '/dev/vx/rdsk/oracle/v_ctl1'
ORA-07368: sfofi: open error, unable to open database file.
원인 : Sequent Symmetry or NUMA-Q platform이 very large file (O/S에서 2GB
이상의 file system 지원)을 지원하기 위해 VLFS patch를 적용했거나
VLFS를 이미 지원하는 O/S Version일 경우 오라클 master node가 정상적으로
startup 되고 나서 다른 node가 startup parallel이 될 때 먼저 startup 된
master node가 shared disk 의 모든 오라클 관련 file을
none-shared mode로 open 하기 때문에 위의 현상이 발생됨.
조치 : 1.PTX/Cluster V1.3.2일 경우
* Oracle V7.3.x : O/S상에서 VLFS patch적용하지 않았을 경우는 관계
없으나, 이미 적용되었다면 추가적으로 O/S patch FP#23373
적용하여야 함
2.PTX/Cluster running DYNIX/PTX 4.4.x 일 경우
* Oracle V7.3.3 : 현재 fix된 patch는 없으며 다음과 같은
workaround 방법으로 해결이 가능함.

Workaround)
--- $ORACLE_HOME/rdbms/lib/ins_rdbms.mk file에 아래의 추가된 부분만
삽입하여 오라클 kernel relink 실시
(예:make -f ins_rdbms ioracle)
oracle: $(ORALIBD) $(CORELIBD) $(NETLIBD) $(KSMS) $(CONFIG)
$(PSOLIBLIST) opimai.o @$(ECHO) $(LINK) -o $@ $(LDFLAGS)
$(LDFLAGS_ORA) opimai.o $(CONFIG) \
-llkseqora \ ---> 추가된 부분
$(LLIBSERVER) $(LLIBORA) $(LLIBKNLOPT) $(LLIBSLAX)
$(LLIBPLSQL) \
$(LLIBSICX) $(LLIBSOWSUTL) \
$(LLIBSICX) $(LLIBSOWSUTL) \

...........
...........

* Oracle V7.3.4 :
Oracle V7.3.4 일 경우는 문제가 없으나 patchset을 적용할 경우
V7.3.4.2에서는 V7.3.3과 같은 방법으로 oracle kernel을 relink하면
문제가 해결됨.
-----
현상 : ORA-0376 : file %s cannot be read at this time
원인 : DBF가 파손됨.
조치 : Check the state of the file. Bring it online
-----
현상 : ORA-00376: file 29 cannot be read at this time
ORA-01110: data file 29: '/db/GICORP_4/axix01.dbf'
원인 : datafile의 size가 os에서 허용하는 filesize를 초과해서 발생.
조치 : unix의 ulimit filesize를 확인해 보시기 바랍니다.
그리고 datafile size 보다 크도록 수정해 주어야 합니다.
1.unix ulimit filesize를 증가 시킨다
C shell인 경우
% limit filesize <number>
Bourne 이나 Korn shell 인 경우
$ ulimit -f <number>
2.archivelog mode인지 확인합니다
SVRMGR> select * from v$database;

NAME CREATED LOG_MODE CHECKPOINT ARCHIVE_CH
--------- -------------------- ------------ ---------- ----------
GICORP 05/17/00 13:44:56 ARCHIVELOG 36290290 36284249
1 row selected.
3.media recovery가 필요한 datafiles를 찾습니다
SVRMGR> select * from v$recover_file;

FILE# ONLINE ERROR CHANGE# TIME
---------- ------- ------------------ ---------- --------------------
9 OFFLINE 36287415 12/20/00 23:30:55
23 OFFLINE 36289350 12/21/00 08:40:54
28 OFFLINE 36287415 12/20/00 23:30:55
29 OFFLINE 36287415 12/20/00 23:30:55
37 OFFLINE 36287415 12/20/00 23:30:55
5 rows selected.
4.각각의 datafile에 대해서 다음을 실행해 줍니다
SVRMGR> recover datafile '/db/GICORP_4/axix01.dbf';

Media recovery complete.

SVRMGR> alter database datafile '/db/GICORP_4/axix01.dbf' ONLINE;
Statement processed.

5.database를 restart합니다

SVRMGR> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SVRMGR> startup
ORACLE instance started.
Total System Global Area 54578916 bytes
Fixed Size 69348 bytes
Variable Size 20783104 bytes
Database Buffers 33554432 bytes
Redo Buffers 172032 bytes
Database mounted.
Database opened.
SVRMGR>
-----
현상 : ORA-0312,0313 에러(ONLINE LOG CRASH)
원인 : 1.데이타베이스 STARTUP 시 발생
조치 : [ ONLINE LOG 가 손상되었을때 DB에 OPERATION 이 없었던 경우는 다음과 같은 절차로 DB을
OPEN 할수있다 - 확률 70% ]

1.CONTROLFILE 생성
-. 손상된 online log 는 포함시키지 않는다.
-.resetlogs option 으로 생성한다.
-.reuse option 은 생략하고 기존 controlfile 은 다른이름으로 move 시킴.

<V7 에서 CONTROLFILE 생성하는 방법 >
sqldba> startup mount
sqldba> alter database backup controlfile to trace;

위와 같이 명령을 입력하면 ORACLE_HOME/rdbms/log 디렉토리에 트레이스 화일이
생긴다. 그 트레이스 화일에서 create controlfile 명령부분을 남기고 삭제한다.
콘트롤화일 생성 문장 예 - <cnt.sql> : GROUP 1 이 ONLINE LOG 라고 가정
---------------------------------------------------------------------
CREATE CONTROLFILE DATABASE "RC722" RESETLOGS NOARCHIVELOG
MAXLOGFILES 32 ********
MAXLOGMEMBERS 2
MAXDATAFILES 30
MAXINSTANCES 8
MAXLOGHISTORY 800
LOGFILE
GROUP 2 '/oracle/oracle/dbs/log2RC722.dbf' SIZE 5M,
GROUP 3 '/oracle/oracle/dbs/log3RC722.dbf' SIZE 5M
DATAFILE
'/oracle/oracle/dbs/systRC722.dbf',
'/oracle/oracle/dbs/rbsRC722.dbf',
'/oracle/oracle/dbs/toolRC722.dbf',
'/oracle/oracle/dbs/usrRC722.dbf',
'/oracle/oracle/dbs/tempRC722.dbf',
'/oracle/oracle/rcdata.dbf'
;
2.절차
$ sqldba lmode=y
SQLDBA> connect internal
SQLDBA> shutdown abort
SQLDBA> startup nomount
statement processed
SQLDBA> @cnt
SQLDBA> recover database using backup controlfile until cancel;
....
...
CANCEL (Return)
Recovery canceled
SQLDBA> alter database open resetlogs;

: 만일 정상적으로 open 되면 log file 추가
SQLDBA> alter database add logfile '?/dbs/log1ORA722.dbf' size 1M;
: 정상적으로 open 안되면 RC에 다시 연락
-----
현상 : ORA-0439
원인 : BITMAP INDEXES 생성 시 option 이 인스톨되지 않아서 발생
조치 : 반드시 Oracle 8 Enterprise Edition 에서만 사용이 가능하다.
Oracle 8i 에서도 동일하게 적용된다.
-----
현상 : ORA-0600[3339] DATA BLOCK CORRUPTION DETECTION
[3339] [arg1] [arg2] [] [] [] []
ORA-1578 : Data block corrupted in file # block #
원인 : 1.ORACLE이 직접 버퍼로 데이타를 읽어들일 때 읽은 블럭의 DBA(Data Block Address)가 잘못
되었음(INVALID)을 의미
2.ORACLE의 문제가 아니라 OS나 HW의 문제인 경우가 많다.
-----
현상 : ORA-0604: error occurred at recursive SQL level %s
원인 : 1.내부적으로 SQL명령이 실행될 때 발생(현재 할당된 익스텐트가 가득 차서 다음 익스텐트를
할당 받으려고 할 때 오라클이 다음 익스텐트의 크기와 위치를 결정하기 위하여 SELECT
명령을 내리게 되는 것과 같은 경우)
2.init.ora 화일의 파라미터 가운데 DC_FREE_EXTENTS 나 ROW_CACHE_ENQUEUES 의 값이 너무
작게 설정
3.테이블 스페이스가 가득 차거나 Extent 갯수의 최대 허용값을 초과해서 에러가 발생하는
경우 ORA-604 에러가 함께 발생
조치 : 1.?/dbs/init<SID>.ora 화일에 지정된 open_cursors 의 크기를 알아보는 것이다. 이 값이
설정이 안되어 있으면 Default가 50이므로
open_cursors=255
----------------
2.DC_FREE_EXTENTS 나 ROW_CACHE_ENQUEUES들의 값을 크게 설정
3.에러의 원인을 찾기 위해서 init.ora 화일에 다음과 같은 라인을 추가한다.
events = "604 trace name errorstack"
이렇게 init.ora를 변경하고 DB를 Shutdown 하고 Startup 하면 ORA-0604 에러가 발생하는
경우에 자세한 정보를 Trace 화일에 기록해 주므로 이 화일을 검사하여 에러의 원인을
찾을 수 있다.
-----
현상 : ORA-0901 invalid CREATE command
원인 : CREATE 뒤에 오는 KeyWord를 식별하지 못한 경우
-----
현상 : ORA-0902 invalid dadatype
원인 : Oracle에서 제공되지 않은 datatype를 사용한 경우
-----
현상 : ORA-0903 invalid table name
원인 : 테이블의 이름이 Oracle object 명명에 대한 필요조건을 만족시키지 못한 경우
-----
현상 : ORA-0904 열명이 부적합합니다.
원인 : 컬럼이 테이블에 존재하지 컬럼을 사용한 경우
-----
현상 : 083147.gold!stmkdjc.22031: LIBTUX_CAT:522: INFO: Default tpsvrdone() function
used
ORA-0904 : invalid column name
ORA-1003 : no statement parsed
원인 : 1.해당 Table에 존재하지 않은 Field를 사용한 경우
2.Host Variable 앞에 ":"를 덧붙지지 않은 경우
3.해당 Table를 변경하고 관련된 프로그램을 컴파일하지 않은 경우
조치 : 1.해당 Table에 Column이 존재하는지 확인
2.Host Variable 앞에 ":"를 덧붙인다.
3.해당 Table에 관련된 프로그램를 컴파일한다.
-----
현상 : ORA-0906 missing left parenthesis
원인 : 왼쪽 괄호를 찾지 못한 경우에 발생
-----
현상 : ORA-0907 missing right parenthesis
원인 : 오른쪽 괄호를 찾지 못한 경우에 발생
-----
현상 : ORA-0910 specified legth too long for its datatype
원인 : 특정 datatype의 길이가 허용 최대 길이를 초과한 경우
-----
현상 : ORA-0911 invalid character
원인 : Oracle이 뮤효 문자라고 간주하는 것을 만날 때 발생한 에러로 실제문제는 없어진 문자때문
-----
현상 : ORA-0913 too many value
원인 : INSERT문에서 지정된 열의 수보다 열 값의 수가 적으면 발생
-----
현상 : ORA-0917 missing comma
원인 : 1.Comma를 기대하고 있는 SQL문에 comma가 없는 경우
2.오른쪽 괄호가 없는 경우에도 발생
-----
현상 : ORA-0918 column ambiguously defined
원인 : 1.둘 이상의 테이블이 한 SQL문에서 참조될 때 발생
2.한개 이상의 지정된 테이블에 존재하는 어떤 열이 해당 테이블로 한정받지 못한 경우
-----
현상 : ORA-0920 invalid relational operator
원인 : 관계 연산자를 식별하지 못한 경우
-----
현상 : ORA-0921 unexpected end of SQL command
원인 : 불완전한 SQL문일 경우에 발생
-----
현상 : ORA-0922 missing or invalid option
원인 : option에 임의의 문자가 삽입됨(예:NOT NULL --> NOT_NULL)
-----
현상 : ORA-0932 inconsistent datatype
원인 : 1.어떤 연산자를 어떤 열에 적용시키려고 하는데 그것의 datatype을 연산자와 함께 사용한 경우
2.ORA-0997 illegal use of LONG datatype을 복귀시킬 가능성
-----
현상 : ORA-00933: SQL command not properly ended
원인:
-----
현상 : ORA-0934 group function is not allowed here
원인 : SQL문의 WHERE구나 GROUP BY구에서 Group function를 사용한 경우
-----
현상 : ORA-0936 missing expression
원인 : 1.Comma 기술 뒤에 열이나 표현식이 존재하지 않은 경우에 발생
2.ORA-0917 missing comma을 복귀시킬 가능성
-----
현상 : ORA-0937 not a single-group group function
원인 : 어떤 SQL문의 선택 list는 어떤 열이 GROUP BY구에서 참조되지 않으면 그열과 Group function를
포함할 수 없다.
-----
현상 : ORA-0938 not enough arguments for function
원인 : SQL문이 불충분한 수의 인수로 함수를 호출한 경우에 발생
-----
현상 : ORA-0942 : table or view does not exist(테이블 또는 뷰가 존재하지 않습니다.)
원인 : Oracle은 테이블이나 뷰가 존재하지만 사용자가 테이블이나 뷰를 위한 오브젝트 특권(Grant)을 부여하지 않음
조치 : Table 생성 및 권한부여
-----
현상 : ORA-0947 not enough values
원인 : INSERT문에서 지정된 열의 수가 열 값의 수보다 클때 발생
-----
현상 : ORA-0979 not GROUP BY expression
원인 : 어떤 query의 선택 list 안의 한 열이 GROUP BY구에 들어있고 다른 열은 들어있지 않은 경우에 발생
-----
현상 : ORA-0997 illegal use of LONG datatype
원인 : 1.어떤 기능들은 datatype이 LONG인 열에서 수행되지 않는다.
2.Long column은 2G까지 지원을 하지만,
SQL*Plus에서 insert into 문장을 이용하여 long column에 넣을 문자열을
single quote(') 안에 기술 시, 2000 characters가 넘으면 ora-1704 에러가 난다.
조치 : 1.TABLE의 COPY는 가능하지 않으므로,LONG COLUMN을 가진 테이블을 COPY하고자 할 때,
32KBytes 이하의 size라면 다음의 PL/SQL을 사용하면 가능하다.
2.PL/SQL을 이용해야 하며, 경우에 따라 Pro*C, SQL*Loader 등을 이용하여 insert해야만 한다.
-----
현상 : ORA-1001 Invalid Cursor
원인 : Typing 에러, 잘못된 메모리 관리 등의 여러가지 원인에 의해서 발생.
조치 : 1.환경에서 조치할 사항
- PRECOMPILE 옵션 가운데 MAXOPENCURSORS 를 늘려준다.
- init<SID>.ora 화일에서 OPEN_CURSORS 파라미터 값을 늘려준다.
- 사용되지 않는 CURSOR는 OPEN 상태로 두지 말고 CLOSE 시켜준다.
- 지금은 거의 사용되지 않지만 ORACLE V6 를 사용한다면 PRECOMPILE 옵션 가운데
AREASIZE를 512K 정도로 크게 늘려주도록 한다. 그리고 init<SID>.ora 에서
CONTEXT_AREA 값도 늘려준다 .
- TRACE FILE을 이용하면 문제의 원인을 찾는데 있어 유용할 때가 있다.
2.그 밖의 경우
- OPEN 되지 않은 CURSOR 에 대해서 작업을 할 때
- 존재하지 않는 OBJECT에 대해서 SQL 명령을 실행할 때
- CURSOR CACHE로부터 삭제된 경우
- CURSOR CACHE로부터 삭제된 또다른 경우
PRECOMPILE 옵션 가운데에서 MAXOPENCUSORS 를 늘려주거나
HOLD_CURSOR=YES, RELEASE_CURSOR=NO 로 설정
- XA/TUXEDO 환경에서 ORA-1001 에러가 발생하는 경우(일부 ORACLE 버젼에서 발생)
-----
현상 : ORA-1002 FETCH OUT OF SEQUENCE IN PRO*C(stop[<fltmsjaud>]:리스너를 중단합니다.
원인 : 1.user가 더이상 유효하지 않은 cursor로부터 fetch를 하려고 하기 때문
2.ORA-1403 등과 같이 NO DATA FOUND를 return하는 fetch작업을 수행할때
3.SELECT FOR UPDATE를 가진 cursor 의 fetch작업내에 commit이 있는 경우
조치 : 3.commit을 fetch loop의 바깥쪽으로 빼거나 select for update문을 사용하지 않아야 한다.
-----
현상 : ORA-1012 Error( not logged on )가 발생
원인 : 1.tpbegin()이 되어 있지 않음
2.PC쪽에서 NOTRAN Mode로 Service를 호출
조치 : 1.Program을 확인한다.
2.flag를 0으로 Setting한다.(TRAN Mode로 Service 호출)
3.Service절에 Default에 AUTOTRAN을 "Y"로 설정하고 해당 Service명을 기술한다.
-----
현상 : ORA-1027 bind variables not allowed for data definition operations
원인 : WHERE에 BIND_VAR 를 이용한 CREATE VIEW 는 불가능
조치 : 이 경우 EXEC SQL CREATE TABLE IMAGE
(EMPNO NUMBER(4) NOT NULL, BITMAP LONG RAW)
END-EXEC.
이 처럼 create 해야 한다.
-----
현상 : ORA-1031 insufficient privileges
원인 : 사용자가 테이블이나 뷰와 연관된 적어도 한 개의 object 특권을 부여받았지만 SQL문에서 지정된
특권을 부여받지 않았을 때 발생
1.ORACLE의 SYSTEM 유저에 POWERBUILDER의 BASE TABLE 5개가 생성이 되어 있지
않은 경우
2.SYSTEM 유저로 접속한 후에도 일반 유저가 접속이 되지 않을 경우
조치 : 1.5개 base table(pbcatcol, pbcattbl, pbcatfmt, pbcatvld, pbcatedt)을
drop한 다음 system 유저로 접속을 하고, 다시 일반 유저로 접속하는 방법.
2.system 유저로 들어가서 5개 base table에 대한 사용 권한을
일반 유저에게 주는 방법.
$sqlplus system/manager

SQL>grant all on pbcatcol to public;
SQL>grant all on pbcatedt to public;
SQL>grant all on pbcatfmt to public;
SQL>grant all on pbcattbl to public;
SQL>grant all on pbcatvld to public;
-----
현상 : ORA-1034, "ORACLE not available"
ORA-7320, "smsget: shmat error when trying to attach sga."
ORA-7429, "smsgsg: shmget() failed to get segment."
원인 : ORACLE DBA 사용자만 데이타베이스를 ACESS할수 있고 다른 사용자는 SQL*PLUS 등을 통하여
CONNECT를 하려고 할때 다음 에러가 발생 할경우
-----
현상 : TPFAILED ......................
sqlca.sqlcode ==> -1036
ORACLE에서 단독으로 실행하면 문제가 발생되지 않고 OUTPUT을 정확하게 출력하지만
TP/M와 함께 실행이 되면 SQL SELECT문을 수행하지 못하고 sqlca.sqlcode ==> -1036의
MESSAGE를 뿌리고 실행을 멈춘다.
원인 : ORACLE에서 Version간의 Segment 정의부분이 다르기 때문
조치 : makefile 혹은 proc.mk file에서
sqlcheck=semantic userid=scrjpcs/scrjpcs를 포함시킨다.
-----
현상 : ORA-1039: insufficient privileges on underlying objects of the view.
원인 : SYS user가 아닌 다른 user로 SQL Analyze에 로그인하여 SQL statement에 대한 explain plan 옵션을 사용할 때 다음과 같은 에러가 발생
조치 : 1.dictionary table/view들을 validate시켜 놓으려면 dba가 read 권한만 SQL Analyze를 수행하는 user에게 grant하면 충분하다.
2.SYS user로서 SQL explaining을 수행하는 것이다.
-----
현상 : ORA-9992 scumnt: failed to open <FILENAME>
ORA-9993 scumnt: failed to lock <FILENAME>
ORA-1102 cannot mount database in exclusive mode
원인 : 서로 독립적인 두개의 instance가 동일한 database file들을 동기화 (synchronisation)없이 access할 수 있기 때문에 database corruption을 유발시킬 수 있었다.
조치 : database의 db_name이 변경되면 각각의 lk<DB_NAME> file을 생성.
-----
현상 : ORA-01118: cannot add any more database files: limit of XXX exceeded
원인 : 데이타 화일의 갯수가 MAXDATAFILES 값에 도달한 경우 발생
조치 : MAXDATAFILES를 늘리기 위해서는 DB를 새로 만들어야 하며 그 이후 버젼을 사용중이라면 콘트롤
화일을 새로 만들어서 MAXDATAFILES를 늘릴 수 있다
-----
현상 : ORA-1157 : cannot identify data file 11 - file not found
ORA-1110 : data file 11 : '/user1/oracle7/dbs/user2.dbf'
원인 : OS 명령으로 DATA FILE 을 삭제한 경우
조치 : DATABASE STARTUP시 STARTUP MOUNT 단계까지 실행한 후, 문제의 데이타 화일을 OFFLINE 시킨다.
데이타베이스를 오픈한다. 단 데이타베이스 오픈이 정상적으로 수행되면 문제가 발생한 데이타
화일을 포함하고 있는 TABLESPACE를 DROP하지 않을 경우에는 DATABASE STARTUP시 항상 데이타
화일의 오픈 단계에서 에러가 발생된다. 따라서, 문제의 데이타 화일의 OFFLINE과 TABLESPACE의
DROP전에 반드시 해당 TABLESPACE를 사용하고 있는 USER의 데이타 백업을 수행해야 한다.

데이타 화일의 OFFLINE과 관련된 명령은 다음과 같다.
SQLDBA를 COMMAND LINE MODE로 기동시킨다.

$ sqldba lmode=y
SQLDBA> CONNECT INTERNAL;
SQLDBA> STARTUP MOUNT;
ORACLE instance started.
Database mounted.
SQLDBA> ALTER DATABASE DATAFILE '/user1/oracle7/dbs/user2.dbf'
OFFLINE DROP;
Statement processed.
SQLDBA> ALTER DATABASE OPEN;
Statement processed.
SQLDBA> DROP TABLESPACE tablespace_name INCLUDING CONTENTS;
Statement
-----
현상 : ORA-01237 cannot extend datafile %s
원인 : O/S 레벨에서는 file size를 1TB 이상 지원한다고 하는데, oracle datafile을 2G 이상으로 resize하려고 한다거나 tablespace에 datafile을 추가하거나 생성할 때, 2G 이상 주면 file size limit에 걸리는 현상 발생
조치 : 화일 시스템에서 large file을 사용하기 위해서는 화일 시스템을 'largefiles' option으로 mount해야 한다.
-----
현상 : ORA-1400 primary key or mandatory(NOT NULL) column is missing or NULL during insert
원인 : 어떤 필수적인 열을 위한 값을 공급하지 않은 경우
-----
현상 : ORA-1401 inserted value too large for column(열에 입력한 값이 너무 큽니다.)
원인 : 문자열을 할당하고자 할때 길이가 최대치를 초과한 경우
-----
현상 : ORA-1403 no dada found
원인 : 사실상 전혀 Error가 아니다.
-----
현상 : ORA-1405 fetched column value is NULL
원인 : ERROR 가 아니고 WARNING MESSAGE 이다.
조치 : dbms=v6 를 PRECOMPILER OPTION 에 추가해준다. dbms=v6 로 SETTING 할경우는 HOST 변수에
NULL 이 RETURN 되더라도 sqlca.sqlcode 는 0 이 된다.
-----
현상 : ORA-1407 cannot update mandatory(NOT NULL) column to NULL
원인 : 필수적인 열의 값을 NULL에 설정한 경우에 발생
-----
현상 : ORA-1408 such column list already indexed
원인 : 이미 동일한 열 List에 기초한 Index를 갖고 있는 Table에서 Index를 작성하고자 하는 경우에 발생
-----
현상 : ORA-1410 invalid ROWID
원인 : 1.적절한 Format으로 ROWID를 상술하지 않은 경우에 발생
2.지정된 ROWID가 존재하지 않은 경우에 발생
-----
현상 : ORA-01438: 지정한 정도를 초과한 값이 열에 지정되었습니다.
원인 : 지정한 자릿수를 초과한 Column이 존재한 경우에 발생
-----
현상 : ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "SYS.STANDARD", line 648
ORA-06512: at "BETH.BETH", line 6
ORA-06512: at line 1
원인 : SELECT 문에서 조건에 해당하는 row가 2건 이상
return되었을 때 발생하는 TOO_MANY_ROWS 에러와 동일한 에러이다.
조치 : 확인한 결과 DUAL table에서는 비록 2개의 ROWID를 볼 수는 없지만,
실제 2개의 row가 DUAL table에 존재하는 상황이다.
따라서, 다음 명령을 이용하여 여분의 필요없는 row를 delete해야 한다.
-----
현상 : ORA-1449 column contains NULL values; cannot alter to NOT NULL
원인 : 어떤 열을 필수적인 것으로 변경하고자 하나 적어도 테이블 내의 한 행이 그 열을 위한 NULL값을
가질 때 발생
-----
현상 : ORA-1452 cannot CREATE UNIQUE INDEX; duplicate keys found
원인 : 값이 독특하지 않은 일련의 열에서 독특한 인덱스를 작성한 경우에 발생
-----
현상 : ORA-1453 SET TRANSACTION must be first statement of transaction
원인 : 모종의 다른 SQL문 이후에 SET TRANSACTION문을 기동할 때 발생
-----
현상 : ORA-01458 Invalid length inside variable character string
원인 : DB Table field의 길이와 Host Variable의 길이 차이가 있을때 발생한다.
그러므로 Table field의 길이와 Host Variable의 길이를 비교해 본다. 혹은 Stored
Procedure의 Input Parameter가 Null 값으로 넘겨질 때도 발생한다.
조치 : DB Table field와 Host Variable의 길이를 조정한다.
Stored Procedure의 Input Parameter에 Null값을 0의 값을 채워서 넘긴다.
주의 : Stored Procedure에서 Cursor를 사용할 때
FOR ... LOOP를 사용할 때 주의를 해야한다.
FOR i IN 1..batch_size LOOP
FETCH get_emp
INTO
emp_name( i )
,job( i )
,sql( i )
;

IF get_emp%NOTFOUND THEN -- if no row was found
CLOSE get_emp;
done_fetch := 100; -- indicate all none
EXIT;
ELSE
done_fetch := 900; -- indicate all none
found := found + 1; -- count row
END IF;
END LOOP;
에서 Fetch Array의 0번째에 Data를 저장할 때 문제가 생긴다.
그러므로, emp_name( 0 )이라고 하면 Error를 발생한다.
-----
현상 : ORA-01476: divisor is equal to zero
원인 : Zero값으로 임의의 수를 나누었을때 발생
-----
현상 : ORA-01480: trailing null missing from STR bind value
원인 : 1.해당 Column의 Size 보다 더 큰 값이 들어온 경우에 발생
2.Character Type(CHAR, VARCHAR)의 Host variable인 경우 변수 선언시 Table의 Column size 만큼의 변수길이를 선언한 경우 발생
조치 : 1.해당 Column의 Size와 해당값을 확인
2.Character Type(CHAR, VARCHAR)의 Host variable인 경우 변수 선언시 Table의 Column size에 1를 더해 주어야 한다.
(데이터의 마지막에 NULL 문자를 포함해야 하기 때문에)
-----
현상 : ORA-1481 invalid number format model
원인 : 어떤 숫자 Format Model이 미정의 문자를 포함한 경우에 발생
-----
현상 : ORA-1547 : Failed to allocate extent of size 'num' in tablespace 'TOOLS
원인 : TABLESPACE가 에러에 명시된 ORACLE block 수 만큼의 요청된 EXTENT를 할당할 충분한 FREE
SPACE를 갖고있지 못할 경우에 발생
조치 : 1.해당 TABLESPACE내에서 연속된 영역의 ORACLE block 할당할 수 있도록 데이타 화일을 추가
2.TABLE의 STORAGE PARAMETER에서 INITIAL EXTENT, NEXT EXTENT의 크기를 조정하여 TABLE을
재구축
3.다음의 방법으로는 관련 TABLESPACE를 재구성하는 것
-----
현상 : ORA-1552 (CANNOT USE SYSTEM ROLLBACK SEGMENT FOR NON-SYSTEM TABLESPACE '%S')
원인 : SYSTEM TABLESPACE 이외의 TABLESPACE를 포함한 OPERATION을 위하여 SYSTEM TABLESPACE의
ROLLBACK SEGMENT를 사용할 경우에 발생
조치 : SYSTEM TABLESPACE에 하나 이상의 ROLLBACK SEGMENT를 추가한 다음, 데이타베이스 오브젝트를
생성
-----
현상 : ORA-1555 Snapshot Too Old
원인 : 1.데이타의 변경이 심한 데이타베이스에서 롤백 세그먼트의 갯수와 크기가 작을 경우에 발생
2.롤백 세그먼트가 손상되어 읽을 수 없게 된 경우
3.Fetch Across Commit(테이블에 대하여 Query가 커서를 열고 루프 내에서 데이타를 Fetch
하고 변경하고 커밋하는 과정에서 발생)
4.Delayed Block Clean Out(데이타 블럭이 변경되고 커밋되면 오라클은 롤백세그먼트 헤더에
그 트랜잭션이 커밋되었다고 기록하지만 데이타 블럭을 바로 변경하지는 않는다 (Fast
Commit). 그리고 다음 트랜잭션이 변경된 블럭을 요구할 때야 비로소 변경 시키는것
조치 : 1.커서가 Open된 상태에서는 커밋을 자주하지 않고 롤백 세그먼트 크기를 키워 나가도록
2.커서를 사용하기 전에 Full Table Scan을 해주면 예방이 가능
-----
현상 : ORA-1562(Failed to extend rollback segment(id = %s))
원인 : 1.사용중인 ACTIVE 상태의 ROLLBACK SEGMENT가 다음 EXTENT를 할당하고자 할 경우
2.해당 ROLLBACK SEGMENT에 대하여 발생 가능한 최대 EXTENT 수를 초과할때 발생
조치 : ROLLBACK SEGMENT의 재생성
-----
현상 : ORA-01578: ORACLE data block corrupted (file # 6, block # 3)
ORA-01110: data file 6: '/tmp/ts_corrupt.dbf'
원인 :
조치 : 해당 objects를 drop하고 recreate하여 처리
-----
현상 : ORA-01578
원인 : data block 에 corruption 이 생긴 경우에 발생.
조치 : 1.최선의 해결책은 backup 받아둔 file 을 restore 한 후 recover 작업을 하는 것이다.
2.backup datafile 을 restore 하고 recover 하지 않을 것이라면 우선, 어떤 object 에서 corruption 이 발생하였는지 확인해야 한다.
3.해당 segment 가 non-data dictionary index 라면, 해당 index 를 drop 한 후 재생성한다.
4.해당 segment 가 table 이라면, corruption 이 발생한 block 의 data 는 소실된 것이다.
5.만약 해당 table 에 대한 최근의 export dump file 이 존재한다면, 해당 table 을 drop 한 후 import 함으로써 복구할 수 있다.
6.corruption 이 발생한 non-clustered table 에서 corrupted block 을
access 하지 않고 나머지 data 들을 select 할 수 있도록 ROWID 를 이용할
수 있다.
7.만약 data dictionary 에 속하는 table, index 또는 rollback segment에
corrupted block 이 발생하였다면 Oracle Support 의 지원을 받는다.
8.일반적으로, ORA-1578 은 hardware 의 문제때문에 유발된다. 하지만 만약에
ORA-600[3374] 가 발생한다면 memory 상에서 corruption 이 발생한
경우이다. 이 경우 database 를 restartup 하면 문제가 해결될 수 있다.
-----
현상 : ORA-1591(Pending Transaction의 처리)
원인 : 분산 트랜잭션의 경우 2 phase commit수행 단계중에 fail이 발생하게 되면 관여된 일부 database에서는 rollback 혹은 commit이 되고, 일부는 distributed lock이 걸린 상태로 계속 지속될 수 있다.
이렇게 pending된 transaction에 대해서는 기본적으로 Oracle의 background process인 RECO process가 자동으로 정리하여 주나, 경우에 따라 자동으로 정리가 되지 못하는 상황이 발생
조치 : STEP 1: alert.log file을 check한다.
STEP 2: network 환경을 확인한다.
STEP 3: RECO process가 떠 있는지 확인한다.
STEP 4: DBA_2PC_PENDING을 조회해 본다.
STEP 5: DBA_2PC_NEIGHBORS view를 조회해 본다.
STEP 6: commit point site를 확인한다.
STEP 7: DBA_2PC_PENDING의 MIXED column을 확인한다.
STEP 8: DBA_2PC_PENDING의 STATE column의 값을 확인한다.
STEP 9: 불일치 사항을 파악하고 DBA_2PC_PENDING을 정리한다.

2PC에서 1st phase commit(xa_prepare)이 정상적으로 종료되면 Oracle의 dba_pending_transaction에 해당
Transaction에 대한 정보가 나타난다.

formatid 40
globalid 636861656A750000000000000000000000000000000000
5B5103A6BEC9900000DE8
branchid 0000006600000065

이 상태에서 일정한 시간 내에 2nd phase commit(xa_commit)에 끝나지 않으면 dba_2pc_pending에도 이
Transaction이 나타난다.

local_tran_id 4.24.3026
global_tran_id 40.636861656A750000000000000000000000000000000000
5B5103A6BEC9900000DE8
state prepared
mixed no
advice
tran_comment
fail_time
force_time
retry_time
os_user jun
os_termina
host chaeju
db_user
commit# 5332231

위에서 "일정한 시간"이란 용어를 사용했는데 Oracle의 문서에는 이에 관한 정확한 언급은 없다.
다만, 다른 Transaction에서 해당 레코드를 참조하려고 할 때 이미 lock이 걸려 있으므로 대기하는
시간에 대해서는 init.ora에서 지정하는 distributed_lock_timeout에 대해서만 언급하고 있다. 그런데
oracle 8.1.7에서는 distributed_lock_timeout을 설정하면 obsolete로 나온다.

이 시간 동안에 해당 레코드에 대한 lock이 풀리지 않으면 아래와 같은 에러를 만난다.

ORA-02049: time-out: distributed transaction waiting for lock

위의 에러가 발생한 이후에 이 레코드를 참조하려고 하면 1591 에러가 나타난다.

ORA-01591: lock held by in-doubt distributed transaction '4.24.3026'

보는 것처럼 ORA-01591 에러 메시지에는 local_tran_id가 있다. 이를 이용하여 dba_2pc_pending에서
global_tran_id를 조회하고, 이 데이터는 dba_pending_transaction의 formatid와 globalid로 이루어져
있으므로 이를 이용하여 dba_pending_transaction에서 branchid도 얻을 수 있다.

이들로 부타 아래와 같이 XID를 얻을 수 있다.

xid.formatid = dba_pending_transactions.formatid
xid.gtrid_length = len(dba_pending_transactions.globalid)
xid.bqual_length = len(dba_pending_transactions.branchid)
xid.data = dba_pending_transactions.globalid + dba_pending_transactions.branchid

여기까지는 Oracle로 부터 XID를 얻는 과정이다.

tpconvert(str, (char *)&xid, TPTOSTRING | TPCONVXID)를 이용하여 XID의 string 표현을 얻을 수 있고
이값을 이용하여 .TMIB 서비스를 호출하면 아래와 같은 정보를 얻을 수 있다.

TA_ERROR 0
TA_MORE 0
TA_OCCURS 1
TA_GRPCOUNT 2
TA_GRPINDEX 0
TA_GRPNO 102
TA_GRPNO 101
TA_TIMEOUT 9
TA_COORDGRPNO 102
TA_CLASS T_TRANSACTION
TA_STATE READY
TA_COORDLMID SITE1
TA_GSTATE READY
TA_GSTATE READY
TA_TPTRANID 0x0 0x3a6bec99 0xde8 0x28 0x0 0x0
TA_XID 0x0 0x3a6bec99 0xde8 0x28 0x66
TA_COORDSRVGRP APPGRP2
TA_LMID SITE1
TA_SRVGRP APPGRP2
TA_SRVGRP APPGRP1

위의 경우에는 아직 Tuxedo가 transaction에 대한 정보를 가지고 있기 때문에 별다른 조치가 필요없다.
하지만, Oracle의 dba_2pc_pending에는 있는데 Tuxedo에서 해당 Transaction에 대한 정보를 가지고
있지 않은 경우에는 Oracle에서 rollback force나 commit force를 이용하여 pending transaction을
정리해 주어야만 lock이 풀린다.
-----
현상 : ORA-1628, 00000, "max # extents (%s) reached for rollback segment %s"
ORA-1630, 00000, "max # extents (%s) reached in temp segment in tablespace %s"
ORA-1631, 00000, "max # extents (%s) reached in table %s.%s"
ORA-1632, 00000, "max # extents (%s) reached in index %s.%s"
원인 : 오브젝트의 익스텐트가 MAX # 에 도달 했기 때문에 발생되며 오브젝트의 MAXEXTENTS는
STORAGE 의 MAXEXTENTS 파라미터에 의해 결정
조치 : ALTER TABLE .. STORAGE (MAXEXTENTS n)를 사용하여 최대 MAXEXTENTS 값보다 작은 수로
MAXEXTENTS를 늘려준다.
-----
현상 : ORA-1652, 00000, "unable to extend temp segment by 6144 in tablespace "VESSEL"
원인 : 테이블이나 인덱스 등을 만들 때 자신의 TEMP TABLESPACE 가 아닌 곳에서 ORA-1652(temp
tablespace가 부족함) 에러가 발생
조치 : 에러메시지에서 보여주는 대로 해당 테이블스페이스에 Temporary Segment 가 생성될 만한
연속된 공간을 마련하여 주는 것
-----
현상 : ORA-1653
원인 : 특정 tablespace 에 space 가 부족해서 table의 extent가 일어나지 못해서 발생
조치 : user의 default tablespace 를 변환한 후, 이 default tablespace
안에 create table을 다시 한 후 sql*loader 를 실행한다
-----
현상 : ORA-1654 ERROR ON INDEX SEGMENT
원인 : tablespace가 적어 extent 영역을 할당할 수 없어서 발생
조치 : datafile을 추가 시 이전값 이상의 사이즈를 추가해야 함.
-----
현상 : ORA-1722 invalid number
원인 : 수치값이 불법일 경우
-----
현상 : ORA-1747 열명을 올바르게 지정해 주십시요.
원인 : 열명이 다른 경우(SQL문장 기술시 첫번째 열명 앞에 Comma를 삽입한 경우)
-----
현상 : tb_ra315 insert error ORA-02291: integrity constraint (SCRJAPPR.A315_E007_FK)
violated - parent ....
원인 : Table과 관련된 Reference 관계로 parent table의 data가 없는 관계로 data 입력불가
조치 : Reference 관계를 끈어주든지 아니면 관계된 Table에 Data를 모두 입력하는 방법.
-----
현상 : ORA-02303: cannot drop or replace a type with type or table dependents
원인 : Type이나 table의 dependency가 있는 type을 drop하거나 replace하고자 할 때 발생.
조치 : SQL Reference guide에 의하면 DROP TYPE FORCE 옵션은 recommend하지 않는다.
왜냐하면 이 옵션을 쓰게 되면 복구가 불가능하고 dependency가 있던 table들은
access하지 못하는 결과를 초래한다.
-----
현상 : ORA-03113: end-of-file on communication channel
원인 : 1.이전에 작동했던 해당 instance의 shared memory segment들이 아직 system에 남아있어서 발생.
2.서버의 Oracle 쉐도 프로세스가 예기치 않게 종료된 경우 발생.
3.SQL*NET 드라이버가 Unix의 ORACLE 실행 파일과 연결되지 않아 발생한 경우.
4.서버쪽의 기계 손상이나 네트워크 고장인 경우.
5.네트워크에서 두 서버가 같은 노드 이름을 가질 때에도 이 오류가 발생.
6.모든 원인은 결국 클라이언트가 서버로부터 어떤 정보를 읽으러 갔다가 거기서 더 이상 연결이 없음을 발견했다는 뜻임.
7.Oracle XA를 사용하는 AP 서버 혹은 TMS 서버가 떠 있는 상황에서 연결된 DB를 재기동 시키거나 혹은 다른 문제로 인해서 데이터베이스와의 연결이 끊어진 경우에 발생
조치 : shared memory를 check하여 oracle이 소유하고 있는 shared memory segment를 삭제하여 문제를 해결.
자동으로 재접속을 하기 위해서는 TUXWA4ORACLE(WorkAround For Oracle) 환경변수를 1로 설정하면 해당 서버가 오라클에 접근하여 3113 에러가 발생하는 순간에 재접속이 이루어진다.
(XA 서버에만 해당되며 Non-XA 서버의 경우는 사용자 coding에 의해서 동일한 기능을 구현할 수 있다.)
-----
현상 : ORA-3114 Error( not connected to ORACLE )가 발생
원인 : ORACLE이 Shutdown 되었다.
조치 : ORACLE이 떠 있는지 확인하고, Server를 새로 기동한다.
-----
현상 : ORA-3121
원인 : SQL*NET V2를 통해 연결하려 할 때 연결 스트링에 'tns:'net접두어를 사용하지 않은 경우
조치 : 구버전인 SQL*NET V1의 net 접두어 (SQL*Net TCP/IP에 대한 "t:"등)를 사용하지 않도록 주의
하십시요.
-----
현상 : ORA-4068 existing state of packages%s%s%s has been discarded
원인 : 응용프로그램 실행 중에 사용하고 있는 Stored Procedure를 Compile하는 경우에 발생
조치 : 응용프로그램을 재기동시킨다.
-----
현상 : ORA-4091 table name is mutating, trigger/function may not see it
원인 : DataBase Trigger가 Transaction 내에서 변경된 테이블에 대하여 Query를 기동할 때 발생
조치 : 1.PL/SQL table을 생성한다.
2.BEFORE STATEMENT trigger를 생성한다.
3.AFTER ROW trigger를 생성한다.
4.AFTER STATEMENT trigger를 생성한다.
5.data insert 및 확인
-----
현상 : ORA-4092 cannot COMMIT or ROLLBACK in a trigger
원인 : 1.Trigger가 COMMIT or ROLLBACK을 실행하고자 할 때 발생
2.Trigger가 내장 프로시저, COMMIT나 ROLLBACK될 함수, 패캐지 서브프로그램을 호출한 경우
-----
현상 : ORA-6106,ORA-6120 NETTCP : socket creation failure
원인 : WIN V1.X용 SQL*NET TCP/IP는 SQLTCP.DLL과 SQLTCP1.DLL들은 ORACLE용 연결 스트링이 TCP/IP
프로토콜 스트링으로 변환되면 OCI DLL에 의해 작업 진행중에 올려집니다. ORACLE INTERFACE
DLL은 SQLTCP.DLL을 먼저 올리려고 합니다. 이것이 실패하면 DOS TSR 버전의 드라이버를
찾습니다. 두 가지 모두 실패하면 ORA-3121 메세지가 나옵니다.
-----
현상 : ORA-6108
원인 : 1.부적절한 machine, 또는 machine는 맞지만 틀린 포트를 지정할 때 발생
2.TCP/IP 레이어는 모든 연결 요구를 Listener의 소켓 큐에 넣을 수 없을 경우 발생
3.네트워크가 아주 혼잡하고 호스트에 도달하려는 중에 시간이 종료할 경우
조치 : 1.클라이언트에서 호스트 Machine에 대해 ping을 실행하십시요. 대부분의 PC TCP/IP업체는
"ping" 유틸리티를 제공합니다. 클라이언트 Machine에서 다음을 입력하십시요
ping <host IP address>
이 방법으로 잘 되지 않으면 아마도 호스트 machine이 down된 것입니다. IP 주소를 사용
하여 호스트에 대해 ping을 성공적으로 실행할 수 없으면, 서버의 호스트 이름을 사용하여
ping을 실행해 보십시요.
ping <hostname>
호스트 이름을 사용하여 ping을 실할 수 없으면 TCP/IP 구성을 점검하십시요. 호스트 이름
을 가지고 ping을 실행할 수 없으면, 연결 스트링에 호스트 이름을 사용하여 SQL*NET와
연결할 수 없습니다.
2.SQL*NET TCP/IP Listener가 해당 서버에서 실행중인지 점검하십시요. 서버의 UNIX프롬프트
에서 다음을 입력하면 됩니다.
ps -al|grep "orasrv"
이 때 최소한 한 행이 표시되어야 합니다. 그렇지 않으면 UNIX 프롬프트에서 "orasrv"
또는 "tcpctl start"를 입력하여 수화자를 띄우십시요. SYSADMIN 특권을 가지고 해당 기계
에 로그인해야 합니다.
3.서버쪽에서 루프백을 할 수 있는 지, 다시 말해서 PC 클라이언트에서 지정한 것과 같은
연결 스트링을 사용하여 서버의 툴을 연결할 수 있는지 점검하십시요. 예를 들면, 서버의
SQLPLUS 또는 SQLDBA를 호출하고 서버의 SQLPLUS 또는 SQLDBA 프롬프트에서 다음을 입력
하십시요.
CONNECT USERNAME/PASSWORD@t:<servername>/<portnum>:<sid>
4.루프백 성사되면 호스트 서버의 ORASRV 포트 번호를 확인하십시요. (대부분의 기계에서
SERVICE 파일은 /etc 디렉토리에 있습니다.) 또한 "tcpctl" 유틸리티를 사용하면 대부분의
UNIX 기계에서 ORACLE Listener를 시작하거나 멈출 수 있습니다. "tcpctl stop"로 Listener
를 종료하십시요. "tcpctl start"으로 다시 시작하십시요. 이때 시작 포트에 관한 정보가
표시됩니다.
5.이것이 성공하면 포트를 지정하지 말고 포트를 연결해 보십시요.
t:<servername>:<sid>
연결되지 않으면 클라이언트에서 SERVICE 파일을 정확하게 설정하 않았기 때문입니다.
a)WINDOWS\WIN.INI를 점검하여 [Oracle] 부분의 ORA_CONFIG 매개 변수가 어떤 구성 파일을
지시하고 는지 알아보십시요. 이폴트는 다음과 같습니다.
[Oracle]
ORA_CONFIG=C:\WINDOWS\ORACLE.INI
b)ORACLE.INI 파일을 보고 TCP_SERVICES_FILE 매개변수가 설정되었고 SERVICES 파일을 지시
하고 있는 지 확인하십시요.
c)SERVICES 파일을 보고 다음 항목이 있는 지 확인하십시요.
orasrv 1525/tcp oracle
6.또한 서버가 SQL*NET V2가 아니라 SQL*NET V1을 실행중인지 확인하십시요.
7.결 스트링의 재시도 매개변수를 증가시켜 보십시요. 재시도 횟수를 지정하는 구문은 다음과
같습니다.
t:host[/service]:SID[,buffer-size][:conn-retries]
conn-retries의 디폴트는 1입니다.
8.VAX에 연결할 경우에는 VAX config.ora 파일에 다음행이 있는지 확인하십시요.
SQLNET USERNAMEMAP*=*
이것은 VAX account가 없는 PC가 디폴트 사용자 account을 사용하여 연결 할 수 있게 해
줍니다.
-----
현상 : ORA-6110 "NETTCP: message send failure"
원인 : Windows 클라이언트의 TCP/IP사이에 버퍼 조정문제가 있을 때 발생
조치 : 1.버퍼 크기를 연결 스트링에 포함시켜 일정한 크기로 고정하는 것
t:<servername>:<sid>,<buffersize>
연결 스트링에 버퍼 크기를 포함시킨 후에도 여전히 ORA-6110이 발생하면 더 작은 값을
사용해 보십시요. WINDOWS용 SQL*NET TCP/IP의 기본 버퍼 크기는 4096입니다. 이것을
1024로 사용하면 대개 ORA-6110에러가 없어집니다.
2.서버쪽
1)서버에서 루프백을 수행할 수 있습니까? 다시 말해서 PC 클라이언트에서 지정한 것과
같은 연결 스트링을 사용하여 서버의 툴을 연결할 수 있습니까? 예를 들어 서버에서
SQLPLUS 또는 SQLDBA를 호출하고 에러가 없어집니다.
CONNECT USERNAME/PASSWORD@t:<servername><portnum>:<sid>
루프백을 실행하면 실제 문제를 더 잘 보여주는 다른 에러가 나타나는 수도 있습니다.
2)ORA-6110은 Oracle실행 파일에 사용 권한이 정확하게 설정 되어 있지 않으면 Unix 서버에
연결할 때도 발생할 수 있습니다. Oracle과 orasrv의 사용권한은 다음과 같이 설정되어야
합니다.
>chmod 6755 oracle
>chmod 6755 orasrv
이 때, Permission는 다음과 같이 설정됩니다.
-rwsr-xr-x 1 oracle dba ...size ...date oracle
-rwsr-xr-x 1 root dba ...size ...date oracle

3)ORA-6110과 틀린 네트워크 주소
TCP/IP 네트워크에서 중복 IP주소가 살아 있으면 ORA6110이 발생할 수 있습니다. 네트
워크의 모든 IP주소가 고유의 것인지 확인하십시요.
-----
현상 : ORA-6122 "NETTCP: setup failure
원인 : SQL*NET 구성이 적절하게 설정되지 않은 상태에서 WINDOWS용 SQL*NET TCP/IP를 가지고 연결
하려 할 때 발생
조치 : 1.WINDOWS\WIN.INI를 조사해 보십시요. ORA_CONFIG 매개 변수를 정의하는 ORACLE 부분이
있어야 합니다
[Oracle]
ORA_CONFIG=C:\WINDOWS\ORACLE.INI
2.ORACLE.INI(또는 ORA_CONFIG 매개변수가 지시하는 파일)을 보십시요. ORACLE_HOME이
WINDOWS용 SQL*NET TCP/IP와 다른 Oracle Windows 응용 프로그램이 설 된 디렉토리를
지시하는 지 확인하십시요. 디폴트는 다음과 같습니다.
ORACLE_HOME=\ORAWIN
3.또한 ORACLE.INI에 TCP_VENDOR를 정확하게 설정했는지도 확인하십시요.
4.경로에 C:\ORAWIN\BIN(또한 ORACLE_HOME을 설정한 BIN 디렉토리)이 있는지 확인하십시요.
DOS프롬프트에서 SET을 입력하고 <return>을 누르면 됩니다. 이명령은 경로를 보여줍니다.
5.ORAWIN\BIN 디렉토리에 SQLTCP.DLL과 SQLTCP1.DLL이 모두 있는지 확인하십시요.
6.경로의 다른 어떤 디렉토리에도 SQLTCP.DLL이 없는 것을 확인하십시요.
7.ORAWIN\BIN 디렉토리와 경로의 다른 디렉토리에 MSOCKLIB.DLL이 있는 지 확인하십시요.
또한 파일의 두 복사본을 가지고 있지 않도록 하십시요. 복사본이 둘일 경우, 이전 복사본
의 이름을 바 면 문제가 줄어들 수 있습니다.
8.WINDOWS 디렉토리에 VSL.INI 파일이 있는지 확인하십시요. 만약 없으면 ORACLE INSTALLER
를 통해 SQL*NET를 다시 입력하십시요.
-----
현상 : ORA-6136, 00000, "NETTCP: error during connection handshake"
원인 : 1.Client and Server 환경에서 간혹 SQL*NET으로 Server에 접속하려고 할 경우
2.Unix Server에서 $tcpctl stop 으로 orasrv의 Process를 정지시키려고 해도 아무런 반응
없이 Holding되는 경우가 발생
조치 : 1.TCPCTL Utility를 이용하여 다음의 Option을 부여하여 Start하는 방법.
$tcpctl start listen=30 timeout=30 forkon listen=<queue size>이며, 청취자 열의
크기를 지정.
timeout=<seconds>이며, 지정된 시간에 orasrv와의 응답 확인 시간을 나타냄.
forkon SQL*net이 orasrv process에 접근하는 방법을 나타냄.
System에 따라서 forkon option이 적용 않되는 경우도 있음.
2.Client에서 접속을 하여 사용 다가 비정상 종료(Session이 맺어진 상태에서 Client의
Power Off)를 하여 Server에 Processor가 남아 있고, orasrv를 통해 접속할 수 있는
Session의 수가 점점 줄어들 경우가 있는 데 이러한 경우에는 orasrv를(tcpctl stop or
UNIX kill command를 이용)강제로 종료 시고 다음과 같이 Start 시켜 주십시오.

#nohup tcpctl start ( Client의 비정상 종료가 Orasrv에는 영향을 미치지 않음)
또는
#orasrv (ORACLE_HOME\bin directory에서 직접 orasrv processor를 띄운다)
-----
현상 : ORA-06502 : PL/SQL : 값(수치) 오류입니다.
원인 : DB Column과 Host variableㅇ의 길이가 맞지 않은 경우.
조치 : DB Column과 Host variableㅇ의 길이를 확인하고 길이를 동일하게 한다.
-----
현상 : ORA-06533: Subscript beyond count
원인 : VARRAY는 default 로 3개의 element 이상을 가져 올수 없기 때문.
조치 : EXTEND method를 이용하여 해결할 수 있다.
-----
현상 : ORA-06571
원인 : SQL문 안에서 Stored function을 call하여 사용하는 경우 발생.
조치 : 기본적으로 stored function이나 procedure, package에서의
DML 문장의 사용은 보장이 되는 기능이나, sql list에서의 stored function의
사용은 몇 가지 제약 조건을 가지고 수행이 가능합니다.
-----
현상 : ORA-1119: error in creating database file
ORA-7515: sfccf UIC GROUP <= MAXSYSGROUP - file operations not allowed
원인 : VMS에서만 발생하는 에러로 DATAFILE을 생성하려는 Directory의 Owner가 DBA user가 아닐때 발생.
조치 : Datafile을 생성하려는 Directory의 Owner를 Oracle DBA user로 변경시켜 주어야 한다.
-----
현상 : ORA-9241, ORA-9301
원인 : 개발툴이 해당 툴 또는 SQL*NET에 필요한 메세지 화일을 찾을 수 없을 때 발생
조치 : ORACLE.INI 파일에 LOCAL = <V2 service name>을 추가한다. 만일 ORACLE.INI 파일에 LOCAL
파라미터를 추가한 후에도 계속 ora-9301 에러가 계속 발생한다면 autoexec.bat 파일에 SET
CONFIG = <PATH> \ORACLE.INI를 추가한다.
[주의 1]CONFIG가 ORACLE.INI를 지시하도록 설정하면 나중에 다시 설치할 문제가 발생할 수
있다. 그럴 때는 AUTOEXEC.BAT 에서 SET CONFIG 행을 삭제하고 다시 Booting 한후
설치를 시작한다.
[주의 2]MS ACCESS를 이용하여 ORACLE의 데이타를 질의할 경우는 환경변수를 다음과 같이
설정한다.
SET CONFIG_FILES = <path> \ORACLE.INI
[주의 3]SET 다음의 CONFIG 나 CONFIG_FILES 은 반드시 대문자 이어야 한다.
-----
현상 : ORA-9352
원인 : nt 에서 service 의 problem 발생.
조치 : 1.background services and processes 를 띄우기
dos>oradim80 -startup -sid SID -starttype srvc,inst -usrpwd password -pfile filename
2.여러 개의 instance 를 띄우고자 하는 경우
- ORACLE_SID 를 setting 한다.
c:\> set oracle_sid =sid
- server manager 실행
c:\>svrmgr30
svrmgr>connect internal/passwd
-----
현상 : ORA-12004/ORA-12034
원인 : master table의 snapshot log가 있는 table에 대해서, snapshot이 추가로
생성되고 나면 snapshot을 생성하기 시작한 시간과, 기존의 snapshot이 log를
refresh해간 시간을 비교하여 새로운 snapshot 생성시작 시간이 더 빠르면
ora-12004가 발생
조치 : 생성하고자 하는 snapshot에 대한 master table의 다른 snapshot들을 refresh하지 못하도록 하거나, refresh하지 않는 시간에 새로운 snapshot을 생성하여야 한다.
refresh 못하도록 막는 방법으로는 일시적으로 snapshot job을 broken시킨 후 snapshot이 생성된 후 다시 broken을 false로 하면 된다.
-----
현상 : ORA-12154
원인 : tnsnames.ora 파일의 Alias처럼 정의된 Connect String으로 사용하는 db_alias를 찾지 못할 경우 발생
-----
현상 : TNS-12203 "TNS:unable to connect to destination"
원인 : 1.WINDOWS용 TCP/IP 어댑터를 설치하지 않은 상태에서 연결하려 할
2.TNS-12203 에러는 WINDOWS용 ORACLE SQL*NET소프트웨어가 ORACLE 홈 디 렉토리를 찾을 수
없다는 의미일 수 있습니다.
3.TNSNAMES.ORA가 ORACLE 홈 디렉토리 아래의 NETWORK\ADMIN에 있는지 확인하십시요.
4.서버쪽에서 실행중인 SQL*NET V2 TCP/IP Listener가 없어도 TNS-12203이 발생
5.연결할 SERVICES 이름에 대해 CONNECT DESCRIPTOR에 정확한 ADDRESS 매개변수를 지정했는지
확인하십시요.
6.JSB VSL 소켓이 초기화되지 않으면 TNS-12203 이 발생할 수 있습니다.
7.TNS-12203에 이어 실제 문제가 무엇인지 더 자세하게 나타내 주는 또 다른 에러가 발생할 수
있습니다.
조치 : 1.SQL*NET TCP/IP V2는 SQL*NET V2와 V2 TCP/IP 어댑터 등 두가지 제품으로 구성됩니다.
이들은 별도의 두 키트로 되어 있는데, 반드시 두 키트를 모두 설치해야 합니다.
2.WIN.INI파일의 ORACLE 부분에 다음 항목이 있는지 확인하십시요.
[ORACLE]
ORA_CONFIG=C:\WINDOWS\ORACLE.INI
WINDOWS디렉토리가 C:\WINDOWS가 아니면, 위 행의 C:\WINDOWS 부분을 그 이름으로 바꾸십시요
그런 다음, ORACLE 소프트웨어를 다시 설치하십시요. ORACLE.INI 파일이 있으면 ORACLE.INI
파일에 다음 행이 있는지 확인하십시요.
ORACLE_HOME=C:\ORAWIN
ORACLE 홈 디렉토리가 C:\ORAWIN이 아니면 위 행의 C:\ORAWIN 부분을 이름으로 바꾸십시요.
3.ORACLE 홈 디렉토리는 ORACLE.INI(또는 WIN.INI의 ORA_CONFIG매개변수가 지시하는 파일)의
ORACLE_HOME 에 의해 정의됩니다.
4.서버쪽에서 실행중인 SQL*NET V2가 있는지 확인하십시요. 서버쪽에서 Listener Control 유틸
리티(LSNRCTL)를 사용하면 서버의 V2 Listener가 실행중인지 확인할 수 있습니다. 서버에서
"LSNRCTL STATUS"명령을 실행하십시요. Listener Control이 유틸리티 대해서는 SQL*NET
Administrator's Guide를 참조하십시요.
5.정확한 ADDRESS 매개변수를 사용중인지 확인하는 방법은, WINDOWS 클라이언트에서 사용 할 것
과 같은 ADDRESS 매개 변수를 가진 TNSNAMES.ORA를 사용하여 서버에서 루프백을 해 보는 것
입니다. 루프백을 수행한다는 것은 데이타베이스와 같은 기계에서 SQL*DBA 등을 호출하고
연결 스트링을 지정함으로써 SQL*NET V2를 통해 연결한다는 뜻입니다.
6.문제를 해결하려면 다음 사항을 점검하여 JSB VSL 레이어가 정확하게 초기화되었는지 확인
하십시요.
1)ORACLE.INI 파일(또는 WIN.INI의 ORA_CONFIG 매개변수가 지시하는 파일)의 업체키 매개
변수 TCP_VENDOR가 정확하게 설정되었는 지 확인하십시요
2)ORACLE_HOME\BIN 디렉토리에 MSOCKLIB.DLL이 있는지 확인하십시요.
3)ORACLE_HOME\BIN 디렉토리에 선택된 JSB 업체 특유의 DLL이 있는지, 또는그 JSB 업체 특유
의 TSR 파일이 실행되는 지 확인하십시요.
4)WINDOWS 홈 디렉토리에 VSL.INI 파일이 있는 지 확인하십시요.
7.화면에서 다른 에러가 보이지 않으면 ORACLE_HOME\NETWORK\LOG 디렉토리의 SQLNET.LOG 파일을
점검하십시요.
-----
현상 : TNS-12533

Posted by 1010
02.Oracle2009. 6. 4. 18:24
반응형

Keep pool로 바꾸는 방법

 SQL> show parameter keep

NAME                                    TYPE        VALUE
-----------------------------------------------------
buffer_pool_keep                     string
control_file_record_keep_time   integer          7
db_keep_cache_size               big integer     0
SQL> alter system set db_keep_cache_size=4M          <--- 에러가 날 경우

System altered.

SQL> show parameter keep

NAME                                    TYPE           VALUE
--------------------------------------------------------
buffer_pool_keep                     string
control_file_record_keep_time   integer           7
db_keep_cache_size               big integer     4M
<에러 해결>

SQL> show parameter sga_target

NAME                                 TYPE           VALUE
------------------------------------------------------
sga_target                           big integer    272M
SQL> show parameter sga_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
sga_target                           big integer 272M
SQL> alter system set db_keep_cache_size=4M scope=both


용량 확인

SQL> show parameter size

NAME                                 TYPE        VALUE
--------------------------------------------------------
bitmap_merge_area_size            integer     1048576
create_bitmap_area_size            integer     8388608
db_16k_cache_size                    big integer 0
db_2k_cache_size                      big integer 0
db_32k_cache_size                    big integer 0
db_4k_cache_size                      big integer 0
db_8k_cache_size                      big integer 0
db_block_size                            integer     8192
db_cache_size                           big integer 0
db_keep_cache_size                   big integer 4M
db_recovery_file_dest_size           big integer 2G

db_recycle_cache_size                big integer 0
global_context_pool_size              String
hash_area_size                           integer     131072
java_max_sessionspace_size       integer     0
java_pool_size                            big integer 0
large_pool_size                           big integer 0
max_dump_file_size                    string      UNLIMITED
object_cache_max_size_percent   integer     10
object_cache_optimal_size           integer     102400
olap_page_pool_size                   big integer 0
parallel_execution_message_size integer     2148

sga_max_size                             big integer 272M
shared_pool_reserved_size           big integer 4613734
shared_pool_size                         big integer 0
sort_area_retained_size                 integer     0
sort_area_size                             integer     65536
streams_pool_size                       big integer 0
workarea_size_policy                   string      AUTO

redolog 버퍼용량 확인

SQL> show parameter log


ASMM Disable 만드는 질의

SQL> alter system set sga_target=0 scope=both

SQL> alter system set java_pool_size=0 scope=both

SQL> alter system set large_pool_size=0 scope=both
SQL> alter system set shared_pool_size=0 scope=both

SQL> alter system set stream_pool_size=0 scope=both


버퍼사이즈 계산

SQL> select pool,sum(bytes)/1024/1024 from v$sgastat group by pool;

POOL         SUM(BYTES)/1024/1024
----------------------------------
                           175.998459      <===기타 keep(4M), sga 와 상관없는거 다빼면 버퍼사이즈
java pool                       4
shared pool            84.0056801
large pool                      4


SQL> show parameter sga_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
sga_target                           big integer 272M
SQL> select name,value from v$parameter where name like '%size'

NAME                                          VALUE
-------------------------------------------------------------------------------
sga_max_size                              285212672

shared_pool_size                          92274688

large_pool_size                              4194304

java_pool_size                                 4194304

streams_pool_size                                 0

shared_pool_reserved_size                  4613734

java_max_sessionspace_size                  0

db_block_size                                          8192

db_cache_size                                    176160768

db_2k_cache_size                                       0

db_4k_cache_size                                 0

db_8k_cache_size                                 0

db_16k_cache_size                                 0

db_32k_cache_size                                 0

db_keep_cache_size                           4194304

db_recycle_cache_size                              0

db_recovery_file_dest_size                  2147483648

global_context_pool_size

 create_bitmap_area_size                     8388608

bitmap_merge_area_size                     1048576

parallel_execution_message_size               2148

hash_area_size                                 131072

max_dump_file_size                        UNLIMITED

object_cache_optimal_size                  102400

sort_area_size                                     65536

sort_area_retained_size                           0

olap_page_pool_size                                0


9장 자동화된 툴


Dictionary Views

SQL> select table_name, num_rows from dba_tables where owner='SCOTT'

TABLE_NAME                       NUM_ROWS
--------------------------------------------
DEPT
EMP
BONUS
SALGRADE

EM-Admin-Advisor central

SQL> select view_name from dba_views where view_name like '%ADVICE'
VIEW_NAME
------------------------------
V_$PGA_TARGET_ADVICE
V_$MTTR_TARGET_ADVICE
V_$PX_BUFFER_ADVICE
V_$DB_CACHE_ADVICE
V_$SGA_TARGET_ADVICE
V_$SHARED_POOL_ADVICE
V_$JAVA_POOL_ADVICE
V_$STREAMS_POOL_ADVICE
GV_$PGA_TARGET_ADVICE
GV_$MTTR_TARGET_ADVICE
GV_$PX_BUFFER_ADVICE

GV_$DB_CACHE_ADVICE
GV_$SGA_TARGET_ADVICE
GV_$SHARED_POOL_ADVICE
GV_$JAVA_POOL_ADVICE
GV_$STREAMS_POOL_ADVICE
DBA_HIST_DB_CACHE_ADVICE
DBA_HIST_SHARED_POOL_ADVICE
DBA_HIST_STREAMS_POOL_ADVICE
DBA_HIST_PGA_TARGET_ADVICE
DBA_HIST_SGA_TARGET_ADVICE
DBA_HIST_JAVA_POOL_ADVICE

DBA_HIST_MTTR_TARGET_ADVICE

23 rows selected.


Asynchronius와  synchronius 장단점 비교

 Commit 장점 단점
 Asynchronius  속도가 빠름  신뢰도 떨어짐(data lose의 가능성), 배치잡할때
 synchronius  안정성이 높음  Transaction 많을때 느려짐, 일반 사용

Posted by 1010