1   package com.trendmicro.grid.acl.ds.dummy;
2   
3   import com.trendmicro.grid.acl.commons.Paths;
4   import com.trendmicro.grid.acl.ds.FileContentRepository;
5   import net.sf.tinyjee.util.Assert;
6   import net.sf.tinyjee.util.Hex;
7   import net.sf.tinyjee.util.FileUtils;
8   import org.slf4j.Logger;
9   import org.slf4j.LoggerFactory;
10  import org.springframework.stereotype.Repository;
11  
12  import javax.annotation.PreDestroy;
13  import java.io.*;
14  import java.net.URI;
15  import java.security.DigestOutputStream;
16  import java.security.MessageDigest;
17  import java.security.NoSuchAlgorithmException;
18  import java.util.UUID;
19  import java.util.Map;
20  import java.util.Properties;
21  import java.util.Date;
22  
23  /**
24   * Is a trivial implementation using a single local folder.
25   *
26   * @author juergen_kellerer, 2010-05-05
27   * @version 1.0
28   */
29  @Repository
30  public class DummyFileRepository implements FileContentRepository {
31  
32  	private static final Logger log = LoggerFactory.getLogger(DummyFileRepository.class);
33  	private static String URI_SCHEME = "dummy-repository";
34  
35  	File repositoryPath;
36  	final int digestLength = newHashKeyDigest().getDigestLength();
37  
38  	public DummyFileRepository() {
39  		try {
40  			repositoryPath = new File(Paths.getResourcePath(), "/dummy-file-repository").getCanonicalFile();
41  			if (!repositoryPath.isDirectory() && !repositoryPath.mkdirs())
42  				throw new IllegalArgumentException("Failed");
43  			cleanup();
44  		} catch (IOException e) {
45  			log.error("TMACL-00070: Failed to initialize the dummy file repository.", e);
46  		}
47  	}
48  
49  	@PreDestroy
50  	void cleanup() {
51  		FileUtils.removeFiles(repositoryPath);
52  	}
53  
54  	public String getHashKeyAlgorithm() {
55  		return newHashKeyDigest().getAlgorithm();
56  	}
57  
58  	public MessageDigest newHashKeyDigest() {
59  		try {
60  			return MessageDigest.getInstance("SHA1");
61  		} catch (NoSuchAlgorithmException e) {
62  			throw new RuntimeException(e);
63  		}
64  	}
65  
66  	File toFile(byte[] hashKey, boolean isProperties) {
67  		return new File(repositoryPath, encodeHashKey(hashKey) + (isProperties ? ".properties" : ".data"));
68  	}
69  
70  	public void attachProperties(byte[] hashKey, Map<String, String> properties) throws IOException {
71  		if (!isExisting(hashKey))
72  			throw new FileNotFoundException(Hex.encode(hashKey));
73  
74  		File propertiesFile = toFile(hashKey, true);
75  		Properties p = new Properties();
76  		p.putAll(properties);
77  		p.store(new FileOutputStream(propertiesFile), "");
78  	}
79  
80  	@SuppressWarnings("unchecked") 
81  	public Map<String, String> readProperties(byte[] hashKey) throws IOException {
82  		if (!isExisting(hashKey))
83  			throw new FileNotFoundException(Hex.encode(hashKey));
84  
85  		File propertiesFile = toFile(hashKey, true);
86  		if (propertiesFile.isFile()) {
87  			Properties p = new Properties();
88  			p.load(new FileInputStream(propertiesFile));
89  			return (Map) p;
90  		}
91  
92  		return null;
93  	}
94  
95  	public boolean isExisting(byte[] hashKey) {
96  		return toFile(hashKey, false).exists();
97  	}
98  
99  	public Date getLastModified(byte[] hashKey) {
100 		long lm = toFile(hashKey, false).lastModified();
101 		return lm == 0L ? null : new Date(lm);
102 	}
103 
104 	public DigestOutputStream openForWrite(byte[] hashKey) throws IllegalStateException, FileNotFoundException {
105 		return new DigestOutputStream(new BufferedOutputStream(
106 				new FileOutputStream(toFile(hashKey, false))), newHashKeyDigest());
107 	}
108 
109 	public InputStream openForRead(byte[] hashKey) throws FileNotFoundException {
110 		return new BufferedInputStream(new FileInputStream(toFile(hashKey, false)));
111 	}
112 
113 	public void rename(byte[] fromHashKey, byte[] toHashKey) throws FileNotFoundException, IllegalArgumentException {
114 		File from = toFile(fromHashKey, false);
115 		if (!from.exists())
116 			throw new FileNotFoundException("The file '" + from + "' does not exist.");
117 		File to = toFile(toHashKey, false);
118 		if (to.exists())
119 			throw new FileNotFoundException("The target file '" + to + "' is in the way.");
120 		from.renameTo(to);
121 	}
122 
123 	public byte[] createTemporaryHashKey() {
124 		return newHashKeyDigest().digest(UUID.randomUUID().toString().getBytes());
125 	}
126 
127 	public URI encodeToInternalURI(byte[] hashKey) {
128 		String key = encodeHashKey(hashKey);
129 		return URI.create(URI_SCHEME + ":" + key);
130 	}
131 
132 	public byte[] decodeFromInternalURI(URI internalURI) {
133 		if (!internalURI.getScheme().equals(URI_SCHEME))
134 			return null;
135 		return decodeHashKey(internalURI.toString().substring(URI_SCHEME.length() + 1));
136 	}
137 
138 	public String encodeHashKey(byte[] hashKey) {
139 		return Hex.encode(hashKey);
140 	}
141 
142 	public byte[] decodeHashKey(String hashKey) {
143 		byte[] hash = Hex.decode(hashKey);
144 		Assert.assertEquals("hashKeyLength", digestLength, hash.length);
145 		return hash;
146 	}
147 }