/**
* 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.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
///**
// * Aceのアクセスクラス.
// */
/**
* It creates a new object of Acl. This class is used for setting access control information.
*/
public class Acl {
/** ACE. */
ArrayList<Ace> aceList;
/** base Attribute Value. */
String roleBaseUrl;
/** requireSchemaAuthz Attribute Value. */
String requireSchemaAuthz;
/**
* This is the default constructor calling its parent constructor and initializing the aceList.
*/
public Acl() {
super();
aceList = new ArrayList<Ace>();
}
// /**
// * base属性値を設定.
// * @param value base属性値
// */
/**
* This method sets the base URL value.
* @param value baseURL
*/
public void setBase(String value) {
this.roleBaseUrl = value;
}
// /**
// * base属性値を取得.
// * @return base属性値
// */
/**
* This method gets the base URL value.
* @return baseURL value
*/
public String getBase() {
return this.roleBaseUrl;
}
// /**
// * requireSchemaAuthz属性値を設定.
// * @param value requireSchemaAuthz属性値
// */
/**
* This method sets the requireSchemaAuthz attribute value.
* @param value requireSchemaAuthz value
*/
public void setRequireSchemaAuthz(String value) {
this.requireSchemaAuthz = value;
}
// /**
// * requireSchemaAuthz属性値を取得.
// * @return requireSchemaAuthz属性値
// */
/**
* This method gets the requireSchemaAuthz attribute value.
* @return requireSchemaAuthz value
*/
public String getRequireSchemaAuthz() {
return this.requireSchemaAuthz;
}
// /**
// * ACEを追加.
// * @param value ACEオブジェクト
// */
/**
* This method adds the specified ace to the aceList.
* @param value ACE object
*/
public void addAce(Ace value) {
this.aceList.add(value);
}
// /**
// * Aceオブジェクトの一覧を返却.
// * @return Aceオブジェクト一覧
// */
/**
* This method returns the list of Ace objects.
* @return Ace List
*/
public ArrayList<Ace> getAceList() {
return aceList;
}
/**
* This method generates a string form of WebDAV ACL XML.
* @return String representation of WebDAV ACL XML
* @throws DaoException DcClientException
*/
public String toXmlString() throws DaoException {
// XML DOM 初期設定
/** XML DOM default. */
String nsD = "DAV:";
String roleBaseUrlStr = this.roleBaseUrl;
String nsDefault = "http://www.w3.org/XML/1998/namespace";
String baseRoleBoxName = "";
/** if roleBaseUrl is not specified, then infer it from the Ace Roles.Also infer baseRoleBoxName. */
if (this.roleBaseUrl == null) {
roleBaseUrlStr = "";
baseRoleBoxName = "";
for (Ace ace : aceList) {
if (ace != null) {
Principal principal = ace.getPrincipal();
if (principal != null && principal instanceof Role) {
Role role = (Role) principal;
roleBaseUrlStr = role.getResourceBaseUrl();
baseRoleBoxName = role.getBoxName();
break;
} else {
roleBaseUrlStr = "";
baseRoleBoxName = "";
}
}
}
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e1) {
throw new DaoException(e1.getMessage(), e1);
}
DOMImplementation domImpl = builder.getDOMImplementation();
Document document = domImpl.createDocument(nsD, "D:acl", null);
// root 要素作成
/** Root element created. */
Element acl = document.getDocumentElement();
Attr attrBase = document.createAttributeNS(nsDefault, "xml:base");
attrBase.setValue(roleBaseUrlStr);
acl.setAttributeNodeNS(attrBase);
if (this.requireSchemaAuthz != null && !this.requireSchemaAuthz.trim().equals("")) {
Attr attrRequireSchemaAuthz = document.createAttributeNS("urn:x-dc1:xmlns", "dc:requireSchemaAuthz");
attrRequireSchemaAuthz.setValue(requireSchemaAuthz);
acl.setAttributeNodeNS(attrRequireSchemaAuthz);
}
// ace要素
/** Ace element. */
for (Ace ace : aceList) {
if (ace == null) {
continue;
}
Element elmAce = document.createElementNS(nsD, "D:ace");
acl.appendChild(elmAce);
/** acl/ace/principal */
Element elmPrincipal = document.createElementNS(nsD, "D:principal");
elmAce.appendChild(elmPrincipal);
if (ace.getPrincipal() == Principal.ALL) {
Element elmHref = document.createElementNS(nsD, "D:all");
elmPrincipal.appendChild(elmHref);
} else {
/** acl/ace/principal/href */
Element elmHref = document.createElementNS(nsD, "D:href");
elmPrincipal.appendChild(elmHref);
if (ace.getPrincipal() != null) {
/** href string should be relative url. */
Role aceRole = (Role) ace.getPrincipal();
String relativeUrl = aceRole.getRelativeUrl(baseRoleBoxName);
Text text = document.createTextNode(relativeUrl);
elmHref.appendChild(text);
}
}
/** acl/ace/grant */
Element elmGrant = document.createElementNS(nsD, "D:grant");
elmAce.appendChild(elmGrant);
for (String privilege : ace.getPrivilegeList()) {
if (privilege == null) {
continue;
}
/** acl/ace/grant/privilege */
Element elmPrivilege = document.createElementNS(nsD, "D:privilege");
elmGrant.appendChild(elmPrivilege);
// 各権限
/** Each authority. */
Element elm = document.createElementNS(nsD, "D:" + privilege);
elmPrivilege.appendChild(elm);
}
}
// XML を 文字列化する
/** Converts XML to string. */
StringWriter sw = new StringWriter();
TransformerFactory tfactory = TransformerFactory.newInstance();
Transformer transformer = null;
try {
transformer = tfactory.newTransformer();
} catch (TransformerConfigurationException e) {
throw new RuntimeException(e);
}
try {
if (transformer != null) {
transformer.transform(new DOMSource(acl), new StreamResult(sw));
}
} catch (TransformerException e) {
throw new RuntimeException(e);
}
return sw.toString();
}
/**
* This method is used to parse the WebDAV ACL XML String and generate Acl object.
* @param xmlStr String representation of WebDAV ACL XML
* @return Acl class instance.
*/
public static Acl parse(String xmlStr) {
String nsD = "DAV:";
String roleBaseUrl = "";
String requireSchemaAuthz = "";
String nsDefault = "http://www.w3.org/XML/1998/namespace";
DocumentBuilder builder = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
Document document = null;
InputStream is = new ByteArrayInputStream(xmlStr.getBytes());
try {
if (builder != null) {
document = builder.parse(is);
}
} catch (SAXException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
Acl acl = new Acl();
if (document == null) {
return acl;
}
// Root要素取得
/** Root element acquisition. */
Element elmAcl = (Element) document.getElementsByTagNameNS(nsD, "acl").item(0);
// Base属性値を取得し、Aclオブジェクトにセット
/** Get the Base attribute value, and set to Acl object. */
roleBaseUrl = elmAcl.getAttributeNS(nsDefault, "base");
acl.setBase(roleBaseUrl);
// requireSchemaAuthz属性値を取得し、Aclオブジェクトにセット
/** Get the requireSchemaAuthz attribute value, and set to Acl object. */
requireSchemaAuthz = elmAcl.getAttributeNS("urn:x-dc1:xmlns", "requireSchemaAuthz");
acl.setRequireSchemaAuthz(requireSchemaAuthz);
// 子Aceのリストを取得
/** Get a list of child Ace. */
NodeList nl = document.getElementsByTagNameNS(nsD, "ace");
Ace ace = null;
Element elmAce = null;
for (int i = 0; i < nl.getLength(); i++) {
// Aceオブジェクト生成
/** Ace object creation. */
ace = new Ace();
acl.addAce(ace);
// Role名(href属性値)を取得し、Aceオブジェクトにセット
/** Get Role name (href attribute value), and sets the object Ace. */
elmAce = (Element) nl.item(i);
NodeList nodeList = elmAce.getElementsByTagNameNS(nsD, "href");
if (nodeList.getLength() == 0) {
ace.setPrincipal(Principal.ALL);
} else {
/** The principal is a Role.. */
String roleUrl = nodeList.item(0).getFirstChild().getNodeValue();
Role role = new Role();
role.setName(roleUrl);
ace.setPrincipal(role);
// ace.setRoleName(roleUrl);
}
// privilege要素
/** The privilege element. */
NodeList privilegeList = elmAce.getElementsByTagNameNS(nsD, "privilege");
for (int n = 0; n < privilegeList.getLength(); n++) {
Node elmPrivilege = privilegeList.item(n);
// privilege要素の子要素の要素名をprivilege値としてAceオブジェクトにセットする
/**
* set to Ace object privilege as the value element name of the child elements of the privilege element.
*/
ace.addPrivilege(getChildElementName(elmPrivilege));
}
}
return acl;
}
/**
* This method is used to fetch the privilege name from XML node.
* @param elm Node
* @return privilegeName
*/
static String getChildElementName(Node elm) {
NodeList nl = elm.getChildNodes();
String name = "";
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
name = node.getLocalName();
break;
}
}
return name;
}
}