View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.backend.jpa.access;
20  
21  import java.sql.Timestamp;
22  import java.text.DateFormat;
23  import java.text.SimpleDateFormat;
24  import java.util.Collection;
25  import java.util.List;
26  import java.util.Locale;
27  
28  import org.apache.logging.log4j.LogManager;
29  import org.apache.logging.log4j.Logger;
30  import org.mycore.access.mcrimpl.MCRAccessRule;
31  import org.mycore.access.mcrimpl.MCRRuleStore;
32  import org.mycore.backend.jpa.MCREntityManagerProvider;
33  import org.mycore.common.MCRException;
34  import org.mycore.common.config.MCRConfiguration2;
35  
36  import com.google.common.cache.CacheBuilder;
37  import com.google.common.cache.CacheLoader;
38  import com.google.common.cache.LoadingCache;
39  
40  import jakarta.persistence.EntityManager;
41  import jakarta.persistence.criteria.CriteriaBuilder;
42  import jakarta.persistence.criteria.CriteriaQuery;
43  import jakarta.persistence.criteria.Root;
44  
45  /**
46   * JPA implementation for RuleStore, storing access rules
47   * 
48   * @author Arne Seifert
49   * @author Thomas Scheffler (yagee)
50   */
51  public class MCRJPARuleStore extends MCRRuleStore {
52      private static final Logger LOGGER = LogManager.getLogger();
53  
54      private static int CACHE_SIZE = MCRConfiguration2.getInt("MCR.AccessPool.CacheSize").orElse(2048);
55  
56      private static LoadingCache<String, MCRAccessRule> ruleCache = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE)
57          .build(new CacheLoader<String, MCRAccessRule>() {
58              @Override
59              public MCRAccessRule load(String ruleid) {
60                  MCRAccessRule rule = null;
61                  EntityManager entityManager = MCREntityManagerProvider.getCurrentEntityManager();
62                  MCRACCESSRULE hibrule = entityManager.find(MCRACCESSRULE.class, ruleid);
63                  LOGGER.debug("Getting MCRACCESSRULE done");
64  
65                  if (hibrule != null) {
66                      LOGGER.debug("new MCRAccessRule");
67                      rule = new MCRAccessRule(ruleid, hibrule.getCreator(), hibrule.getCreationdate(),
68                          hibrule.getRule(),
69                          hibrule.getDescription());
70                      LOGGER.debug("new MCRAccessRule done");
71                  }
72                  return rule;
73              }
74          });
75  
76      /**
77       * Method creates new rule in database by given rule-object
78       * 
79       * @param rule
80       *            as MCRAccessRule
81       */
82      @Override
83      public void createRule(MCRAccessRule rule) {
84  
85          if (!existsRule(rule.getId())) {
86              EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
87              MCRACCESSRULE hibrule = new MCRACCESSRULE();
88  
89              DateFormat df = new SimpleDateFormat(SQL_DATE_FORMAT, Locale.ROOT);
90              hibrule.setCreationdate(Timestamp.valueOf(df.format(rule.getCreationTime())));
91              hibrule.setCreator(rule.getCreator());
92              hibrule.setRid(rule.getId());
93              hibrule.setRule(rule.getRuleString());
94              hibrule.setDescription(rule.getDescription());
95              em.persist(hibrule);
96          } else {
97              LOGGER.error("rule with id '{}' can't be created, rule still exists.", rule.getId());
98          }
99      }
100 
101     /**
102      * Method retrieves the ruleIDs of rules, whose string-representation starts with given data
103      */
104     @Override
105     public Collection<String> retrieveRuleIDs(String ruleExpression, String description) {
106         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
107         CriteriaBuilder sb = em.getCriteriaBuilder();
108         CriteriaQuery<String> query = sb.createQuery(String.class);
109         Root<MCRACCESSRULE> ar = query.from(MCRACCESSRULE.class);
110         return em.createQuery(
111             query.select(
112                 ar.get(MCRACCESSRULE_.rid))
113                 .where(
114                     sb.and(
115                         sb.like(ar.get(MCRACCESSRULE_.rule), ruleExpression),
116                         sb.like(ar.get(MCRACCESSRULE_.description), description))))
117             .getResultList();
118     }
119 
120     /**
121      * Method updates accessrule by given rule. internal: get rule object from session set values, update via session
122      */
123     @Override
124     public void updateRule(MCRAccessRule rule) {
125         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
126         MCRACCESSRULE hibrule = em.find(MCRACCESSRULE.class, rule.getId());
127 
128         DateFormat df = new SimpleDateFormat(SQL_DATE_FORMAT, Locale.ROOT);
129         hibrule.setCreationdate(Timestamp.valueOf(df.format(rule.getCreationTime())));
130         hibrule.setCreator(rule.getCreator());
131         hibrule.setRule(rule.getRuleString());
132         hibrule.setDescription(rule.getDescription());
133         ruleCache.put(rule.getId(), rule);
134     }
135 
136     /**
137      * Method deletes accessrule for given ruleid
138      */
139     @Override
140     public void deleteRule(String ruleid) {
141         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
142         em.createQuery("delete MCRACCESSRULE where RID = '" + ruleid + "'").executeUpdate();
143         ruleCache.invalidate(ruleid);
144     }
145 
146     /**
147      * Method returns MCRAccessRule by given id
148      * 
149      * @param ruleid
150      *            as string
151      * @return MCRAccessRule
152      */
153     @Override
154     public MCRAccessRule getRule(String ruleid) {
155         return ruleCache.getUnchecked(ruleid);
156     }
157 
158     @Override
159     public Collection<String> retrieveAllIDs() {
160         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
161         CriteriaQuery<String> query = em.getCriteriaBuilder().createQuery(String.class);
162         return em.createQuery(
163             query.select(
164                 query.from(MCRACCESSRULE.class).get(MCRACCESSRULE_.rid)))
165             .getResultList();
166     }
167 
168     /**
169      * Method checks existance of rule in db
170      * 
171      * @param ruleid
172      *            id as string
173      * @return boolean value
174      */
175     @Override
176     public boolean existsRule(String ruleid) throws MCRException {
177         if (ruleCache.getIfPresent(ruleid) != null) {
178             return true;
179         }
180         return MCREntityManagerProvider.getCurrentEntityManager().find(MCRACCESSRULE.class, ruleid) != null;
181     }
182 
183     @Override
184     public int getNextFreeRuleID(String prefix) {
185         int ret = 1;
186         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
187         List<String> l = em
188             .createQuery("select max(rid) from MCRACCESSRULE where rid like '" + prefix + "%'", String.class)
189             .getResultList();
190         if (l.size() > 0) {
191             String max = l.get(0);
192             if (max == null) {
193                 ret = 1;
194             } else {
195                 int lastNumber = Integer.parseInt(max.substring(prefix.length()));
196                 ret = lastNumber + 1;
197             }
198         } else {
199             return 1;
200         }
201         return ret;
202     }
203 }