1   package com.trendmicro.grid.acl.ds.jpa.entities;
2   
3   import com.trendmicro.grid.acl.ds.datatypes.SharedFileDetails;
4   import com.trendmicro.grid.acl.metadata.Metadata;
5   import org.hibernate.annotations.Type;
6   import org.hibernate.search.annotations.DocumentId;
7   import org.hibernate.search.annotations.Indexed;
8   import org.hibernate.search.annotations.IndexedEmbedded;
9   
10  import javax.persistence.*;
11  
12  import static com.trendmicro.grid.acl.Limits.MAX_SERIALIZED_METADATA_LENGTH;
13  import static com.trendmicro.grid.acl.ds.jpa.QueryHints.*;
14  
15  /**
16   * Binds FileDetails to the table "FILE_CONTENTS".
17   *
18   * @author juergen_kellerer, 2010-06-07
19   * @version 1.0
20   */
21  @NamedQueries({
22  		@NamedQuery(name = "FileContents.GetPrimaryKeyBySHA1", query = "" +
23  				"SELECT fc.primaryKey FROM FILE_CONTENTS fc " +
24  				"WHERE fc.identifier.sha1 = :sha1",
25  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
26  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
27  		@NamedQuery(name = "FileContents.GetPrimaryKeyByMD5", query = "" +
28  				"SELECT fc.primaryKey FROM FILE_CONTENTS fc " +
29  				"WHERE fc.identifier.md5 = :md5",
30  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
31  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
32  		@NamedQuery(name = "FileContents.GetPrimaryKeyBySHA1AndMD5", query = "" +
33  				"SELECT fc.primaryKey FROM FILE_CONTENTS fc " +
34  				"WHERE fc.identifier.sha1 = :sha1 AND fc.identifier.md5 = :md5",
35  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
36  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
37  
38  
39  		@NamedQuery(name = "FileContents.IsFileKnownBySHA1", query = "" +
40  				"SELECT 1 FROM FILE_CONTENTS fc " +
41  				"WHERE fc.information.unknown = false AND fc.identifier.sha1 = :sha1",
42  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
43  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
44  		@NamedQuery(name = "FileContents.IsFileKnownByMD5", query = "" +
45  				"SELECT 1 FROM FILE_CONTENTS fc " +
46  				"WHERE fc.information.unknown = false AND fc.identifier.md5 = :md5",
47  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
48  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
49  		@NamedQuery(name = "FileContents.IsFileKnownBySHA1AndMD5", query = "" +
50  				"SELECT 1 FROM FILE_CONTENTS fc " +
51  				"WHERE fc.information.unknown = false AND fc.identifier.sha1 = :sha1 AND fc.identifier.md5 = :md5",
52  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
53  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
54  
55  
56  		@NamedQuery(name = "FileContents.SelectFileIdentifierBySHA1", query = "" +
57  				"SELECT fc.identifier FROM FILE_CONTENTS fc " +
58  				"WHERE fc.identifier.sha1 = :sha1",
59  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
60  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
61  		@NamedQuery(name = "FileContents.SelectFileIdentifierByMD5", query = "" +
62  				"SELECT fc.identifier FROM FILE_CONTENTS fc " +
63  				"WHERE fc.identifier.md5 = :md5",
64  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
65  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
66  		@NamedQuery(name = "FileContents.SelectFileIdentifierBySHA1AndMD5", query = "" +
67  				"SELECT fc.identifier FROM FILE_CONTENTS fc " +
68  				"WHERE fc.identifier.sha1 = :sha1 AND fc.identifier.md5 = :md5",
69  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
70  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
71  
72  
73  		@NamedQuery(name = "FileContents.SelectFileInformationBySHA1", query = "" +
74  				"SELECT fc.information FROM FILE_CONTENTS fc " +
75  				"WHERE fc.identifier.sha1 = :sha1",
76  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
77  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
78  		@NamedQuery(name = "FileContents.SelectFileInformationByMD5", query = "" +
79  				"SELECT fc.information FROM FILE_CONTENTS fc " +
80  				"WHERE fc.identifier.md5 = :md5",
81  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
82  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
83  		@NamedQuery(name = "FileContents.SelectFileInformationBySHA1AndMD5", query = "" +
84  				"SELECT fc.information FROM FILE_CONTENTS fc " +
85  				"WHERE fc.identifier.sha1 = :sha1 AND fc.identifier.md5 = :md5",
86  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
87  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
88  
89  
90  		@NamedQuery(name = "FileContents.SelectFileDetailsBySHA1", query = "" +
91  				"SELECT fc FROM FILE_CONTENTS fc " +
92  				"WHERE fc.identifier.sha1 = :sha1",
93  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
94  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
95  		@NamedQuery(name = "FileContents.SelectFileDetailsByMD5", query = "" +
96  				"SELECT fc FROM FILE_CONTENTS fc " +
97  				"WHERE fc.identifier.md5 = :md5",
98  				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
99  						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
100 		@NamedQuery(name = "FileContents.SelectFileDetailsBySHA1AndMD5", query = "" +
101 				"SELECT fc FROM FILE_CONTENTS fc " +
102 				"WHERE fc.identifier.sha1 = :sha1 AND fc.identifier.md5 = :md5",
103 				hints = {@QueryHint(name = CACHEABLE, value = V_YES),
104 						@QueryHint(name = CACHE_RETRIEVE_MODE, value = V_USE), @QueryHint(name = CACHE_STORE_MODE, value = V_USE)}),
105 
106 
107 		@NamedQuery(name = "FileContents.UpdateModificationDates", query = "" +
108 				"UPDATE FILE_CONTENTS fc " +
109 				"SET 	fc.information.lastProcessed = :lastProcessed, " +
110 				"		fc.information.lastRetrieved = :lastRetrieved " +
111 				"WHERE 	fc.id = :fileId")
112 })
113 @Indexed
114 @Cacheable
115 @Entity(name = "FILE_CONTENTS")
116 public class JpaFileDetails extends SharedFileDetails {
117 
118 	private static final long serialVersionUID = -8305654919580285347L;
119 
120 	private int primaryKey;
121 	private int revision = 1;
122 
123 	public JpaFileDetails() {
124 	}
125 
126 	public JpaFileDetails(JpaFileIdentifier identifier, JpaFileInformation information, Metadata metadata) {
127 		super(identifier, information, metadata == null ? null : metadata.clone());
128 	}
129 
130 	@Id
131 	@DocumentId
132 	@GeneratedValue
133 	@Column(name = "FILE_CONTENT_ID")
134 	public int getPrimaryKey() {
135 		return primaryKey;
136 	}
137 
138 	public void setPrimaryKey(int primaryKey) {
139 		this.primaryKey = primaryKey;
140 	}
141 
142 	@Column(name = "REVISION", nullable = false)
143 	public int getRevision() {
144 		return revision;
145 	}
146 
147 	public void setRevision(int revision) {
148 		this.revision = revision;
149 	}
150 
151 	/**
152 	 * Selects the current max revision that is stored in the history tables.
153 	 * <p/>
154 	 * NOTE: Data replication or bugs may cause revision numbers to get out of track.
155 	 * This implementation synchronizes the revision to ensure an insert doesn't fail
156 	 * on a unique key constraint.
157 	 *
158 	 * @param entityManager the entity manager to use for the operation.
159 	 */
160 	public void alignRevisionWithSession(EntityManager entityManager) {
161 		if (primaryKey != 0) {
162 			final Integer maxRevision = entityManager.createNamedQuery(
163 					"FileContentHistory.SelectMaxRevisionForPackage", Integer.class).
164 					setParameter("parent", this).getSingleResult();
165 
166 			if (maxRevision != null)
167 				setRevision(maxRevision + 1);
168 			else
169 				setRevision(1);
170 		}
171 	}
172 
173 	@Override
174 	@Embedded
175 	@IndexedEmbedded
176 	public JpaFileInformation getInformation() {
177 		return (JpaFileInformation) information;
178 	}
179 
180 	public void setInformation(JpaFileInformation information) {
181 		this.information = information;
182 	}
183 
184 	@Override
185 	@Embedded
186 	@IndexedEmbedded
187 	public JpaFileIdentifier getIdentifier() {
188 		return (JpaFileIdentifier) identifier;
189 	}
190 
191 	public void setIdentifier(JpaFileIdentifier identifier) {
192 		this.identifier = identifier;
193 	}
194 
195 	@Override
196 	@Type(type = "metadata")
197 	@Basic(fetch = FetchType.EAGER)
198 	@Column(name = "META_DATA", length = MAX_SERIALIZED_METADATA_LENGTH)
199 	public Metadata getMetadata() {
200 		return super.getMetadata();
201 	}
202 
203 	@Override
204 	public void setMetadata(Metadata metadata) { //NOSONAR - Override is required as hook for JPA.
205 		super.setMetadata(metadata == null ? null : metadata.clone());
206 	}
207 
208 	/**
209 	 * {@inheritDoc}
210 	 */
211 	@Override
212 	public boolean equals(Object o) {
213 		if (this == o) return true;
214 		if (!(o instanceof JpaFileDetails)) return false;
215 
216 		JpaFileDetails that = (JpaFileDetails) o;
217 
218 		if (primaryKey != that.primaryKey) return false;
219 		if (revision != that.revision) return false;
220 		return super.equals(o);
221 	}
222 
223 	/**
224 	 * {@inheritDoc}
225 	 */
226 	@Override
227 	public int hashCode() {
228 		int result = super.hashCode();
229 		result = 31 * result + primaryKey;
230 		result = 31 * result + revision;
231 		return result;
232 	}
233 
234 	/**
235 	 * {@inheritDoc}
236 	 */
237 	@Override
238 	public String toString() {
239 		return "FileDetails{" +
240 				"primaryKey=" + primaryKey +
241 				"revision=" + revision +
242 				"identifier=" + identifier +
243 				"information=" + information +
244 				"metadata=" + metadata +
245 				'}';
246 	}
247 }