ref #8189 moving folder funstins from CdmUtils to ConfigFileUtil
[cdmlib.git] / cdmlib-commons / src / main / java / eu / etaxonomy / cdm / common / ConfigFileUtil.java
1 /**
2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.cdm.common;
10
11 import java.io.BufferedWriter;
12 import java.io.File;
13 import java.io.FileInputStream;
14 import java.io.FileNotFoundException;
15 import java.io.IOException;
16 import java.net.URL;
17 import java.nio.file.Files;
18 import java.util.Properties;
19
20 import org.apache.log4j.Logger;
21 import org.springframework.context.EnvironmentAware;
22 import org.springframework.core.env.Environment;
23
24 /**
25 *
26 * @author a.kohlbecker
27 * @since May 8, 2017
28 *
29 */
30 public class ConfigFileUtil implements EnvironmentAware {
31
32 private static final Logger logger = Logger.getLogger(ConfigFileUtil.class);
33
34 private static String userHome = null;
35
36 /**
37 * The per user cdm folder name: ".cdmLibrary"
38 */
39 private static final String CDM_FOLDER_NAME = ".cdmLibrary";
40
41 /**
42 * The per user cdm folder "~/.cdmLibrary"
43 */
44 private static File perUserCdmFolder = null;
45
46 public static File perUserCdmFolder() {
47 return perUserCdmFolder;
48 }
49
50 /**
51 * suggested sub folder for web app related data and configurations.
52 * Each webapp instance should use a dedicated subfolder or file
53 * which is named by the data source bean id.
54 */
55 public static final String SUBFOLDER_WEBAPP = "remote-webapp";
56
57 static final String MUST_EXIST_FILE = "MUST-EXIST.txt";
58
59 //folder separator
60 static String folderSeparator;
61
62 protected Environment env;
63
64 @Override
65 public void setEnvironment(Environment environment) {
66 this.env = environment;
67 if(userHome == null){
68 ConfigFileUtil.userHome = env.getRequiredProperty("user.home");
69 ConfigFileUtil.perUserCdmFolder = new File(userHome + File.separator + CDM_FOLDER_NAME );
70 logger.info("user.home is set to " + ConfigFileUtil.userHome);
71 }
72 }
73
74
75 /**
76 * @return
77 */
78 static public String getFolderSeperator(){
79 if (folderSeparator == null){
80 URL url = CdmUtils.class.getResource("/"+ MUST_EXIST_FILE);
81 if ( url != null && ! urlIsJarOrBundle(url) ){
82 folderSeparator = File.separator;
83 }else{
84 folderSeparator = "/";
85 }
86 }
87 return folderSeparator;
88 }
89
90
91 /**
92 * @param url
93 * @return
94 */
95 static private boolean urlIsJarOrBundle(URL url){
96 return url.getProtocol().startsWith("jar") || url.getProtocol().startsWith("bundleresource");
97 }
98
99
100 public static File getCdmHomeDir() {
101 return new File(perUserCdmFolder + File.separator);
102 }
103
104 /**
105 * Returns specified the sub folder of {@link #CDM_FOLDER_NAME}.
106 * If the sub folder does not exist it will be created.
107 *
108 * @param subFolderName
109 * @return the sub folder or null in case the folder did not exist ant the attempt to create it has failed.
110 *
111 * @see {@link #SUBFOLDER_WEBAPP}
112 */
113 public static File getCdmHomeSubDir(String subFolderName) {
114
115 File parentFolder = getCdmHomeDir();
116 return ensureSubfolderExists(parentFolder, subFolderName);
117 }
118
119 /**
120 * Returns an instance specific folder folder in {@link #CDM_FOLDER_NAME}/<code>subFolderName</code>
121 * Non existing folders will be created.
122 *
123 * @param subFolderName
124 * The name of a subfolded. In most cases this will be {@link #SUBFOLDER_WEBAPP}
125 * @param instanceName
126 * The name of the application instance. The name should be related to the data source id.
127 * @return the sub folder or null in case the folder did not exist ant the attempt to create it has failed.
128 *
129 * @see {@link #SUBFOLDER_WEBAPP}
130 */
131 public static File getCdmInstanceSubDir(String subFolderName, String instanceName) {
132
133 File subfolder = ensureSubfolderExists(getCdmHomeDir(), subFolderName);
134 return ensureSubfolderExists(subfolder, instanceName);
135 }
136
137 /**
138 * @param subFolderName
139 * @param parentFolder
140 * @return
141 */
142 private static File ensureSubfolderExists(File parentFolder, String subFolderName) {
143 if (!parentFolder.exists()){
144 if (!parentFolder.mkdir()) {
145 throw new RuntimeException("Parent folder could not be created: " + parentFolder.getAbsolutePath());
146 }
147 }
148
149 File subfolder = new File(parentFolder, subFolderName);
150 // if the directory does not exist, create it
151 if (!subfolder.exists()) {
152 if (!subfolder.mkdir()) {
153 throw new RuntimeException("Subfolder could not be created: " + subfolder.getAbsolutePath());
154 }
155 }
156 return subfolder;
157 }
158 public static final String CDM_CONFIGFILE_OVERRIDE = "cdm.configfile.override.";
159
160 private Properties props = null;
161
162 private String defaultContent = "";
163
164 public ConfigFileUtil(){
165
166 }
167
168 public ConfigFileUtil setDefaultContent(String content) {
169 if(content != null){
170 defaultContent = content;
171 }
172 return this;
173 }
174
175 /**
176 * Per default the <code>propertiesSet</code> is loaded from a file located in
177 * <code>~/.cdmLibrary/remote-webapp/{instanceName}/{propertiesSet}.properties</code>.
178 * <p>
179 * This behavior can be overwritten by setting the java System property
180 * <code>cdm.configfile.override.{propertiesSet}</code> to an alternative file location.
181 * This mechanism should only be used for unit and integration tests.
182 *
183 * @param instanceName the name of the cdm instance. This value can be retrieved from the
184 * Spring environment with the key DataSourceConfigurer.CDM_DATA_SOURCE_ID ("")
185 * @param propertiesSet
186 * The base name of the properties file to be loaded. This name is extended with
187 * ".properties" to form the actual filename
188 *
189 * @return
190 * The file containing the properties
191 */
192 public File getPropertiesFile(String instanceName, String propertiesSet) {
193
194 if(propertiesSet == null){
195 throw new NullPointerException();
196 }
197 String override = System.getProperty(CDM_CONFIGFILE_OVERRIDE + propertiesSet);
198 if(override != null){
199 return new File(override);
200 } else {
201 File configFolder = ConfigFileUtil.getCdmInstanceSubDir(ConfigFileUtil.SUBFOLDER_WEBAPP, instanceName);
202 return new File(configFolder, propertiesSet + ".properties");
203 }
204 }
205
206 /**
207 * Per default the <code>propertiesSet</code> is loaded from a file located in
208 * <code>~/.cdmLibrary/remote-webapp/{instanceName}/{propertiesSet}.properties</code>.
209 * <p>
210 * This behavior can be overwritten by setting the java System property
211 * <code>cdm.configfile.override.{propertiesSet}</code> to an alternative file location.
212 * This mechanism should only be used for unit and integration tests.
213 *
214 * @param instanceName the name of the cdm instance. This value can be retrieved from the
215 * Spring environment with the key DataSourceConfigurer.CDM_DATA_SOURCE_ID ("")
216 * @param propertiesSet
217 * The base name of the properties file to be loaded. This name is extended with
218 * ".properties" to form the actual filename
219 *
220 * @return
221 * The properties loaded from the file
222 */
223 public Properties getProperties(String instanceName, String propertiesName) throws IOException {
224
225 if(instanceName == null){
226 throw new NullPointerException();
227 }
228 if(props == null){
229 props = new Properties();
230 File uiPropertiesFile = getPropertiesFile(instanceName, propertiesName);
231 if(!uiPropertiesFile.exists()){
232 BufferedWriter writer = Files.newBufferedWriter(uiPropertiesFile.toPath());
233 writer.write(defaultContent);
234 writer.close();
235 }
236 try {
237 props.load(new FileInputStream(uiPropertiesFile));
238 } catch (FileNotFoundException e) {
239 // must not happen since we checked before
240 }
241
242 }
243 return props;
244 }
245 }