1   package com.trendmicro.grid.acl.ds.cifs;
2   
3   import net.sf.tinyjee.collections.Filter;
4   import net.sf.tinyjee.collections.FilteredCollection;
5   import net.sf.tinyjee.config.*;
6   import net.sf.tinyjee.config.documentation.PropertyDocumentation;
7   import net.sf.tinyjee.config.documentation.ResourceDocumentation;
8   import net.sf.tinyjee.config.documentation.SectionDocumentation;
9   
10  import java.util.Arrays;
11  import java.util.Collection;
12  import java.util.Collections;
13  
14  /**
15   * Adds a new configuration section to the application server's config file.
16   *
17   * @author juergen_kellerer, 2010-05-06
18   * @version 1.0
19   */
20  @SectionDocumentation(
21  		name = CIFSPropertySection.NAME_SECTION,
22  		description = "Specifies the configuration options for the GRID file content repository " +
23  				"used by the access layer.\n" +
24  				"\n" +
25  				"This section configures the implementations 'CIFSFileRepository' " +
26  				"and 'LocalFileRepository'.",
27  		properties = {
28  				@PropertyDocumentation(
29  						property = CIFSPropertySection.KEY_FILENAME_HASH_KEY_ALGORITHM,
30  						description = "Defines the hashing algorithm to use for creating the path names.\n" +
31  								"\n" +
32  								"File contents are stored in paths that are generated via the expression:\n" +
33  								"    path = pathPrefix + / + hash(fileContent) + fileExtension\n" +
34  								"\n" +
35  								"Reasonable values this property are: SHA1 or MD5 (default)"
36  				),
37  				@PropertyDocumentation(
38  						property = CIFSPropertySection.KEY_FILENAME_PATH_SCHEMA,
39  						description = "Defines the schema that is used to translate a hash to a file path.\n" +
40  								"\n" +
41  								"This options takes 2 characters '0' and '/'. Every '00' is replaced by the\n" +
42  								"hex value of a single byte in the file hash (single '0' values are invalid).\n" +
43  								"\n" +
44  								"Reasonable values for this property are:\n" +
45  								" - '00000000000000000000000000000000' - creates no folders (with md5 hash)\n" +
46  								" - '00/00/00/' - creates 3 levels of folders (256 on each level)\n" +
47  								"\n" +
48  								"(defaults to empty string => 0000/0000/0000/... is used)."
49  				),
50  				@PropertyDocumentation(
51  						property = CIFSPropertySection.KEY_LOCAL_REPOSITORY_PATH,
52  						description = "Defines the repository path to use by the 'LocalFileRepository'."
53  				),
54  				@PropertyDocumentation(
55  						property = CIFSPropertySection.KEY_FILENAME_EXTENSION,
56  						description = "Defines a file extension to apply for stored file contents " +
57  								"(defaults to empty string => no file extension is added)."
58  				),
59  				@PropertyDocumentation(
60  						property = CIFSPropertySection.KEY_TEMPORARY_PATH_PREFIX,
61  						description = "Defines the path inside the file repository to use for storing " +
62  								"temporary file content.\n" +
63  								"\n" +
64  								"Note: When content is received from remote, it is first streamed to a " +
65  								"temporary location in order to calculate its content hash value. After the " +
66  								"hash value is known, the file is moved to the final location and therefore " +
67  								"the temporary path should be located at the same physical partition to get " +
68  								"the maximum efficiency out of the move operation."
69  				),
70  				@PropertyDocumentation(
71  						property = CIFSPropertySection.KEY_INTERNAL_URI_PREFIX,
72  						description = "Allows to specify a custom value prefix to use when generating " +
73  								"internally reachable URIs pointing to the content stored inside the " +
74  								"file repository.\n" +
75  								"\n" +
76  								"By default this property is empty which will let the implementation choose " +
77  								"a value for the internal URI. Setting this value has no effect on the operations " +
78  								"of the access layer, however it has an influence how internalURI properties are " +
79  								"set when initiating processing.\n" +
80  								"\n" +
81  								"Reasonable values for this property are:\n" +
82  								" - ftp://hostname/path\n" +
83  								" - file:///path\n" +
84  								" - cifs://hostname/path\n" +
85  								" - smb://hostname/path\n"
86  				),
87  				@PropertyDocumentation(
88  						property = CIFSPropertySection.KEY_LOCAL_REPOSITORY_PATH,
89  						description = "Defines the repository path to use by the 'LocalFileRepository'."
90  				)
91  		}
92  )
93  @ResourceDocumentation(
94  		name = CIFSPropertySection.NAME_CIFS_CONNECTION,
95  		description = "Defines an outgoing connection to the GRID file repository using the CIFS protocol.",
96  		properties = {
97  				@PropertyDocumentation(
98  						property = CIFSPropertySection.KEY_CONNECTION_DOMAIN,
99  						description = "Leave empty if not required by the CIFS server."
100 				),
101 				@PropertyDocumentation(
102 						property = CIFSPropertySection.KEY_CONNECTION_PATH_PREFIX,
103 						description = "Defines base path to use on the remote repository."
104 				)
105 		}
106 )
107 public class CIFSPropertySection extends PropertySection implements ConfigurationBuilder {
108 
109 	private static final long serialVersionUID = -4111897772847377832L;
110 	private static final CIFSPropertySection sharedInstance = new CIFSPropertySection();
111 
112 	public static final String NAME_SECTION = "gacl-file-repository";
113 	public static final String NAME_CIFS_CONNECTION = "gacl-cifs-repository";
114 
115 	public static final String KEY_CONNECTION_USERNAME = "username";
116 	public static final String KEY_CONNECTION_PASSWORD = "password";
117 	public static final String KEY_CONNECTION_DOMAIN = "domain";
118 	public static final String KEY_CONNECTION_PATH_PREFIX = "pathPrefix";
119 
120 	public static final String KEY_FILENAME_HASH_KEY_ALGORITHM = "filenameHashKeyAlgorithm";
121 	public static final String KEY_FILENAME_PATH_SCHEMA = "filenamePathSchema";
122 	public static final String KEY_FILENAME_EXTENSION = "filenameExtension";
123 	public static final String KEY_LOCAL_REPOSITORY_PATH = "localRepositoryPath";
124 	public static final String KEY_INTERNAL_URI_PREFIX = "internalURIPrefix";
125 	public static final String KEY_TEMPORARY_PATH_PREFIX = "temporaryPathPrefix";
126 
127 	public static PropertySection getPropertySection() {
128 		Configuration config = ConfigurationContext.getInstance().getConfiguration();
129 		PropertySection section = config.getPropertySection(NAME_SECTION);
130 		return section == null ? sharedInstance : section;
131 	}
132 
133 	public static Collection<Connection> getCIFSConnections() {
134 		Configuration config = ConfigurationContext.getInstance().getConfiguration();
135 		return new FilteredCollection<Connection>(config.getActiveConnections(), new Filter<Connection>() {
136 			public boolean accept(Connection value) {
137 				return NAME_CIFS_CONNECTION.equals(value.getName());
138 			}
139 		});
140 	}
141 
142 	/**
143 	 * Creates a new connection instance that can be used to configure the CIFS provider.
144 	 *
145 	 * @param hostname the hostname of the cifs server.
146 	 * @param path	 the name / path of the share.
147 	 * @param domain   the domain of the user (defaults to "*").
148 	 * @param username the username to connect with.
149 	 * @param password the password to connect with.
150 	 * @return a new connection instance confiogured with the given values.
151 	 */
152 	public static Connection createCIFSConnection(String hostname, String path,
153 												  String domain, String username, String password) {
154 		Connection c = new Connection(
155 				Connection.Protocol.generic, Connection.Type.outgoing, NAME_CIFS_CONNECTION, hostname, 139);
156 		c.addProperty(KEY_CONNECTION_DOMAIN, domain == null ? "*" : domain);
157 		c.addProperty(KEY_CONNECTION_USERNAME, username);
158 		c.addProperty(KEY_CONNECTION_PASSWORD, password);
159 		c.addProperty(KEY_CONNECTION_PATH_PREFIX, path);
160 		return c;
161 	}
162 
163 	{
164 		setSection(NAME_SECTION);
165 
166 		addProperty(KEY_LOCAL_REPOSITORY_PATH, "/path/to/local/repository");
167 		addProperty(KEY_FILENAME_HASH_KEY_ALGORITHM, "MD5");
168 		addProperty(KEY_FILENAME_PATH_SCHEMA, "");
169 		addProperty(KEY_FILENAME_EXTENSION, "");
170 		addProperty(KEY_TEMPORARY_PATH_PREFIX, "temporary");
171 		addProperty(KEY_INTERNAL_URI_PREFIX, "");
172 	}
173 
174 	/**
175 	 * {@inheritDoc}
176 	 */
177 	public Collection<PropertySection> buildDefaultSections() {
178 		return Collections.singleton((PropertySection) new CIFSPropertySection());
179 	}
180 
181 	/**
182 	 * {@inheritDoc}
183 	 */
184 	@Override
185 	public Collection<? extends Resource> buildDefaultResources() {
186 		Connection devConnection = createCIFSConnection("${cifsserver}", "GRID", null, "guest", "tr3ndm1cro");
187 		return Arrays.asList(devConnection);
188 	}
189 }