1 package com.trendmicro.grid.acl.ds.jpa;
2
3 import com.trendmicro.grid.acl.ds.jpa.entities.*;
4 import com.trendmicro.grid.acl.l0.datatypes.*;
5 import com.trendmicro.grid.acl.metadata.Meta;
6 import com.trendmicro.grid.acl.metadata.Metadata;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10 import java.net.URI;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.Iterator;
15
16 import static com.trendmicro.grid.acl.ds.jpa.ReceivedPreparedPackagesHandler.PreparedPackage;
17
18
19
20
21
22
23
24 public class ReceivedPreparedPackagesHandler extends AbstractReceivedFileContentsHandler<Collection<PreparedPackage>> {
25
26 private static final Logger log = LoggerFactory.getLogger(ReceivedPreparedPackagesHandler.class);
27
28 private final JpaPackageRepository packageRepository;
29
30 private final AbstractReceivedResultsHandler<Collection<JpaPackageFamily>> familyHandler;
31
32
33
34
35
36
37
38
39 public ReceivedPreparedPackagesHandler(JpaFileRepository fileRepository, JpaPackageRepository packageRepository,
40 AbstractReceivedResultsHandler<Collection<JpaPackageFamily>> familyHandler) {
41 super(fileRepository);
42 this.familyHandler = familyHandler;
43 this.packageRepository = packageRepository;
44 }
45
46
47
48
49 @Override
50 protected Collection<PreparedPackage> handle(StorageContext context) {
51 final Iterator<JpaPackageFamily> familyRefs = familyHandler.handle(context).iterator();
52
53 Collection<PreparedPackage> preparedPackages = new ArrayList<PreparedPackage>(context.receivedDataSets.size());
54 for (ProcessPackageDataSet dataSet : context.receivedDataSets) {
55
56 context.em.flush();
57 preparedPackages.add(preparedPackage(context, familyRefs.next(), dataSet));
58 }
59
60 return preparedPackages;
61 }
62
63
64
65
66
67
68
69
70
71 PreparedPackage preparedPackage(final StorageContext context,
72 final JpaPackageFamily familyReference,
73 final ProcessPackageDataSet dataSet) {
74
75 final PackageDetails packageDetails = dataSet.getProcessedPackage();
76 final JpaFileDetails fileDetailsReference = createOrUpdateFileReference(context, packageDetails);
77
78 final PackageInformation information = packageDetails.getPackageInformation();
79 final String packageName = information.getName();
80
81 JpaPackageDetails existingDetails = packageRepository.getJpaPackageDetailsListByName(
82 Collections.singleton(packageName)).iterator().next();
83 final boolean isNewPackage = existingDetails == null;
84
85
86 if (isNewPackage) {
87 final String[] tags = information.getTags().toArray(new String[information.getTags().size()]);
88
89 JpaPackageInformation jpaInformation = new JpaPackageInformation(
90 information.getName(), information.getDisplayName(),
91 information.getFamilyName(), information.getVendorName(),
92 tags, fileDetailsReference.getInformation());
93
94 existingDetails = new JpaPackageDetails(familyReference, jpaInformation,
95 packageDetails.getMetadata(), fileDetailsReference);
96
97 if (log.isTraceEnabled()) {
98 log.trace("Storing new package '{}', tagged as '{}'",
99 information.getName(), existingDetails.getPackageInformation().getTags());
100 }
101
102 context.em.persist(existingDetails);
103
104 } else {
105 if (context.ignoreAllUpdates) {
106 if (log.isTraceEnabled()) {
107 log.trace("Not further processing package '{}', " +
108 "updates are generally disabled.", information.getName());
109 }
110 return null;
111 }
112
113
114 if (context.enableHistoryRecording) existingDetails.alignRevisionWithSession(context.em);
115
116
117
118 if (existingDetails.getPackageFileDetails().getPrimaryKey() != fileDetailsReference.getPrimaryKey()) {
119 log.warn("TMACL-01840:The previously stored package named '{}' was reprocessed with a different " +
120 "package file than before identifier was {}, but is now {}. The change is applied but the " +
121 "current ACL version doesn't support to record this in the history table.", new Object[]{
122 packageName, existingDetails.getPackageFileDetails().getIdentifier(),
123 fileDetailsReference.getIdentifier()});
124 }
125
126
127
128 existingDetails.setPackageFileDetails(fileDetailsReference);
129 if(!familyReference.equals(existingDetails.getPackageFamily()))
130 existingDetails.setPackageFamily(familyReference);
131 }
132
133 return new PreparedPackage(context, packageDetails, existingDetails,
134 fileDetailsReference, extractPackageRemoteFilename(dataSet), isNewPackage);
135 }
136
137
138 private JpaFileDetails createOrUpdateFileReference(final StorageContext context, final PackageDetails details) {
139 return createOrUpdateFileReference(context, new FileDetails(
140 details.getFileMetadata().getIdentifier(),
141 details.getPackageInformation().getPackageFileInformation(),
142 details.getFileMetadata().getMetadata()), true
143 );
144 }
145
146
147 private String extractPackageRemoteFilename(ProcessPackageDataSet dataSet) {
148
149 String fileName = "";
150 Collection<Source> sources = dataSet.getProcessSources();
151 if (sources != null && !sources.isEmpty()) {
152 Source mainSource = sources.iterator().next();
153 URI remoteURI = mainSource.getRemoteURI();
154 if (remoteURI != null) {
155 fileName = remoteURI.getPath() == null ? "" : remoteURI.getPath();
156 fileName = fileName.substring(fileName.lastIndexOf('/') + 1);
157 }
158
159 final Metadata sourceMetadata = mainSource.getMetadata();
160 if (sourceMetadata != null)
161 for (String key : StorageOptions.META_FILENAME_KEYS) {
162 Meta m = sourceMetadata.get(key);
163 if (m != null) {
164 String fn = m.getValue();
165 if (fn != null && fn.indexOf('.') != -1)
166 fileName = fn;
167 }
168 }
169 }
170 return fileName;
171 }
172
173
174
175
176
177 public static final class PreparedPackage {
178
179 private final StorageContext context;
180 private final PackageDetails updatedDetails;
181 private final JpaPackageDetails reference;
182 private final JpaFileDetails fileReference;
183 private final String remoteFileName;
184 private final boolean isNew;
185
186 private PreparedPackage(StorageContext context, PackageDetails updatedDetails, JpaPackageDetails reference,
187 JpaFileDetails fileReference, String remoteFileName, boolean isNew) {
188 this.context = context;
189 this.updatedDetails = updatedDetails;
190 this.reference = reference;
191 this.fileReference = fileReference;
192 this.remoteFileName = remoteFileName;
193
194 this.isNew = isNew;
195 }
196
197
198
199
200
201
202 public JpaPackageDetails getReference() {
203 return reference;
204 }
205
206
207
208
209
210
211 public JpaFileDetails getFileReference() {
212 return fileReference;
213 }
214
215
216
217
218
219
220 public String getRemoteFileName() {
221 return remoteFileName;
222 }
223
224
225
226
227
228
229
230
231
232 public void applyFinalPackageUpdates(boolean incrementRevision) {
233 final PackageInformation information = updatedDetails.getPackageInformation();
234 final Metadata metadata = updatedDetails.getMetadata();
235 final boolean ignoreMetadata = context.ignoreNullMetadataUpdates && isNull(metadata);
236
237 if (!isNew && JpaPackageHistory.wasChanged(reference, updatedDetails, ignoreMetadata)) {
238 if (log.isTraceEnabled())
239 log.trace("Updating package-content to: {}", updatedDetails);
240
241 JpaPackageHistory history = new JpaPackageHistory(reference);
242
243
244 if (context.enableHistoryRecording) {
245 if (log.isTraceEnabled())
246 log.trace("Storing new package-content history entry: {}", history);
247 context.em.persist(history);
248 } else {
249 if (log.isTraceEnabled())
250 log.trace("enableHistoryRecording is set to {}. Disregarding package-content history entry: {}", context.enableHistoryRecording, history);
251 }
252
253 final JpaPackageInformation existingInformation = reference.getPackageInformation();
254 reference.setMetadata(metadata);
255 existingInformation.setDisplayName(information.getDisplayName());
256 existingInformation.setTags(information.getTags());
257
258 } else if (incrementRevision) {
259 reference.setRevision(reference.getRevision() + 1);
260
261 if (log.isTraceEnabled()) {
262 log.trace("Incremented package revision inside '{}' " +
263 "after a change in the file assignments.", reference);
264 }
265 }
266 }
267 }
268 }