/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.fujitsu.dc.client; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import org.apache.http.HttpStatus; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.fujitsu.dc.client.http.CacheEntry; import com.fujitsu.dc.client.http.CacheMap; import com.fujitsu.dc.client.http.DcResponse; import com.fujitsu.dc.client.http.IRestAdapter; import com.fujitsu.dc.client.http.RestAdapter; import com.fujitsu.dc.client.http.RestAdapterFactory; import com.fujitsu.dc.client.utils.UrlUtils; ///** // * DAVコレクションへアクセスするクラス. // */ /** * It creates a new object of DavCollection. This class is used to access the DAV collection for performing Odata * operations. */ public class DavCollection extends DcCollection { private static final int REDIRECTION_CODE = 300; // CHECKSTYLE:OFF // /** boxレベルACLへアクセスするためのクラス. */ /** Reference variable to access the box level ACL. */ public AclManager acl; // CHECKSTYLE:ON // /** // * コンストラクタ. // */ /** * This is the default constructor and calls its parent constructor internally. */ public DavCollection() { super(); } // /** // * コンストラクタ. // * @param as アクセス主体 // * @param pathValue これまでのパス // */ /** * This is the parameterized constructor with two parameters. It calls its parent constructor internally. * @param as Accessor * @param pathValue Path */ public DavCollection(Accessor as, String pathValue) { super(as, pathValue); this.acl = new AclManager(accessor, this); } // /** // * コレクションの生成. // * @param name 生成するCollection名 // * @throws DaoException DAO例外 // */ /** * This method creates a Collection. * @param name CollectionName * @throws DaoException Exception thrown */ public void mkCol(String name) throws DaoException { RestAdapter rest = (RestAdapter) RestAdapterFactory.create(this.accessor); rest.mkcol(UrlUtils.append(this.getPath(), name)); } // /** // * ODataコレクションの生成. // * @param name 生成するODataCollection名 // * @throws DaoException DAO例外 // */ /** * This method creates a OData Collection. * @param name ODataCollectionName * @throws DaoException Exception thrown */ public void mkOData(String name) throws DaoException { RestAdapter rest = (RestAdapter) RestAdapterFactory.create(this.accessor); rest.mkOData(UrlUtils.append(this.getPath(), name)); } // /** // * Serviceコレクションの生成. // * @param name 生成するServiceCollection名 // * @throws DaoException DAO例外 // */ /** * This method creates a Service Collection. * @param name ServiceCollectionName * @throws DaoException Exception thrown */ public void mkService(String name) throws DaoException { RestAdapter rest = (RestAdapter) RestAdapterFactory.create(this.accessor); rest.mkService(UrlUtils.append(this.getPath(), name)); } // /** // * Calendarコレクションの生成. // * @param name 生成するCalendarCollectoin名 // * @throws DaoException DAO例外 // */ /** * This method creates a Calendar Collection. * @param name CalendarCollectoinName * @throws DaoException Exception thrown */ public void mkCalendar(String name) throws DaoException { RestAdapter rest = (RestAdapter) RestAdapterFactory.create(this.accessor); rest.mkCalendar(UrlUtils.append(this.getPath(), name)); } // /** // * コレクション内のリソースの一覧を取得する. // * @return リソースの一覧 // * @throws DaoException DAO例外 // */ /** * This method gets the list of resources in the collection by calling getResourceList method internally. * @return List of resources * @throws DaoException Exception thrown */ public String[] getFileList() throws DaoException { return getResourceList(false); } // /** // * コレクション内のサブコレクションの一覧を取得する. // * @return サブコレクションの一覧 // * @throws DaoException DAO例外 // */ /** * This method gets the list of sub-collection in the collection by calling getResourceList method internally. * @return List of sub-collection * @throws DaoException Exception thrown */ public String[] getColList() throws DaoException { return getResourceList(true); } /** * This method fetches the list of resource for the box/collection as specified in the path URL. * @param folder value * @return List of resources * @throws DaoException Exception thrown */ private String[] getResourceList(boolean folder) throws DaoException { ArrayList<String> folderList = new ArrayList<String>(); ArrayList<String> fileList = new ArrayList<String>(); RestAdapter rest = (RestAdapter) RestAdapterFactory.create(this.accessor); DcResponse res = rest.propfind(this.url.toString()); Document doc = res.bodyAsXml(); NodeList nl = doc.getElementsByTagName("response"); String name; for (int i = 1; i < nl.getLength(); i++) { Element elm = (Element) nl.item(i); Node href = elm.getElementsByTagName("href").item(0); name = href.getFirstChild().getNodeValue(); NodeList col = elm.getElementsByTagName("collection"); if (col.getLength() > 0) { folderList.add(name); } else { fileList.add(name); } } if (folder) { return folderList.toArray(new String[0]); } else { return fileList.toArray(new String[0]); } } // /** // * コレクションにプロパティをセットする. // * @param key プロパティ名 // * @param value プロパティの値 // */ /** * This method sets the property in a collection. * @param key Key value * @param value Value */ public void setProp(String key, String value) { } // /** // * コレクションからプロパティを取得する. // * @param key プロパティ名 // * @return 取得したプロパティ値 // */ /** * This method gets the property from a collection based on specified key. * @param key Key value * @return Value Empty string */ public String getProp(String key) { return ""; } // /** // * サブコレクションを指定. // * @param name コレクション名 // * @return 指定したコレクション名のDavCollectionオブジェクト // */ /** * This method specifies the sub-collection. * @param name Collection Name * @return DavCollection object */ public DavCollection col(String name) { return new DavCollection(this.accessor, UrlUtils.append(this.getPath(), name)); } // /** // * ODataコレクションを指定. // * @param name ODataコレクション名 // * @return 取得したODataCollectionオブジェクト // */ /** * This method specifies the odata collection. * @param name ODataCollection Name * @return ODataCollection object */ public ODataCollection odata(String name) { return new ODataCollection(this.accessor, UrlUtils.append(this.getPath(), name)); } // /** // * Serviceコレクションを指定. // * @param name Serviceコレクション名 // * @return 取得したSerivceコレクションオブジェクト // */ /** * This method specifies the service collection. * @param name ServiceCollection Name * @return SerivceCollection object */ public ServiceCollection service(String name) { return new ServiceCollection(this.accessor, UrlUtils.append(this.getPath(), name)); } // /** // * DAVに対するGETメソッドをリクエストする. // * @param pathValue 取得するパス // * @return GETした文字列 // * @throws DaoException DAO例外 // */ /** * This method requests the GET method for the DAV by calling its overloaded version. * @param pathValue Path * @return GET Response in string form * @throws DaoException Exception thrown */ public String getString(String pathValue) throws DaoException { return this.getString(pathValue, "utf-8"); } // /** // * DAVに対するGETメソッドをリクエストする. // * @param pathValue 取得するパス // * @param charset 文字コード // * @return GETした文字列 // * @throws DaoException DAO例外 // */ /** * This method requests the GET method for the DAV and returns in string format. * @param pathValue Path * @param charset Character Code * @return GET Response in string form * @throws DaoException Exception thrown */ public String getString(String pathValue, String charset) throws DaoException { WebDAV webDAV = getStringWebDAV(pathValue, charset); return webDAV.getStringBody(); } // /** // * DAVに対するGETメソッドをリクエストする. // * @param pathValue 取得するパス // * @return GETしたストリーム // * @throws DaoException DAO例外 // */ /** * This method requests the GET method for the DAV and returns in stream format. * @param pathValue Path * @return GET Response as Stream * @throws DaoException Exception thrown */ public InputStream getStream(String pathValue) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); // リクエスト /** Request. */ DcResponse res = RestAdapterFactory.create(this.accessor).get(url, "application/octet-stream"); // レスポンスボディをストリームとして返却 /** Return stream as the response body. */ return res.bodyAsStream(); } // /** // * DAVに対するGETメソッドをリクエストする. // * @param pathValue 取得するパス // * @return WebDAV GETした文字列を含むWebDAVオブジェクト // * @throws DaoException DAO例外 // */ /** * This method requests the GET method for the DAV by calling its overloaded version. * @param pathValue Path * @return WebDAV GET WebDAV object that contains a string * @throws DaoException Exception thrown */ public WebDAV getStringWebDAV(String pathValue) throws DaoException { return this.getStringWebDAV(pathValue, "utf-8"); } // /** // * DAVに対するGETメソッドをリクエストする. // * @param pathValue 取得するパス // * @param charset 文字コード // * @return WebDAV GETした文字列を含むWebDAVオブジェクト // * @throws DaoException DAO例外 // */ /** * This method requests the GET method for the DAV and retruns in WebDAV object. * @param pathValue Path * @param charset Character Code * @return WebDAV GET WebDAV object that contains a string * @throws DaoException Exception thrown */ public WebDAV getStringWebDAV(String pathValue, String charset) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); // まずはキャッシュから検索する /** First search from cache. */ CacheMap cm = this.accessor.getContext().getCacheMap(); CacheEntry ce = cm.search(url); IRestAdapter rest = RestAdapterFactory.create(this.accessor); DcResponse res; try { if (ce == null) { // キャッシュになければ新規取得 /** If not found in cache, then acquire. */ res = rest.get(url, "text/plain"); } else { // キャッシュにあれば、IF_NONE_MATCHにETag指定 /** If you are on the cache and ETag specified in IF_NONE_MATCH. */ res = rest.get(url, "text/plain", ce.getEtag()); } } catch (DaoException e) { // 304 NOT_MODIFIEDの場合は、キャッシュの値を返却する /** In the case of 304 NOT_MODIFIED, to return the value of the cache. */ if (Integer.parseInt(e.getCode()) == HttpStatus.SC_NOT_MODIFIED && ce != null) { WebDAV webDAVCache = new WebDAV(); webDAVCache.setStringBody(ce.getBody()); webDAVCache.setResHeaders(ce.getHeaders()); webDAVCache.setStatusCode(HttpStatus.SC_NOT_MODIFIED); return webDAVCache; } throw e; } // レスポンスボディを取得 /** Get the response body. */ String body = res.bodyAsString(charset); WebDAV webDAV = new WebDAV(); webDAV.setStringBody(body); webDAV.setResHeaders(res.getHeaderList()); webDAV.setStatusCode(res.getStatusCode()); if (ce == null) { // キャッシュになければ新規にキャッシュに保存 /** Save the new one to cache. */ cm.appendEntry(new CacheEntry(url, res.getHeaderList(), body)); } else { // キャッシュにあれば、キャッシュ情報を更新 /** If was present on the cache, then update its new value. */ ce.setHeaders(res.getHeaderList()); ce.setBody(body); } return webDAV; } // /** // * DAVに対するGETメソッドをリクエストする<br> // * ETag値がnull以外の場合は、If-None-Matchヘッダを付加する. // * @param pathValue 取得するパス // * @param eTag ETag値 // * @param charset 文字コード // * @return WebDAV GETした文字列を含むWebDAVオブジェクト<br> // * 更新なしの場合はnullを返却する // * @throws DaoException DAO例外 // */ /** * DAVに対するGETメソッドをリクエストする<br> * ETag値がnull以外の場合は、If-None-Matchヘッダを付加する. * @param pathValue 取得するパス * @param eTag ETag値 * @param charset 文字コード * @return WebDAV GETした文字列を含むWebDAVオブジェクト<br> * 更新なしの場合はnullを返却する * @throws DaoException DAO例外 */ /** * This method is used to request the GET method for DAV. If the ETag value is non-null, add an If-None-Match * header. * @param pathValue Path * @param eTag ETag value * @param charset character code * @return WebDAV objects that contain the string If no update, then return null. * @throws DaoException DAO exception */ public WebDAV getStringWebDAV(String pathValue, String eTag, String charset) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); DcResponse res = null; int statusCode = 0; try { res = RestAdapterFactory.create(this.accessor).get(url, "text/plain", eTag); statusCode = res.getStatusCode(); } catch (DaoException e) { // TODO 300系をエラーとして処理することの可否は検討が必要 /** TODO Propriety of treating it as an error 300 system needs to be considered. */ if (Integer.parseInt(e.getCode()) != HttpStatus.SC_NOT_MODIFIED) { throw e; } else { statusCode = Integer.parseInt(e.getCode()); } } WebDAV webDAV = new WebDAV(); webDAV.setStatusCode(statusCode); if (statusCode < REDIRECTION_CODE) { webDAV.setResHeaders(res.getHeaderList()); // レスポンスボディを取得 /** Get the response body. */ webDAV.setStringBody(res.bodyAsString(charset)); } return webDAV; } // /** // * DAVに対するGETメソッドをリクエストする. // * @param pathValue 取得するパス // * @return WebDAV GETしたストリームを含むWebDAVオブジェクト // * @throws DaoException DAO例外 // */ /** * This method requests the GET method for the DAV. * @param pathValue Path * @return WebDAV object that contains the stream * @throws DaoException Exception thrown */ public WebDAV getStreamWebDAV(String pathValue) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); DcResponse res = RestAdapterFactory.create(this.accessor).get(url, "application/octet-stream"); // レスポンスボディのストリームを持つWebDAVを返却 /** Return WebDAV with a stream of the response body. */ WebDAV webDAV = new WebDAV(); webDAV.setStreamBody(res.bodyAsStream()); webDAV.setResHeaders(res.getHeaderList()); webDAV.setStatusCode(res.getStatusCode()); return webDAV; } // /** // * DAVに対するGETメソッドをリクエストする<br> // * ETag値がnull以外の場合は、If-None-Matchヘッダを付加する. // * @param pathValue 取得するパス // * @param eTag ETag値 // * @return WebDAV GETしたストリームを含むWebDAVオブジェクト<br> // * 更新なしの場合はnullを返却する // * @throws DaoException DAO例外 // */ /** * This method requests the GET method for the DAV. If the ETag value is non-null, add an If-None-Match header. * @param pathValue Path * @param eTag ETag Value * @return WebDAV object that contains the stream If no update, then return null. * @throws DaoException Exception thrown */ public WebDAV getStreamWebDAV(String pathValue, String eTag) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); DcResponse res = null; int statusCode = 0; try { res = RestAdapterFactory.create(this.accessor).get(url, "application/octet-stream", eTag); statusCode = res.getStatusCode(); } catch (DaoException e) { // TODO 300系をエラーとして処理することの可否は検討が必要 /** TODO Propriety of treating it as an error 300 system needs to be considered. */ if (Integer.parseInt(e.getCode()) != HttpStatus.SC_NOT_MODIFIED) { throw e; } else { statusCode = Integer.parseInt(e.getCode()); } } WebDAV webDAV = new WebDAV(); webDAV.setStatusCode(statusCode); if (statusCode < REDIRECTION_CODE) { webDAV.setResHeaders(res.getHeaderList()); // レスポンスボディを取得 /** Get the response body. */ webDAV.setStreamBody(res.bodyAsStream()); } return webDAV; } // /** // * 指定pathに任意のInputStreamの内容をPUTします. 指定IDのオブジェクトが既に存在すればそれを書き換え、存在しない場合はあらたに作成する. // * @param pathValue DAVのパス // * @param contentType メディアタイプ // * @param enc 文字コード(使用しない) // * @param is InputStream // * @param etag ETag値 // * @return WebDAV WebDAVオブジェクト // * @throws DaoException DAO例外 // */ /** * The purpose of this method is to PUT the contents of the InputStream of any specified path. If ID already exists, * it rewrites the specified object , else creates a new one if it does not exist. * @param pathValue DAV path * @param contentType Media Type * @param enc character code (not used) * @param is InputStream * @param etag ETag Value * @return WebDAV WebDAV object * @throws DaoException Exception thrown */ public WebDAV put(String pathValue, String contentType, String enc, InputStream is, String etag) throws DaoException { // ストリームの場合はエンコーディング指定は使用しない /** Do not use the encoding specified in the case of stream. */ return put(pathValue, contentType, is, etag); } // /** // * 指定pathに任意のInputStreamの内容をPUTします. 指定IDのオブジェクトが既に存在すればそれを書き換え、存在しない場合はあらたに作成する. // * @param pathValue DAVのパス // * @param contentType メディアタイプ // * @param is InputStream // * @param etagValue ETag値 // * @return WebDAV WebDAVオブジェクト // * @throws DaoException DAO例外 // */ /** * The purpose of this method is to PUT the contents of the InputStream of any specified path. If ID already exists, * it rewrites the specified object , else creates a new one if it does not exist. * @param pathValue DAV Path * @param contentType Media Type * @param is InputStream * @param etagValue ETag value * @return WebDAV WebDAV object * @throws DaoException Exception thrown */ public WebDAV put(String pathValue, String contentType, InputStream is, String etagValue) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); DcResponse res = ((RestAdapter) RestAdapterFactory.create(this.accessor)).putStream(url, contentType, is, etagValue); WebDAV webDAV = new WebDAV(); webDAV.setResHeaders(res.getHeaderList()); webDAV.setStatusCode(res.getStatusCode()); return webDAV; } // /** // * 指定Pathに任意の文字列データをPUTします. // * @param pathValue DAVのパス // * @param contentType メディアタイプ // * @param data PUTするデータ // * @param etagValue PUT対象のETag。新規または強制更新の場合は "*" を指定する // * @return WebDAV WebDAVオブジェクト // * @throws DaoException DAO例外 // */ /** * The purpose of this method is to PUT a string of data to any specified Path. * @param pathValue DAV Path * @param contentType Media Type * @param data PUT data * @param etagValue Etag, specify "*" for forcing new or updated * @return WebDAV WebDAV object * @throws DaoException Exception thrown */ public WebDAV put(String pathValue, String contentType, String data, String etagValue) throws DaoException { byte[] bs; try { bs = data.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new DaoException("UnsupportedEncodingException", e); } InputStream is = new ByteArrayInputStream(bs); String url = UrlUtils.append(this.getPath(), pathValue); DcResponse res = ((RestAdapter) RestAdapterFactory.create(this.accessor)).putStream(url, contentType, is, etagValue); WebDAV webDAV = new WebDAV(); webDAV.setResHeaders(res.getHeaderList()); webDAV.setStatusCode(res.getStatusCode()); return webDAV; } // /** // * 指定Pathに任意の文字列データをPUTします. // * @param pathValue DAVのパス // * @param contentType メディアタイプ // * @param enc 文字コード // * @param data PUTするデータ // * @param etag PUT対象のETag。新規または強制更新の場合は "*" を指定する // * @return WebDAV WebDAVオブジェクト // * @throws DaoException DAO例外 // */ /** * The purpose of this method is to PUT a string of data to any specified Path. * @param pathValue DAV Path * @param contentType Media Type * @param enc character code * @param data PUT Data * @param etag Etag, specify "*" for forcing new or updated * @return WebDAV WebDAV object * @throws DaoException Exception thrown */ public WebDAV put(String pathValue, String contentType, String enc, String data, String etag) throws DaoException { byte[] bs; try { if (!enc.isEmpty()) { bs = data.getBytes(enc); } else { bs = data.getBytes("UTF-8"); } } catch (UnsupportedEncodingException e) { throw new DaoException("UnsupportedEncodingException", e); } InputStream is = new ByteArrayInputStream(bs); String url = UrlUtils.append(this.getPath(), pathValue); DcResponse res = ((RestAdapter) RestAdapterFactory.create(this.accessor)).putStream(url, contentType, is, etag); WebDAV webDAV = new WebDAV(); webDAV.setResHeaders(res.getHeaderList()); webDAV.setStatusCode(res.getStatusCode()); return webDAV; } // /** // * 指定PathのデータをDeleteします. // * @param pathValue DAVのパス // * @throws DaoException DAO例外 // */ /** * The purpose of this method is to Delete the data in the specified Path. * @param pathValue DAV Path * @throws DaoException Exception thrown */ public void del(String pathValue) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); RestAdapterFactory.create(this.accessor).del(url, "*"); } // /** // * 指定PathのデータをDeleteします(ETag指定). // * @param pathValue DAVのパス // * @param etagValue PUT対象のETag。新規または強制更新の場合は "*" を指定する // * @throws DaoException DAO例外 // */ /** * The purpose of this method is to Delete the data in the specified Path(ETag specified). * @param pathValue DAV Path * @param etagValue Etag, specify "*" for forcing new or updated * @throws DaoException Exception thrown */ public void del(String pathValue, String etagValue) throws DaoException { String url = UrlUtils.append(this.getPath(), pathValue); RestAdapterFactory.create(this.accessor).del(url, etagValue); } }