Java tutorial
/** * 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 io.personium.core.model.impl.es; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; import org.odata4j.core.OEntity; import org.odata4j.core.OEntityKey; import org.odata4j.core.OProperty; import org.odata4j.expression.BoolCommonExpression; import org.odata4j.producer.EntitiesResponse; import org.odata4j.producer.EntityResponse; import org.odata4j.producer.InlineCount; import org.odata4j.producer.ODataProducer; import org.odata4j.producer.QueryInfo; import org.odata4j.producer.resources.OptionsQueryParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.personium.common.auth.token.IExtRoleContainingToken; import io.personium.common.auth.token.Role; import io.personium.common.es.response.PersoniumGetResponse; import io.personium.common.es.response.PersoniumSearchHit; import io.personium.common.es.response.PersoniumSearchHits; import io.personium.common.es.response.PersoniumSearchResponse; import io.personium.common.es.util.IndexNameEncoder; import io.personium.core.PersoniumCoreException; import io.personium.core.PersoniumCoreLog; import io.personium.core.PersoniumUnitConfig; import io.personium.core.auth.AccessContext; import io.personium.core.auth.AuthUtils; import io.personium.core.event.EventBus; import io.personium.core.event.EventUtils; import io.personium.core.model.Box; import io.personium.core.model.BoxCmp; import io.personium.core.model.Cell; import io.personium.core.model.ModelFactory; import io.personium.core.model.ctl.Account; import io.personium.core.model.ctl.Common; import io.personium.core.model.ctl.ExtCell; import io.personium.core.model.ctl.ExtRole; import io.personium.core.model.ctl.ReceivedMessage; import io.personium.core.model.ctl.Relation; import io.personium.core.model.ctl.SentMessage; import io.personium.core.model.file.BinaryDataAccessException; import io.personium.core.model.file.BinaryDataAccessor; import io.personium.core.model.impl.es.accessor.CellAccessor; import io.personium.core.model.impl.es.accessor.EntitySetAccessor; import io.personium.core.model.impl.es.accessor.ODataLinkAccessor; import io.personium.core.model.impl.es.cache.BoxCache; import io.personium.core.model.impl.es.cache.CellCache; import io.personium.core.model.impl.es.doc.CellDocHandler; import io.personium.core.model.impl.es.doc.OEntityDocHandler; import io.personium.core.model.impl.es.odata.CellCtlODataProducer; import io.personium.core.model.impl.fs.DavCmpFsImpl; import io.personium.core.model.lock.CellLockManager; import io.personium.core.odata.OEntityWrapper; import io.personium.core.utils.UriUtils; import net.spy.memcached.internal.CheckedOperationTimeoutException; /** * Cell object implemented using ElasticSearch. */ public final class CellEsImpl implements Cell { private String id; private String name; private String url; private String owner; private Long published; private Map<String, Object> json; /** * Es???. */ private static final int TOP_NUM = PersoniumUnitConfig.getEsTopNum(); /** * logger. */ static Logger log = LoggerFactory.getLogger(CellEsImpl.class); /** * constructor. */ public CellEsImpl() { } @Override public EventBus getEventBus() { return new EventBus(this); } @Override public boolean isEmpty() { CellCtlODataProducer producer = new CellCtlODataProducer(this); // check no box exists. QueryInfo queryInfo = new QueryInfo(InlineCount.ALLPAGES, null, null, null, null, null, null, null, null); if (producer.getEntitiesCount(Box.EDM_TYPE_NAME, queryInfo).getCount() > 0) { return false; } // check that Main Box is empty Box defaultBox = this.getBoxForName(Box.DEFAULT_BOX_NAME); BoxCmp defaultBoxCmp = ModelFactory.boxCmp(defaultBox); if (!defaultBoxCmp.isEmpty()) { return false; } // check that no Cell Control Object exists // TODO ??????Type?c:?uuid????????? if (producer.getEntitiesCount(Account.EDM_TYPE_NAME, queryInfo).getCount() > 0 || producer.getEntitiesCount(Role.EDM_TYPE_NAME, queryInfo).getCount() > 0 || producer.getEntitiesCount(ExtCell.EDM_TYPE_NAME, queryInfo).getCount() > 0 || producer.getEntitiesCount(ExtRole.EDM_TYPE_NAME, queryInfo).getCount() > 0 || producer.getEntitiesCount(Relation.EDM_TYPE_NAME, queryInfo).getCount() > 0 || producer.getEntitiesCount(SentMessage.EDM_TYPE_NAME, queryInfo).getCount() > 0 || producer.getEntitiesCount(ReceivedMessage.EDM_TYPE_NAME, queryInfo).getCount() > 0) { return false; } // TODO check EventLog return true; } @Override public Box getBoxForName(String boxName) { if (Box.DEFAULT_BOX_NAME.equals(boxName)) { return new Box(this, null); } // URl???Box????????Box??????null?? if (!validatePropertyRegEx(boxName, Common.PATTERN_NAME)) { return null; } // ??Box??? Box cachedBox = BoxCache.get(boxName, this); if (cachedBox != null) { return cachedBox; } Box loadedBox = null; try { ODataProducer op = ModelFactory.ODataCtl.cellCtl(this); EntityResponse er = op.getEntity(Box.EDM_TYPE_NAME, OEntityKey.create(boxName), null); loadedBox = new Box(this, er.getEntity()); BoxCache.cache(loadedBox); return loadedBox; } catch (RuntimeException e) { if (e.getCause() instanceof CheckedOperationTimeoutException) { return loadedBox; } else { return null; } } } @Override public Box getBoxForSchema(String boxSchema) { // ??????? List<String> boxSchemas = UriUtils.getUrlVariations(this.getUnitUrl(), boxSchema); ODataProducer op = ModelFactory.ODataCtl.cellCtl(this); for (int i = 0; i < boxSchemas.size(); i++) { BoolCommonExpression filter = OptionsQueryParser.parseFilter("Schema eq '" + boxSchemas.get(i) + "'"); QueryInfo qi = QueryInfo.newBuilder().setFilter(filter).build(); try { EntitiesResponse er = op.getEntities(Box.EDM_TYPE_NAME, qi); List<OEntity> entList = er.getEntities(); if (entList.size() == 1) { return new Box(this, entList.get(0)); } continue; } catch (RuntimeException e) { return null; } } return null; } /** * @param uriInfo * UriInfo * @return Cell ?Cell????????null */ public static Cell load(final UriInfo uriInfo) { URI reqUri = uriInfo.getRequestUri(); URI baseUri = uriInfo.getBaseUri(); String rPath = reqUri.getPath(); String bPath = baseUri.getPath(); rPath = rPath.substring(bPath.length()); String[] paths = StringUtils.split(rPath, "/"); return findCell("s.Name.untouched", paths[0], uriInfo); } /** * @param id * id * @param uriInfo * UriInfo * @return Cell ?Cell????????null */ public static Cell load(final String id, final UriInfo uriInfo) { log.debug(id); EntitySetAccessor esCells = EsModel.cell(); PersoniumGetResponse resp = esCells.get(id); if (resp.exists()) { CellEsImpl ret = new CellEsImpl(); ret.setJson(resp.getSource()); ret.id = resp.getId(); if (uriInfo != null) { ret.url = getBaseUri(uriInfo, ret.name); } else { ret.url = "/" + ret.name + "/"; } return ret; } else { return null; } } private static String getBaseUri(final UriInfo uriInfo, String cellName) { // URL???Set StringBuilder urlSb = new StringBuilder(); UriBuilder uriBuilder = uriInfo.getBaseUriBuilder(); uriBuilder.scheme(PersoniumUnitConfig.getUnitScheme()); urlSb.append(uriBuilder.build().toASCIIString()); urlSb.append(cellName); urlSb.append("/"); return urlSb.toString(); } /** * ID ??Cell??Cell?Cell??. * @param queryKey * Cell??(Cell??) * @param queryValue * Cell???? * @param uriInfo * UriInfo * @return Cell ?Cell??????????queryKey?????null */ public static Cell findCell(String queryKey, String queryValue, UriInfo uriInfo) { if (!queryKey.equals("_id") && !queryKey.equals("s.Name.untouched")) { return null; } // URl???Cell?????????Cell??????null?? if (!validatePropertyRegEx(queryValue, Common.PATTERN_NAME)) { return null; } EntitySetAccessor ecCells = EsModel.cell(); CellEsImpl ret = new CellEsImpl(); Map<String, Object> cache = CellCache.get(queryValue); if (cache == null) { Map<String, Object> source = new HashMap<String, Object>(); Map<String, Object> filter = new HashMap<String, Object>(); Map<String, Object> term = new HashMap<String, Object>(); term.put(queryKey, queryValue); filter.put("term", term); source.put("query", QueryMapFactory.filteredQuery(null, filter)); PersoniumSearchResponse resp = ecCells.search(source); if (resp == null || resp.getHits().getCount() == 0) { return null; } PersoniumSearchHit hit = resp.getHits().getAt(0); ret.setJson(hit.getSource()); ret.id = hit.getId(); cache = hit.getSource(); cache.put("_id", hit.getId()); try { CellCache.cache(queryValue, cache); } catch (RuntimeException e) { if (e.getCause() instanceof CheckedOperationTimeoutException) { // memcached???????????? log.info("Faild to cache Cell info."); } else { // ?????????? throw PersoniumCoreException.Server.SERVER_CONNECTION_ERROR; } } } else { ret.setJson(cache); ret.id = (String) cache.get("_id"); } ret.url = getBaseUri(uriInfo, ret.name); return ret; } /** * Map????. * @param json * ?Map */ @SuppressWarnings({ "unchecked", "rawtypes" }) public void setJson(Map json) { this.json = json; if (this.json == null) { return; } Map<String, String> urlJson = (Map<String, String>) json.get("s"); Map<String, String> hJson = (Map<String, String>) json.get("h"); this.published = (Long) json.get("p"); this.name = urlJson.get("Name"); this.owner = hJson.get("Owner"); } @Override public OEntityWrapper getAccount(final String username) { ODataProducer op = ModelFactory.ODataCtl.cellCtl(this); OEntityKey key = OEntityKey.create(username); OEntityWrapper oew = null; try { EntityResponse resp = op.getEntity("Account", key, null); oew = (OEntityWrapper) resp.getEntity(); } catch (PersoniumCoreException dce) { log.debug(dce.getMessage()); } return oew; } @Override public boolean authenticateAccount(final OEntityWrapper oew, final String password) { // TODO ?????? ?????ID????????????? String cred = null; if (oew != null) { cred = (String) oew.get("HashedCredential"); } String hCred = AuthUtils.hashPassword(password); if (hCred.equals(cred)) { return true; } return false; } @SuppressWarnings("unchecked") @Override public List<Role> getRoleListForAccount(final String username) { // Account? EntitySetAccessor accountType = EsModel.cellCtl(this, Account.EDM_TYPE_NAME); List<Map<String, Object>> filters = new ArrayList<Map<String, Object>>(); filters.add(QueryMapFactory.termQuery("s.Name.untouched", username)); List<Map<String, Object>> queries = new ArrayList<Map<String, Object>>(); queries.add(QueryMapFactory.termQuery("c", this.getId())); Map<String, Object> query = QueryMapFactory.filteredQuery(null, QueryMapFactory.mustQuery(queries)); Map<String, Object> source = new HashMap<String, Object>(); source.put("filter", QueryMapFactory.andFilter(filters)); source.put("query", query); PersoniumSearchHits hits = accountType.search(source).getHits(); if (hits.getCount() == 0) { return null; } PersoniumSearchHit hit = hits.getHits()[0]; List<Role> ret = new ArrayList<Role>(); ODataLinkAccessor links = EsModel.cellCtlLink(this); // ??????? List<Map<String, Object>> searchRoleQueries = new ArrayList<Map<String, Object>>(); searchRoleQueries.add(QueryMapFactory.termQuery("t1", "Account")); searchRoleQueries.add(QueryMapFactory.termQuery("t2", "Role")); List<Map<String, Object>> searchRoleFilters = new ArrayList<Map<String, Object>>(); searchRoleFilters.add(QueryMapFactory.termQuery("k1", hit.getId())); Map<String, Object> and = new HashMap<String, Object>(); and.put("filters", searchRoleFilters); Map<String, Object> searchRoleFilter = new HashMap<String, Object>(); searchRoleFilter.put("and", and); Map<String, Object> searchRoleSource = new HashMap<String, Object>(); searchRoleSource.put("filter", searchRoleFilter); searchRoleSource.put("query", QueryMapFactory.filteredQuery(null, QueryMapFactory.mustQuery(searchRoleQueries))); // ? searchRoleSource.put("size", TOP_NUM); PersoniumSearchResponse res = links.search(searchRoleSource); if (res == null) { return ret; } PersoniumSearchHit[] hits2 = res.getHits().getHits(); for (PersoniumSearchHit hit2 : hits2) { Map<String, Object> row = hit2.getSource(); String role = (String) row.get("k2"); log.debug(this.id); EntitySetAccessor roleDao = EsModel.cellCtl(this, Role.EDM_TYPE_NAME); PersoniumGetResponse gRes = roleDao.get(role); if (gRes == null) { continue; } Map<String, Object> src = gRes.getSource(); Map<String, Object> s = (Map<String, Object>) src.get("s"); Map<String, Object> l = (Map<String, Object>) src.get("l"); String roleName = (String) s.get(KEY_NAME); String boxId = (String) l.get(Box.EDM_TYPE_NAME); String boxName = null; String schema = null; if (boxId != null) { // Box? EntitySetAccessor box = EsModel.box(this); PersoniumGetResponse getRes = box.get(boxId); if (getRes == null || !getRes.isExists()) { continue; } Map<String, Object> boxsrc = getRes.getSource(); Map<String, Object> boxs = (Map<String, Object>) boxsrc.get("s"); boxName = (String) boxs.get(KEY_NAME); schema = (String) boxs.get(KEY_SCHEMA); } Role roleObj = new Role(roleName, boxName, schema); ret.add(roleObj); } return ret; } @Override public List<Role> getRoleListHere(final IExtRoleContainingToken token) { List<Role> ret = new ArrayList<Role>(); // ExtCell?Role????????Role this.addRoleListExtCelltoRole(token, ret); // ExtCell?Relation?Role????????Role // ? // ExtCell?Relation?ExtRole?Role????????Role this.addRoleListExtCelltoRelationAndExtRole(token, ret); return ret; } /** * ExtCell?Role??????????Role?. * @param token * * @param roles * ??????? */ private void addRoleListExtCelltoRole(final IExtRoleContainingToken token, List<Role> roles) { // ExtCell-Role??????Role?? String extCell = token.getExtCellUrl(); String principal = token.getSubject(); String principalCell; if (principal.contains("#")) { principalCell = token.getSubject().substring(0, principal.indexOf("#")); } else { principalCell = token.getSubject(); } // ?ExtCell???2?????? if (extCell.equals(principalCell)) { ODataProducer op = ModelFactory.ODataCtl.cellCtl(this); EntitiesResponse response = null; // ? QueryInfo qi = QueryInfo.newBuilder().setTop(TOP_NUM).setInlineCount(InlineCount.NONE).build(); List<String> list = UriUtils.getUrlVariations(this.getUnitUrl(), extCell); for (int i = 0; i < list.size(); i++) { String extCellUrl = list.get(i); try { // ExtCell-Role?? response = (EntitiesResponse) op.getNavProperty(ExtCell.EDM_TYPE_NAME, OEntityKey.create(extCellUrl), "_" + Role.EDM_TYPE_NAME, qi); } catch (PersoniumCoreException dce) { if (PersoniumCoreException.OData.NO_SUCH_ENTITY != dce) { throw dce; } } if (response != null) { break; } } if (response == null) { return; } // ExtCell-Role??????????????? List<OEntity> entList = response.getEntities(); for (OEntity ent : entList) { OEntityWrapper entRole = (OEntityWrapper) ent; this.addRole(entRole.getUuid(), roles); } } } /** * ExtCell?Relation?Role????????Role. ? * ExtCell?Relation?ExtRole?Role????????Role. * @param token * * @param roles * ??????? */ @SuppressWarnings("unchecked") private void addRoleListExtCelltoRelationAndExtRole(final IExtRoleContainingToken token, List<Role> roles) { String extCell = token.getExtCellUrl(); // ExtCell-Role??????Role?? ODataProducer op = ModelFactory.ODataCtl.cellCtl(this); EntitiesResponse response = null; // ? QueryInfo qi = QueryInfo.newBuilder().setTop(TOP_NUM).setInlineCount(InlineCount.NONE).build(); List<String> list = UriUtils.getUrlVariations(this.getUnitUrl(), extCell); for (int i = 0; i < list.size(); i++) { try { String extCellUrl = list.get(i); // ExtCell-Relation?? response = (EntitiesResponse) op.getNavProperty(ExtCell.EDM_TYPE_NAME, OEntityKey.create(extCellUrl), "_" + Relation.EDM_TYPE_NAME, qi); } catch (PersoniumCoreException dce) { if (PersoniumCoreException.OData.NO_SUCH_ENTITY != dce) { throw dce; } } if (response != null) { break; } } if (response == null) { return; } List<OEntity> entList = response.getEntities(); for (OEntity ent : entList) { OEntityWrapper entRelation = (OEntityWrapper) ent; // ExtCell-Relation??????????????? PersoniumSearchResponse res = serchRoleLinks(Relation.EDM_TYPE_NAME, entRelation.getUuid()); if (res == null) { continue; } this.addRoles(res.getHits().getHits(), roles); // ?????ExtCell?Relation?Role????????Role.? // ????ExtCell?Relation?ExtRole?Role????????Role??. // Relation?ExtRole?? EntitySetAccessor extRoleType = EsModel.cellCtl(this, ExtRole.EDM_TYPE_NAME); // Relation??????ExtRole? // ???????? Map<String, Object> source = new HashMap<String, Object>(); // ????????? List<Map<String, Object>> implicitFilters = QueryMapFactory.getImplicitFilters(this.id, null, null, null, extRoleType.getType()); String linksKey = OEntityDocHandler.KEY_LINK + "." + Relation.EDM_TYPE_NAME; implicitFilters.add(0, QueryMapFactory.termQuery(linksKey, entRelation.getUuid())); Map<String, Object> query = QueryMapFactory.mustQuery(implicitFilters); Map<String, Object> filteredQuery = QueryMapFactory.filteredQuery(null, query); source.put("query", filteredQuery); long hitNum = extRoleType.count(source); // ExtCell??????????? if (hitNum == 0) { continue; } source.put("size", hitNum); PersoniumSearchHits extRoleHits = extRoleType.search(source).getHits(); // ExtCell??????????? // ????????????????? if (extRoleHits.getCount() == 0) { continue; } for (PersoniumSearchHit extRoleHit : extRoleHits.getHits()) { Map<String, Object> extRoleSource = extRoleHit.getSource(); Map<String, Object> extRoleS = (Map<String, Object>) extRoleSource.get("s"); String esExtRole = (String) extRoleS.get(ExtRole.EDM_TYPE_NAME); // ?????????? for (Role tokenRole : token.getRoleList()) { if (!tokenRole.createUrl().equals(esExtRole)) { continue; } // ExtCell-Role??????????????? PersoniumSearchResponse resExtRoleToRole = serchRoleLinks(ExtRole.EDM_TYPE_NAME, extRoleHit.getId()); if (resExtRoleToRole == null) { continue; } this.addRoles(resExtRoleToRole.getHits().getHits(), roles); } } } } /** * Role???????. * @param searchKey * ???? * @param searchValue * ?uuid * @return ? */ private PersoniumSearchResponse serchRoleLinks(final String searchKey, final String searchValue) { ODataLinkAccessor links = EsModel.cellCtlLink(this); // Relation??????? Map<String, Object> source = new HashMap<String, Object>(); Map<String, Object> filter = new HashMap<String, Object>(); Map<String, Object> and = new HashMap<String, Object>(); List<Map<String, Object>> filters = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> queries = new ArrayList<Map<String, Object>>(); queries.add(QueryMapFactory.termQuery("t1", searchKey)); queries.add(QueryMapFactory.termQuery("t2", "Role")); Map<String, Object> query = QueryMapFactory.filteredQuery(null, QueryMapFactory.mustQuery(queries)); filters.add(QueryMapFactory.termQuery("k1", searchValue)); and.put("filters", filters); filter.put("and", and); source.put("filter", filter); source.put("query", query); // ? source.put("size", TOP_NUM); return links.search(source); } /** * Role????SearchHit??????. * @param hits * Role?? * @param roles * ??????? */ private void addRoles(PersoniumSearchHit[] hits, List<Role> roles) { for (PersoniumSearchHit hit : hits) { Map<String, Object> src = hit.getSource(); String roleUuid = (String) src.get("k2"); // Relation-Role??????????????? this.addRole(roleUuid, roles); } } /** * ???. * @param uuid * Role?UUID * @param roles * ??????? */ @SuppressWarnings("unchecked") private void addRole(String uuid, List<Role> roles) { EntitySetAccessor roleDao = EsModel.cellCtl(this, Role.EDM_TYPE_NAME); PersoniumGetResponse gRes = roleDao.get(uuid); if (gRes == null) { return; } Map<String, Object> src = gRes.getSource(); Map<String, Object> s = (Map<String, Object>) src.get("s"); Map<String, Object> l = (Map<String, Object>) src.get("l"); String roleName = (String) s.get(KEY_NAME); String schema = (String) s.get(KEY_SCHEMA); String boxId = (String) l.get(Box.EDM_TYPE_NAME); String boxName = null; if (boxId != null) { // Box? Map<String, Object> boxsrc = DavCmpFsImpl.searchBox(this, boxId); Map<String, Object> boxs = (Map<String, Object>) boxsrc.get("s"); boxName = (String) boxs.get(KEY_NAME); } roles.add(new Role(roleName, boxName, schema, this.url)); } @Override public String getOwner() { return this.owner; } @Override public String getDataBundleNameWithOutPrefix() { String unitUserName; if (this.owner == null) { unitUserName = AccessContext.TYPE_ANONYMOUS; } else { unitUserName = IndexNameEncoder.encodeEsIndexName(owner); } return unitUserName; } @Override public String getDataBundleName() { String unitUserName = PersoniumUnitConfig.getEsUnitPrefix() + "_" + getDataBundleNameWithOutPrefix(); return unitUserName; } /** * Cell??????. * @return Cell?? */ @Override public String getName() { return name; } /** * ??Cell?ID???. * @return ID */ @Override public String getId() { return this.id; } /** * ??Cell?ID???. * @param id * ID */ public void setId(String id) { this.id = id; } /** * ??Cell?URL???. * @return URL */ @Override public String getUrl() { return this.url; } /** * ??Cell?URL???. * @param url * URL */ public void setUrl(String url) { this.url = url; } /** * ??Cell?Unit URL???. * @return unitUrl */ @Override public String getUnitUrl() { return UriUtils.getUnitUrl(this.getUrl()); } static final String KEY_NAME = "Name"; static final String KEY_SCHEMA = "Schema"; /** * ??????. * @param propValue * * @param dcFormat * dcFormat? * @return ???false? */ private static boolean validatePropertyRegEx(String propValue, String dcFormat) { // ??? Pattern pattern = Pattern.compile(dcFormat); Matcher matcher = pattern.matcher(propValue); if (!matcher.matches()) { return false; } return true; } /** * Cell????. * @return Cell?? */ public long getPublished() { return this.published; } @Override public String roleIdToRoleResourceUrl(String roleId) { CellCtlODataProducer ccop = new CellCtlODataProducer(this); OEntity oe = ccop.getEntityByInternalId(Role.EDM_TYPE_NAME, roleId); if (oe == null) { // ??????null? return null; } String boxName = (String) oe.getProperty("_Box.Name").getValue(); OProperty<?> schemaProp = oe.getProperty("_Box.Schema"); String schema = null; if (schemaProp != null) { schema = (String) schemaProp.getValue(); } String roleName = (String) oe.getProperty("Name").getValue(); Role roleObj = new Role(roleName, boxName, schema, this.getUrl()); return roleObj.createUrl(); } @Override public String roleResourceUrlToId(String roleUrl, String baseUrl) { EntitySetAccessor roleType = EsModel.cellCtl(this, Role.EDM_TYPE_NAME); // roleName?URL? URL rUrl = null; try { // xml:base? if (baseUrl != null && !"".equals(baseUrl)) { // URL? rUrl = new URL(new URL(baseUrl), roleUrl); } else { rUrl = new URL(roleUrl); } } catch (MalformedURLException e) { throw PersoniumCoreException.Dav.ROLE_NOT_FOUND.reason(e); } Role role = null; try { role = new Role(rUrl); } catch (MalformedURLException e) { log.info("Role URL:" + rUrl.toString()); throw PersoniumCoreException.Dav.ROLE_NOT_FOUND; } // ?URL?ACL?URL?????????? if (!(this.getUrl().equals(role.getBaseUrl()))) { PersoniumCoreLog.Dav.ROLE_NOT_FOUND.params("Cell different").writeLog(); throw PersoniumCoreException.Dav.ROLE_NOT_FOUND; } // Role? List<Map<String, Object>> queries = new ArrayList<Map<String, Object>>(); queries.add(QueryMapFactory.termQuery("c", this.getId())); queries.add(QueryMapFactory.termQuery("s." + KEY_NAME + ".untouched", role.getName())); Map<String, Object> query = QueryMapFactory.filteredQuery(null, QueryMapFactory.mustQuery(queries)); List<Map<String, Object>> filters = new ArrayList<Map<String, Object>>(); if (!(Box.DEFAULT_BOX_NAME.equals(role.getBoxName()))) { // Role???????? Box targetBox = this.getBoxForName(role.getBoxName()); if (targetBox == null) { throw PersoniumCoreException.Dav.BOX_LINKED_BY_ROLE_NOT_FOUND.params(baseUrl); } String boxId = targetBox.getId(); filters.add(QueryMapFactory.termQuery("l." + Box.EDM_TYPE_NAME, boxId)); } else { // Role????????null filters.add(QueryMapFactory.missingFilter("l." + Box.EDM_TYPE_NAME)); } Map<String, Object> source = new HashMap<String, Object>(); if (!filters.isEmpty()) { source.put("filter", QueryMapFactory.andFilter(filters)); } source.put("query", query); PersoniumSearchHits hits = roleType.search(source).getHits(); // ?Role??????Null if (hits == null || hits.getCount() == 0) { PersoniumCoreLog.Dav.ROLE_NOT_FOUND.params("Not Hit").writeLog(); throw PersoniumCoreException.Dav.ROLE_NOT_FOUND; } // ?Role???????? if (hits.getAllPages() > 1) { PersoniumCoreLog.OData.FOUND_MULTIPLE_RECORDS.params(hits.getAllPages()).writeLog(); throw PersoniumCoreException.OData.DETECTED_INTERNAL_DATA_CONFLICT; } PersoniumSearchHit hit = hits.getHits()[0]; return hit.getId(); } @Override public void delete(boolean recursive, String unitUserName) { // Cell??????? int maxLoopCount = Integer.valueOf(PersoniumUnitConfig.getCellLockRetryTimes()); long interval = Long.valueOf(PersoniumUnitConfig.getCellLockRetryInterval()); waitCellAccessible(this.id, maxLoopCount, interval); CellLockManager.setBulkDeletionStatus(this.id); // Cell? CellAccessor cellAccessor = (CellAccessor) EsModel.cell(); CellDocHandler docHandler = new CellDocHandler(cellAccessor.get(this.getId())); try { cellAccessor.delete(docHandler); log.info("Cell Entity Deletion End."); } finally { CellCache.clear(this.getName()); CellLockManager.resetBulkDeletionStatus(this.getId()); } // Make this cell empty asynchronously Thread thread = new Thread(new Runnable() { @Override public void run() { makeEmpty(); } }); thread.start(); } private void waitCellAccessible(String cellId, int maxLoopCount, long interval) { for (int loopCount = 0; loopCount < maxLoopCount; loopCount++) { long count = CellLockManager.getReferenceCount(cellId); // ??????????????? if (count <= 1) { return; } try { Thread.sleep(interval); } catch (InterruptedException e) { throw PersoniumCoreException.Misc.CONFLICT_CELLACCESS; } } throw PersoniumCoreException.Misc.CONFLICT_CELLACCESS; } private static final int DAVFILE_DEFAULT_FETCH_COUNT = 1000; @Override public void makeEmpty() { CellAccessor cellAccessor = (CellAccessor) EsModel.cell(); String unitUserNameWithOutPrefix = this.getDataBundleNameWithOutPrefix(); String cellInfoLog = String.format(" CellId:[%s], CellName:[%s], CellUnitUserName:[%s]", this.getId(), this.getName(), this.getDataBundleName()); // ID????WebDav????? long davfileCount = cellAccessor.getDavFileTotalCount(this.getId(), unitUserNameWithOutPrefix); // 1000???WebDav????? int fetchCount = DAVFILE_DEFAULT_FETCH_COUNT; BinaryDataAccessor accessor = new BinaryDataAccessor(PersoniumUnitConfig.getBlobStoreRoot(), unitUserNameWithOutPrefix, PersoniumUnitConfig.getPhysicalDeleteMode(), PersoniumUnitConfig.getFsyncEnabled()); for (int i = 0; i <= davfileCount; i += fetchCount) { // WebDav?ID?? List<String> davFileIdList = cellAccessor.getDavFileIdList(this.getId(), unitUserNameWithOutPrefix, fetchCount, i); // BinaryDataAccessor?delete??.deleted???? for (String davFileId : davFileIdList) { try { accessor.delete(davFileId); } catch (BinaryDataAccessException e) { // ????????? log.warn(String.format("Delete DavFile Failed DavFileId:[%s].", davFileId) + cellInfoLog, e); } } } log.info("DavFile Deletion End."); // delete EventLog file try { EventUtils.deleteEventLog(this.getId(), this.getOwner()); log.info("EventLog Deletion End."); } catch (BinaryDataAccessException e) { // ????????? log.warn("Delete EventLog Failed." + cellInfoLog, e); } // Cell??? cellAccessor.cellBulkDeletion(this.getId(), unitUserNameWithOutPrefix); log.info("Cell Entity Resource Deletion End."); } }