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 com.fujitsu.dc.core.model.impl.es; import java.net.URI; 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 net.spy.memcached.internal.CheckedOperationTimeoutException; import org.apache.commons.lang.StringUtils; import org.odata4j.core.OEntity; import org.odata4j.core.OEntityKey; 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 com.fujitsu.dc.common.auth.token.IExtRoleContainingToken; import com.fujitsu.dc.common.auth.token.Role; import com.fujitsu.dc.common.es.response.DcGetResponse; import com.fujitsu.dc.common.es.response.DcSearchHit; import com.fujitsu.dc.common.es.response.DcSearchHits; import com.fujitsu.dc.common.es.response.DcSearchResponse; import com.fujitsu.dc.common.es.util.IndexNameEncoder; import com.fujitsu.dc.core.DcCoreConfig; import com.fujitsu.dc.core.DcCoreException; import com.fujitsu.dc.core.auth.AccessContext; import com.fujitsu.dc.core.auth.AuthUtils; import com.fujitsu.dc.core.event.EventBus; import com.fujitsu.dc.core.model.Box; import com.fujitsu.dc.core.model.BoxCmp; import com.fujitsu.dc.core.model.Cell; import com.fujitsu.dc.core.model.ModelFactory; import com.fujitsu.dc.core.model.ctl.Account; import com.fujitsu.dc.core.model.ctl.Common; import com.fujitsu.dc.core.model.ctl.ExtCell; import com.fujitsu.dc.core.model.ctl.ExtRole; import com.fujitsu.dc.core.model.ctl.ReceivedMessage; import com.fujitsu.dc.core.model.ctl.Relation; import com.fujitsu.dc.core.model.ctl.SentMessage; import com.fujitsu.dc.core.model.impl.es.accessor.EntitySetAccessor; import com.fujitsu.dc.core.model.impl.es.accessor.ODataLinkAccessor; import com.fujitsu.dc.core.model.impl.es.cache.BoxCache; import com.fujitsu.dc.core.model.impl.es.cache.CellCache; import com.fujitsu.dc.core.model.impl.es.doc.OEntityDocHandler; import com.fujitsu.dc.core.model.impl.es.odata.CellCtlODataProducer; import com.fujitsu.dc.core.odata.OEntityWrapper; /** * Cell?Es???. */ 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 = DcCoreConfig.getEsTopNum(); /** * . */ static Logger log = LoggerFactory.getLogger(CellEsImpl.class); /** * . */ public CellEsImpl() { } @Override public EventBus getEventBus() { return new EventBus(this); } @Override public boolean isEmpty() { CellCtlODataProducer producer = new CellCtlODataProducer(this); // ????. 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; } // ??????? Box defaultBox = this.getBoxForName(Box.DEFAULT_BOX_NAME); BoxCmp defaultBoxCmp = ModelFactory.boxCmp(defaultBox); if (!defaultBoxCmp.isEmpty()) { return false; } // ?????????? // TODO v1.1 ??????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 v1.1 Message?????409 return true; } @Override public void makeEmpty() { // TODO } @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", 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) { ODataProducer op = ModelFactory.ODataCtl.cellCtl(this); BoolCommonExpression filter = OptionsQueryParser.parseFilter("Schema eq '" + boxSchema + "'"); QueryInfo qi = QueryInfo.newBuilder().setFilter(filter).build(); try { EntitiesResponse er = op.getEntities("Box", qi); List<OEntity> entList = er.getEntities(); if (entList.size() != 1) { return null; } return new Box(this, entList.get(0)); } catch (RuntimeException e) { 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) { EntitySetAccessor esCells = EsModel.cell(); DcGetResponse resp = esCells.get(id); if (resp.exists()) { CellEsImpl ret = new CellEsImpl(); ret.setJson(resp.getSource()); ret.id = resp.getId(); return ret; } else { return null; } } /** * 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)); DcSearchResponse resp = ecCells.search(source); if ((resp == null) || (resp.getHits().getCount() == 0)) { return null; } DcSearchHit 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 DcCoreException.Server.SERVER_CONNECTION_ERROR; } } } else { ret.setJson(cache); ret.id = (String) cache.get("_id"); } // URL???Set StringBuilder urlSb = new StringBuilder(); UriBuilder uriBuilder = uriInfo.getBaseUriBuilder(); uriBuilder.scheme(DcCoreConfig.getUnitScheme()); urlSb.append(uriBuilder.build().toASCIIString()); urlSb.append(ret.getName()); urlSb.append("/"); ret.url = urlSb.toString(); 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 (DcCoreException 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); DcSearchHits hits = accountType.search(source).getHits(); if (hits.getCount() == 0) { return null; } DcSearchHit 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); DcSearchResponse res = links.search(searchRoleSource); if (res == null) { return ret; } DcSearchHit[] hits2 = res.getHits().getHits(); for (DcSearchHit 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); DcGetResponse 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"); String boxName = null; String schema = null; if (boxId != null) { // Box? EntitySetAccessor box = EsModel.box(this); DcGetResponse 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(); try { // ExtCell-Role?? response = (EntitiesResponse) op.getNavProperty(ExtCell.EDM_TYPE_NAME, OEntityKey.create(extCell), "_" + Role.EDM_TYPE_NAME, qi); } catch (DcCoreException dce) { if (DcCoreException.OData.NO_SUCH_ENTITY != dce) { throw dce; } } 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; try { // ? QueryInfo qi = QueryInfo.newBuilder().setTop(TOP_NUM).setInlineCount(InlineCount.NONE).build(); // ExtCell-Relation?? response = (EntitiesResponse) op.getNavProperty(ExtCell.EDM_TYPE_NAME, OEntityKey.create(extCell), "_" + Relation.EDM_TYPE_NAME, qi); } catch (DcCoreException dce) { if (DcCoreException.OData.NO_SUCH_ENTITY != dce) { throw dce; } } if (response == null) { return; } List<OEntity> entList = response.getEntities(); for (OEntity ent : entList) { OEntityWrapper entRelation = (OEntityWrapper) ent; // ExtCell-Relation??????????????? DcSearchResponse 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); DcSearchHits extRoleHits = extRoleType.search(source).getHits(); // ExtCell??????????? // ????????????????? if (extRoleHits.getCount() == 0) { continue; } for (DcSearchHit 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??????????????? DcSearchResponse 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 DcSearchResponse 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(DcSearchHit[] hits, List<Role> roles) { for (DcSearchHit 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); DcGetResponse 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 = DavCmpEsImpl.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 getUnitUserNameWithOutPrefix() { String unitUserName; if (this.owner == null) { unitUserName = AccessContext.TYPE_ANONYMOUS; } else { unitUserName = IndexNameEncoder.encodeEsIndexName(owner); } return unitUserName; } @Override public String getUnitUserName() { String unitUserName = DcCoreConfig.getEsUnitPrefix() + "_" + getUnitUserNameWithOutPrefix(); 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; } 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; } }