1 package com.trendmicro.grid.acl.ds.jpa;
2
3 import com.trendmicro.grid.acl.ds.PackageProvider;
4 import com.trendmicro.grid.acl.ds.RemoteCacheable;
5 import com.trendmicro.grid.acl.ds.TagQueryExpression;
6 import com.trendmicro.grid.acl.ds.datatypes.SharedNamedFileIdentifier;
7 import com.trendmicro.grid.acl.ds.datatypes.SharedNamedFileIdentifierListPage;
8 import com.trendmicro.grid.acl.ds.datatypes.SharedPackageDetails;
9 import com.trendmicro.grid.acl.ds.datatypes.SharedPackageInformation;
10 import com.trendmicro.grid.acl.ds.jpa.entities.JpaFileInformation;
11 import com.trendmicro.grid.acl.ds.jpa.entities.JpaNamedFileIdentifier;
12 import com.trendmicro.grid.acl.ds.jpa.entities.JpaPackageDetails;
13 import com.trendmicro.grid.acl.ds.jpa.entities.JpaPackageInformation;
14 import com.trendmicro.grid.acl.ds.jpa.tagquery.TagQueryProviderSelector;
15 import com.trendmicro.grid.acl.ds.jpa.util.FileQueryConfigurator;
16 import com.trendmicro.grid.acl.l0.datatypes.*;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19 import org.springframework.stereotype.Repository;
20 import org.springframework.transaction.annotation.Transactional;
21
22 import javax.annotation.Resource;
23 import javax.persistence.EntityManager;
24 import javax.persistence.PersistenceContext;
25 import javax.persistence.Query;
26 import javax.persistence.TypedQuery;
27 import java.util.*;
28
29 import static com.trendmicro.grid.acl.ds.jpa.util.JpaUtils.*;
30
31
32
33
34
35
36
37 @Repository
38 @Transactional(readOnly = true)
39 public class JpaPackageRepository implements PackageProvider {
40
41 private static final Logger log = LoggerFactory.getLogger(JpaPackageRepository.class);
42
43 private static int pageSize = 1000;
44
45 public static int getPageSize() {
46 return pageSize;
47 }
48
49 public static void setPageSize(int pageSize) {
50 JpaPackageRepository.pageSize = pageSize;
51 }
52
53
54
55
56
57
58
59
60 static final Callback<Object[], NamedFileIdentifier> namedFileIdentifierAssembler = new Callback<Object[], NamedFileIdentifier>() {
61 @Override
62 public NamedFileIdentifier call(Object[] columns) {
63 final FileIdentifier identifier = (FileIdentifier) columns[1];
64 if (columns[0] instanceof String) {
65 final String fileName = (String) columns[0];
66 return new SharedNamedFileIdentifier(identifier, fileName);
67 } else
68 return ((JpaNamedFileIdentifier) columns[0]).export(identifier);
69 }
70 };
71
72 @PersistenceContext(unitName = "CoreDB")
73 EntityManager em;
74
75 @Resource
76 TagQueryProviderSelector providerSelector;
77
78 Integer rootPackageKey;
79
80 @Override
81 public NameListPage getPackageNamesInFamily(String packageFamilyName, int pageNumber) {
82 TypedQuery<String> query = em.createNamedQuery("Packages.GetPackageNamesInFamily", String.class).
83 setParameter("familyName", packageFamilyName);
84 return toNameListPage(query, pageNumber, pageSize);
85 }
86
87 @Override
88 @RemoteCacheable
89 public Collection<Boolean> isPackagesTaggedWithById(Collection<FileIdentifier> files, String[] tags) {
90
91
92 final Collection<Boolean> results = new ArrayList<Boolean>(files.size());
93 for (SharedPackageInformation information : getPackageInformationListById(files))
94 results.add(isTaggedWith(information, tags));
95
96 return results;
97 }
98
99 @Override
100 @RemoteCacheable
101 public Collection<Boolean> isPackagesTaggedWithByName(Collection<String> packageNames, String[] tags) {
102
103
104 final Collection<Boolean> results = new ArrayList<Boolean>(packageNames.size());
105 for (SharedPackageInformation information : getPackageInformationListByName(packageNames))
106 results.add(isTaggedWith(information, tags));
107
108 return results;
109 }
110
111 @Override
112 public NameListPage getMatchingPackageNames(TagQueryExpression expression, Range range, int pageNumber) {
113 if (range != null && !(range instanceof DaysRange)) {
114 log.warn("TMACL-00830:Ignoring CompositeRange in JPA implementation. Such requests should get handled inside the Cache module.");
115 return null;
116 }
117
118 final TagQueryProvider provider = providerSelector.getSelectedProvider(em);
119 final Query query = provider.getMatchingPackageNamesQuery(em, expression, (DaysRange) range);
120
121 return toNameListPage(query, pageNumber, pageSize);
122 }
123
124 @Override
125 public SharedNamedFileIdentifierListPage getFilesContainedInPackageById(FileIdentifier packageFile, int pageNumber) {
126 final FileQueryConfigurator queryConfigurator = new FileQueryConfigurator<Object>(em, null, "Packages.SelectFilesContainedInPackage");
127 Query query = applyPage(queryConfigurator.getUntypedQuery(packageFile), pageNumber, pageSize);
128 return toListPage(query, namedFileIdentifierAssembler, new SharedNamedFileIdentifierListPage());
129 }
130
131 @Override
132 public SharedNamedFileIdentifierListPage getFilesContainedInPackageByName(String packageName, int pageNumber) {
133 Query query = em.createNamedQuery("Packages.SelectFilesContainedInPackageByName").setParameter("name", packageName);
134 applyPage(query, pageNumber, pageSize);
135 return toListPage(query, namedFileIdentifierAssembler, new SharedNamedFileIdentifierListPage());
136 }
137
138
139
140
141
142
143
144
145
146
147 public Map<NamedFileIdentifier, JpaNamedFileIdentifier> getFilesContainedInPackage(JpaPackageDetails packageDetails) {
148
149 final List queryResults = em.createNamedQuery("Packages.SelectFilesContainedInPackageByPrimaryKey").
150 setParameter("packageDetails", packageDetails).getResultList();
151 final Map<NamedFileIdentifier, JpaNamedFileIdentifier> results = new HashMap<NamedFileIdentifier, JpaNamedFileIdentifier>(queryResults.size());
152
153 for (Object queryResult : queryResults) {
154 Object[] cols = (Object[]) queryResult;
155 results.put(namedFileIdentifierAssembler.call(cols), (JpaNamedFileIdentifier) cols[0]);
156 }
157
158 return results;
159 }
160
161 @Override
162 public NameListPage getReferencingPackageNamesById(FileIdentifier file, int pageNumber) {
163 final FileQueryConfigurator<String> queryConfigurator =
164 new FileQueryConfigurator<String>(em, String.class, "Packages.SelectReferencingPackageNames");
165 return toNameListPage(queryConfigurator.getQuery(file), pageNumber, pageSize);
166 }
167
168 @Override
169 public NameListPage getReferencingPackageNames(String packageName, int pageNumber) {
170 final TypedQuery<String> query = em.createNamedQuery(
171 "Packages.SelectReferencingPackageNamesByName", String.class).setParameter("name", packageName);
172 return toNameListPage(query, pageNumber, pageSize);
173 }
174
175 @Override
176 public NameListPage getPackagesContainedInPackageById(FileIdentifier packageFile, int pageNumber) {
177 final FileQueryConfigurator<String> queryConfigurator =
178 new FileQueryConfigurator<String>(em, String.class, "Packages.SelectPackagesContainedInPackage");
179 return toNameListPage(queryConfigurator.getQuery(packageFile), pageNumber, pageSize);
180 }
181
182 @Override
183 public NameListPage getPackagesContainedInPackageByName(String packageName, int pageNumber) {
184 final TypedQuery<String> query = em.createNamedQuery(
185 "Packages.SelectPackagesContainedInPackageByName", String.class).setParameter("name", packageName);
186 return toNameListPage(query, pageNumber, pageSize);
187 }
188
189 @Override
190 @RemoteCacheable
191 public Collection<SharedPackageInformation> getPackageInformationListById(Collection<FileIdentifier> files) {
192 final FileQueryConfigurator queryConfigurator = new FileQueryConfigurator<Object>(em, null, "Packages.SelectPackageInformation");
193
194 final Collection<SharedPackageInformation> results = new ArrayList<SharedPackageInformation>(files.size());
195 for (FileIdentifier file : files)
196 doGetPackageInformationList(queryConfigurator.getUntypedQuery(file), results);
197
198 return results;
199 }
200
201 @Override
202 @RemoteCacheable
203 public Collection<SharedPackageInformation> getPackageInformationListByName(Collection<String> packageNames) {
204 final Query query = em.createNamedQuery("Packages.SelectPackageInformationByName");
205
206 final Collection<SharedPackageInformation> results = new ArrayList<SharedPackageInformation>(packageNames.size());
207 for (String name : packageNames)
208 doGetPackageInformationList(query.setParameter("name", name), results);
209
210 return results;
211 }
212
213 @SuppressWarnings("unchecked")
214 private static void doGetPackageInformationList(final Query query, final Collection<SharedPackageInformation> results) {
215 List<Object[]> rows = query.getResultList();
216 if (rows.isEmpty())
217 results.add(null);
218 else {
219 Object[] row = rows.get(0);
220 ((JpaPackageInformation) row[0]).setPackageFileInformation((JpaFileInformation) row[1]);
221 results.add((SharedPackageInformation) row[0]);
222 }
223 }
224
225 @Override
226 @SuppressWarnings("unchecked")
227 @RemoteCacheable(comment = "Note: Don't use this method for JPA purposes, " +
228 "the returned entities will not be usable when returned from the remote cache.")
229 public Collection<SharedPackageDetails> getPackageDetailsListById(Collection<FileIdentifier> files) {
230 return (Collection) getJpaPackageDetailsListById(files);
231 }
232
233
234
235
236
237
238
239 public Collection<JpaPackageDetails> getJpaPackageDetailsListById(Collection<FileIdentifier> files) {
240 final FileQueryConfigurator<Integer> queryConfigurator =
241 new FileQueryConfigurator<Integer>(em, Integer.class, "Packages.SelectPackageDetailsPrimaryKey");
242
243 final Collection<Integer> results = new ArrayList<Integer>(files.size());
244 for (FileIdentifier file : files)
245 appendSingleElementToList(results, queryConfigurator.getQuery(file));
246
247 return toDetails(results);
248 }
249
250 @Override
251 @SuppressWarnings("unchecked")
252 @RemoteCacheable(comment = "Note: Don't use this method for JPA purposes, " +
253 "the returned entities will not be usable when returned from the remote cache.")
254 public Collection<SharedPackageDetails> getPackageDetailsListByName(Collection<String> packageNames) {
255 return (Collection) getJpaPackageDetailsListByName(packageNames);
256 }
257
258
259
260
261
262
263
264 public Collection<JpaPackageDetails> getJpaPackageDetailsListByName(Collection<String> packageNames) {
265 final TypedQuery<Integer> query = em.createNamedQuery("Packages.SelectPackageDetailsPrimaryKeyByName", Integer.class);
266
267 final Collection<Integer> results = new ArrayList<Integer>(packageNames.size());
268 for (String name : packageNames)
269 appendSingleElementToList(results, query.setParameter("name", name));
270
271 return toDetails(results);
272 }
273
274 private Collection<JpaPackageDetails> toDetails(Collection<Integer> primaryKeys) {
275 final Collection<JpaPackageDetails> results = new ArrayList<JpaPackageDetails>(primaryKeys.size());
276 for (Integer pk : primaryKeys)
277 results.add(pk == null ? null : em.find(JpaPackageDetails.class, pk));
278 return results;
279 }
280
281 @Override
282 @RemoteCacheable(comment = "Note: Don't use this method for JPA purposes, " +
283 "the returned entities will not be usable when returned from the remote cache.")
284 public Collection<FileIdentifier> getPackageFileIdentifiersByName(Collection<String> packageNames) {
285 TypedQuery<FileIdentifier> query = em.createNamedQuery("Packages.GetPackageFileIdentifierByName", FileIdentifier.class);
286
287 final Collection<FileIdentifier> results = new ArrayList<FileIdentifier>(packageNames.size());
288 for (String name : packageNames)
289 appendSingleElementToList(results, query.setParameter("name", name));
290
291 return results;
292 }
293
294
295
296
297
298
299
300 public Integer getPackagePrimaryKeyByName(String packageName) {
301 final boolean isRoot = JpaPackageInformation.ROOT_PACKAGE_NAME.equalsIgnoreCase(packageName);
302 if (isRoot && rootPackageKey != null)
303 return rootPackageKey;
304
305 final List<Integer> r = em.createNamedQuery("Packages.SelectPackageDetailsPrimaryKeyByName", Integer.class).
306 setParameter("name", packageName).getResultList();
307 final Integer result = r.isEmpty() ? null : r.get(0);
308
309 if (isRoot)
310 rootPackageKey = result;
311
312 return result;
313 }
314 }