RSS feed
<< 2007년 10월 29일 (월) | Home | 2007년 10월 31일 (수) >>

Jakarta Slide 프로젝트를 이용해 Microsoft Sharepoint Server 연동 문제해결 하기 (

Jakarta Slide 프로젝트를 이용해 Microsoft Sharepoint Server (MOSS or WSS) 연동 문제해결 하기 (NTLM 문제등 ) - v0.4 by Ko,jinhyuk

WebDAV 가 나름 표준이기는 해도 늘 그렇듯 밴더마다 조금식 동작하는게 다르다 보니 이러저런 문제가 생기게 마련이다.

이중에 Java 쪽에 많지 않은 솔루션쪽에 널리알려진게 Jakarta의 Slide WebDAV 프로젝트인데 (2004년 마지막 릴리즈 이후 변화없음)
Slide는 Subversion 에 WebDAV를 얹어서는 잘되던게 MOSS (Microsoft Office Sharepoint Server )에서는 문제가 되는사항들이 좀 있었다. 관련해서 문제가 되었던것과 해결했던것들을
정리해보려고 한다.

이하에서 webdavResource 변수는 org.apache.webdav.lib.WebdavResource 의 인스턴스 이다.


1) isCollection() 의 문제
특정 경로(url)이 directory 인지 여부를 판단할때 사용하게 되는데 문제는 MOSS에서는 파일인 경우에도 isCollection()를 true 로 리턴해버리는 바람에 디렉토리 구별을 할때 문제가 되었다. 이에 대한 대안으로 webdavResource.getSupportedLock() 을 이용해서 결과가 "Exclusive write lock"를 리턴하는 경우에는 파일이므로 (디렉토리에 lock를 걸수는 없으므로) 이를 이용하는 방법이 있었다.
그래서
boolean isFile =!(webdavResource.isCollection() && webdavResource.getSupportedLock().length()<1);

와 같이 할 수 있다.

2) NTLM (NT 도메인 인증 방식)연결을 하려면
일단 최신의 HttpClient 라이브러리 버전을 사용하면 되는데 (Jakarta common library에 있다. ) 여기에 NTLM 관련 scheme 및 NTCredentials 이 포함되어있다.
library 의 jar 경로에 commons-httpclient-3.1.jar 와 같은 최신버전 잡아주고 (아마 commons-codec-1.3.jar,commons-httpclient-contrib.jar 도 필요 할것이다.. 기억이 가물해서).

다음처럼 소스에서 작업을 해주면 된다.

NTCredentials creds = new NTCredentials(userId, password,httpURL.getHost(),NTdomain );
HostConfiguration hostConfig = new HostConfiguration();
hostConfig.setHost(httpURL.getHost());
HttpURL host = new HttpURL(repositoryUrl);
host.setUserinfo(userId,password);
webdavResource = new WebdavResource(host, (Credentials)creds, WebdavResource.DEFAULT, DepthSupport.DEPTH_1);


3) putMethod 의 문제해결
Slide 의 문제인데. NTLM 을 이용한 사용자 인증을 하게 되는 경우 putMethod시 default Auth Scheme 로 Basic 을 사용하다보니 인증실패나고 다시 시도 할때

================================= 에러 스택 =====================================================
org.apache.commons.httpclient.ProtocolException: Unbuffered entity enclosing request can not be repeated.
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:487)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
... 이하 생략
===============================================================================================
위 에러가 발생한다. 이는 put 재시도 를 하면서 발생하는 문제인데 근본적으로 인증실패난 상태에서 put을 날리기 때문이다. slide 의 버그라고 봐야. 기본적으로 connect 하는 과정에서 이미 인증이 되었는데 이때 사용한 auth scheme 를 이용하지 않고 putMethod에서 다시 인증 방식을 새로이 (Basic)하면서 생긴문제다. 여러가지 해결 방안이있겠지만

org.apache.commons.httpclient.auth.AuthState 가 default auth scheme 로 내부변수 PREEMPTIVE_AUTH_SCHEME 에 basic를 박아놓아서... 항상 basic 이 기본이 되는걸...
특정 scheme 가 default로 되도록 고쳐서 적용하려고 한다. 방법은 여러가지가 있겠으나 환경변수로서 NTLM 이나 basic등을 지정하게 하는방법도 있을듯한데

우선 테스트삼아..

/**
* Preemptively assigns Basic authentication scheme.
*/
public void setPreemptive() {
if (!this.preemptive) {
if (this.authScheme != null) {
throw new IllegalStateException("Authentication state already initialized");
}
// this.authScheme = AuthPolicy.getAuthScheme(PREEMPTIVE_AUTH_SCHEME);
this.authScheme = AuthPolicy.getAuthScheme("NTLM");
this.preemptive = true;
}
}

위에// 처리한게 원래 이고 아래줄에 this.authScheme = AuthPolicy.getAuthScheme("NTLM"); 는 일단 동작여부확인을 위해 박아넣은것인데... 예상대로 전송이 안되던게 바로 해결이되었다.



3) getIsHidden() 의 문제해결 - 2007.12.13일 추가

MS WSS 의 경우 DAV Resource(디렉토리나 파일)의 Property 전달과정에서 표준을 지키지 않는 문제가 있다... 뭐 나름 속사정이 있겠지만 . 적어도 표준을 포함하면서 확장하면 모르겠는데 Hidden 디렉토리나 파일에 대한 속석을 slide의 getIsCollection()으로 구하는 경우 false 로 떨어지는 문제가있다. 이것은
보통 Response XML에서 0 를 이용하여 속성값을 구하는데 반해 MS의 그것은 Hidden 속성이있는 경우 00000002 처럼 임의 확장 Property 를 추가하고 비트 mask 정보를 이용하여 얻을수있도록하는 (전통적인 MS 방식)것으로 값을 전달하고 있었다. 그래서 이것을 얻어내서 내부적으로 16진수 변환하여 숫자 '2'값과 AND 비트연산을 해봐야 하는것이다.

다음과같이 처리를 했다.

============ 소스 - 1) WebDavResource.java ================
public static final String WIN32_ATTRIBUTES="Win32FileAttributes";
......
......
protected void processProperty(Property property) {
... 중략 ...

// MS WSS (Win32 WebDAV) 서버인경우 처리를 위하여
else if (property.getLocalName().equals(WIN32_ATTRIBUTES)){

if(_logger.isDebugEnabled()){
_logger.debug("set property about Win32 Attributes");

}
/**
* 1: ReadyOnly, 2:Hidden
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfile.asp
* http://www.nlog-project.org/help/NLog.Internal.Win32.Win32FileAttributes.html
*
* MS의 WSS인경우에는 isHidden 대신 WIN32_ATTRIBUTES 로 속성을 전달하는경우가 있으므로
*
* HEX 값으로 변형하여 2 값이 set되어있는 경우
*/

if((Integer.parseInt(property.getPropertyAsString(),16) & 2)==2){
this.setIsHidden(true);
}
}

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