1   package com.trendmicro.grid.acl.ds.jpa;
2   
3   import com.trendmicro.grid.acl.ds.jpa.entities.JpaSource;
4   import com.trendmicro.grid.acl.ds.jpa.entities.JpaSourceInformation;
5   import com.trendmicro.grid.acl.l0.datatypes.ProcessPackageDataSet;
6   import com.trendmicro.grid.acl.l0.datatypes.Source;
7   import com.trendmicro.grid.acl.l0.datatypes.SourceIdentifier;
8   import net.sf.tinyjee.config.PropertySection;
9   import org.slf4j.Logger;
10  import org.slf4j.LoggerFactory;
11  
12  import java.util.*;
13  
14  import static com.trendmicro.grid.acl.ds.config.DataSourcePropertySection.*;
15  import static com.trendmicro.grid.acl.ds.jpa.util.JpaUtils.metadataDiffers;
16  import static net.sf.tinyjee.util.Assert.assertNotNull;
17  
18  /**
19   * Implements a handler for syncing source entries contained in processing results.
20   * <p/>
21   * Creates corresponding collections of source references that can be used to assign them to
22   * the package members.
23   *
24   * @author juergen_kellerer, 2010-11-22
25   * @version 1.0
26   */
27  public class ReceivedSourcesHandler extends AbstractReceivedResultsHandler<Collection<List<JpaSource>>> {
28  
29  	private static final Logger log = LoggerFactory.getLogger(ReceivedSourcesHandler.class);
30  
31  	private final JpaSourceRepository sourceRepository;
32  
33  	private final boolean createSourceIfMissing, presetUpdateSource;
34  
35  	/**
36  	 * Creates a thread safe instance.
37  	 *
38  	 * @param sourceRepository the SourceRepository to use.
39  	 */
40  	public ReceivedSourcesHandler(JpaSourceRepository sourceRepository) {
41  		PropertySection section = getPropertySection();
42  
43  		this.sourceRepository = sourceRepository;
44  		createSourceIfMissing = getValue(section, KEY_CREATE_PACKAGE_FAMILY_IF_MISSING);
45  		presetUpdateSource = getValue(section, KEY_UPDATE_SOURCES_FROM_PROCESS_RESULT);
46  	}
47  
48  	public JpaSourceRepository getSourceRepository() {
49  		return sourceRepository;
50  	}
51  
52  	/**
53  	 * Creates a corresponding collection of source references that can be used to assign them to files.
54  	 *
55  	 * @param context the data set to handle.
56  	 * @return a corresponding collection of source references.
57  	 */
58  	@Override
59  	protected Collection<List<JpaSource>> handle(StorageContext context) {
60  		boolean updateSource = !context.ignoreAllUpdates && presetUpdateSource;
61  		return getSourceReferences(context.receivedDataSets, updateSource, context.ignoreNullMetadataUpdates);
62  	}
63  
64  
65  	Collection<List<JpaSource>> getSourceReferences(Collection<ProcessPackageDataSet> dataSets,
66  													boolean updateSource, boolean ignoreNullMetadataUpdates) {
67  
68  		final Collection<List<JpaSource>> refs = new ArrayList<List<JpaSource>>(dataSets.size());
69  
70  		final Map<SourceIdentifier, JpaSource> cache = updateSource ? null :
71  				new HashMap<SourceIdentifier, JpaSource>();
72  
73  		for (ProcessPackageDataSet dataSet : dataSets) {
74  			List<JpaSource> sourceRefs = new ArrayList<JpaSource>();
75  			for (Source source : dataSet.getProcessSources()) {
76  				final SourceIdentifier identifier = source.getSourceInformation().getIdentifier();
77  				JpaSource ref;
78  
79  				if (cache == null || (ref = cache.get(identifier)) == null) {
80  					ref = updateSource ?
81  							sourceRepository.getSource(identifier) :
82  							sourceRepository.getSourceReference(identifier);
83  
84  					if (ref == null) {
85  						if (!createSourceIfMissing) {
86  							throw new IllegalArgumentException("The source '" +
87  									source.getRemoteURI() + "' did not exist inside the CoreDB.");
88  						}
89  
90  						ref = (JpaSource) sourceRepository.createSource(source.getRemoteURI(), source.getInternalURI(),
91  								source.getSourceInformation(), source.getMetadata());
92  						assertNotNull("ProcessingResultReceiver#createdSource", ref);
93  
94  						log.info("TMACL-00980:Implicitly created new source: {}", ref);
95  
96  					} else if (updateSource) {
97  						boolean ignoreMetadata = ignoreNullMetadataUpdates && isNull(source.getMetadata());
98  						boolean changed = !ref.getSourceInformation().equals(source.getSourceInformation()) ||
99  								(!ignoreMetadata && metadataDiffers(ref, source));
100 
101 						if (changed) {
102 							final JpaSourceInformation info = ref.getSourceInformation();
103 							info.setContentTag(source.getSourceInformation().getContentTag());
104 							info.setLastModified(source.getSourceInformation().getLastModified());
105 							ref.setMetadata(source.getMetadata());
106 
107 							log.info("TMACL-00990:Updated source from processing result: {}", ref);
108 						}
109 					}
110 				}
111 
112 				if (cache != null)
113 					cache.put(identifier, ref);
114 				sourceRefs.add(ref);
115 			}
116 			refs.add(sourceRefs);
117 		}
118 		return refs;
119 	}
120 }