001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * *** 008 * 009 * Community License: GPL 3.0 010 * 011 * This file is free software: you can redistribute it and/or modify 012 * it under the terms of the GNU General Public License as published 013 * by the Free Software Foundation, either version 3 of the License, 014 * or (at your option) any later version. 015 * 016 * This file is distributed in the hope that it will be useful, but 017 * WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 019 * GNU General Public License for more details. 020 * 021 * You should have received a copy of the GNU General Public License 022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 023 * 024 * *** 025 * 026 * Available Commercial License: GraniteDS SLA 1.0 027 * 028 * This is the appropriate option if you are creating proprietary 029 * applications and you are not prepared to distribute and share the 030 * source code of your application under the GPL v3 license. 031 * 032 * Please visit http://www.granitedataservices.com/license for more 033 * details. 034 */ 035package org.granite.client.tide.security; 036 037import java.util.ArrayList; 038import java.util.HashMap; 039import java.util.IdentityHashMap; 040import java.util.List; 041import java.util.Map; 042import java.util.Map.Entry; 043 044import org.granite.client.tide.BaseIdentity; 045import org.granite.client.tide.server.TideFaultEvent; 046import org.granite.client.tide.server.TideResponder; 047import org.granite.client.tide.server.TideResultEvent; 048 049/** 050 * @author William DRAI 051 */ 052public class TidePermissionCache { 053 054 private final BaseIdentity identity; 055 private final Map<Object, Map<String, Object>> cache = new IdentityHashMap<Object, Map<String, Object>>(); 056 057 public TidePermissionCache(BaseIdentity identity) { 058 this.identity = identity; 059 } 060 061 public boolean get(Object object, String action, TideResponder<Boolean> tideResponder) { 062 Map<String, Object> objectCache = cache.get(object); 063 if (objectCache == null) { 064 objectCache = new HashMap<String, Object>(); 065 cache.put(object, objectCache); 066 } 067 Object cached = objectCache.get(action); 068 if (cached == null) { 069 if (this.identity.isLoggedIn()) { 070 TideResponder<Boolean> responder = new TidePermissionResponder(object, action, tideResponder); 071 identity.call("hasPermission", object, action, responder); 072 objectCache.put(action, responder); 073 } 074 return false; 075 } 076 if (cached instanceof TideResponder) { 077 ((TidePermissionResponder)cached).addResponder(tideResponder); 078 return false; 079 } 080 if (tideResponder != null) { 081 TideResultEvent<Boolean> event = identity.newResultEvent((Boolean)cached); 082 tideResponder.result(event); 083 } 084 return (Boolean)cached; 085 } 086 087 public void clear() { 088 for (Entry<Object, Map<String, Object>> me : cache.entrySet()) { 089 for (Entry<String, Object> me2 : me.getValue().entrySet()) { 090 if (me2.getValue() == Boolean.TRUE) 091 identity.firePropertyChange("hasPermission", true, false); 092 } 093 } 094 cache.clear(); 095 } 096 097 098 private class TidePermissionResponder implements TideResponder<Boolean> { 099 100 private final Object object; 101 private final String action; 102 private final List<TideResponder<Boolean>> responders = new ArrayList<TideResponder<Boolean>>(); 103 104 public TidePermissionResponder(Object object, String action, TideResponder<Boolean> tideResponder) { 105 this.object = object; 106 this.action = action; 107 if (tideResponder != null) 108 responders.add(tideResponder); 109 } 110 111 public void addResponder(TideResponder<Boolean> tideResponder) { 112 responders.add(tideResponder); 113 } 114 115 public void result(TideResultEvent<Boolean> event) { 116 for (TideResponder<Boolean> responder : responders) 117 responder.result(event); 118 119 Map<String, Object> objectCache = cache.get(object); 120 Object cached = objectCache != null ? objectCache.get(action) : null; 121 boolean oldValue = cached instanceof Boolean ? (Boolean)cached : false; 122 objectCache.put(action, event.getResult()); 123 boolean newValue = event.getResult() != null ? event.getResult() : false; 124 if (event.getResult() != oldValue) 125 identity.firePropertyChange("hasPermission", oldValue, newValue); 126 } 127 128 public void fault(TideFaultEvent event) { 129 Map<String, Object> objectCache = cache.get(object); 130 if (objectCache != null) 131 objectCache.remove(action); 132 133 for (TideResponder<Boolean> responder : responders) 134 responder.fault(event); 135 } 136 } 137}