1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.environment.internal

File AbstractEnvironment.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

24
46
9
1
254
118
26
0.57
5.11
9
2.89

Classes

Class Line # Actions
AbstractEnvironment 39 46 0% 26 6
0.924050692.4%
 

Contributing tests

This file is covered by 84 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.environment.internal;
21   
22    import java.io.File;
23    import java.io.IOException;
24    import java.nio.file.Files;
25   
26    import javax.inject.Inject;
27    import javax.inject.Provider;
28   
29    import org.apache.commons.io.FileUtils;
30    import org.slf4j.Logger;
31    import org.xwiki.environment.Environment;
32   
33    /**
34    * Makes it easy to implement {@link org.xwiki.environment.Environment}.
35    *
36    * @version $Id: ce00789368fc96add8b245e8de4e568341cc3565 $
37    * @since 3.5M1
38    */
 
39    public abstract class AbstractEnvironment implements Environment
40    {
41    /**
42    * Default temporary directory to use when none has been specified.
43    */
44    private static final String DEFAULT_TMP_DIRECTORY = System.getProperty("java.io.tmpdir");
45   
46    /**
47    * The name of the temporary directory which will be cleaned at every restart.
48    */
49    private static final String TEMP_NAME = "xwiki-temp";
50   
51    @Inject
52    protected Logger logger;
53   
54    /**
55    * Environment configuration data. We load it lazily to avoid a cyclic runtime dependency between the Environment
56    * implementation (which requires a Configuration Source) and the Configuration Source implementation (which
57    * requires an Environment).
58    */
59    @Inject
60    private Provider<EnvironmentConfiguration> configurationProvider;
61   
62    /**
63    * @see #getTemporaryDirectory()
64    */
65    private File temporaryDirectory;
66   
67    /**
68    * @see #getPermanentDirectory()
69    */
70    private File permanentDirectory;
71   
72    /**
73    * @param permanentDirectory see {@link #getPermanentDirectory()}
74    */
 
75  235 toggle public void setPermanentDirectory(File permanentDirectory)
76    {
77  235 this.permanentDirectory = permanentDirectory;
78    }
79   
80    /**
81    * @param temporaryDirectory see {@link #getTemporaryDirectory()}
82    */
 
83  239 toggle public void setTemporaryDirectory(File temporaryDirectory)
84    {
85  239 this.temporaryDirectory = temporaryDirectory;
86    }
87   
88    /**
89    * {@inheritDoc}
90    * <p>
91    * Rather than overriding this, it is safer to override {@link #getPermanentDirectoryName()} if you need to change
92    * the default behavior. This is because this method does a number of checks to make sure the directory exists, is a
93    * directory (not a file) and the XWiki process has permission to write to it. If the directory doesn't exist it is
94    * created and if it cannot be written to, an error is printed in the log and it is passed over for the default
95    * permanent directory. Thus by overriding {@link #getPermanentDirectoryName()} you'll still benefit from all those
96    * checks.
97    * </p>
98    */
 
99  1065 toggle @Override
100    public File getPermanentDirectory()
101    {
102    // Note: We're initializing the permanent directory here instead of in an Initializable.initialize() method
103    // since otherwise we get a cyclic dependency with the Configuration Source implementation used to get the
104    // Environment configuration property for the permanent directory location (since that Source require the
105    // Environment for finding the configuration resource in the executing Environment).
106  1065 if (this.permanentDirectory == null) {
107  56 String systemProperty = System.getProperty("xwiki.data.dir");
108  56 final String classSpecified = getPermanentDirectoryName();
109  56 final String configured = this.configurationProvider.get().getPermanentDirectoryPath();
110   
111  56 final String[] locations =
112    new String[] { systemProperty, classSpecified, configured, getTemporaryDirectoryName(),
113    DEFAULT_TMP_DIRECTORY };
114  55 this.permanentDirectory = initializeDirectory(locations, false);
115   
116  55 if (systemProperty == null && classSpecified == null && configured == null) {
117    // There's no defined permanent directory, fall back to the temporary directory but issue a warning
118  7 this.logger.warn("No permanent directory configured, fallbacking to temporary directory. "
119    + "You should set the \"environment.permanentDirectory\" configuration property in the "
120    + "xwiki.properties file.");
121    }
122  55 this.logger.info("Using permanent directory [{}]", this.permanentDirectory);
123    }
124   
125  1064 return this.permanentDirectory;
126    }
127   
128    /**
129    * Get the name of the permanent directory to use. This name will be preferred when choosing the permanent directory
130    * and if it is not able to be written to, this class will fail over to the default directory after printing an
131    * error in the log file.
132    *
133    * @return the permanent directory as specified
134    */
 
135  56 toggle protected String getPermanentDirectoryName()
136    {
137  56 return null;
138    }
139   
140    /**
141    * {@inheritDoc}
142    * <p>
143    * Rather than overriding this, it is safer to override {@link #getTemporaryDirectoryName()} This is
144    * because this function does a number of checks to make sure the directory exists, is a directory (not a file) and
145    * the XWiki process has permission to write to it. If the directory doesn't exist it is created and if it cannot be
146    * written to, an erroris printed in the log and it is passed over for the default temporary directory.
147    * </p>
148    *
149    * @see Environment#getTemporaryDirectory()
150    */
 
151  1961 toggle @Override
152    public File getTemporaryDirectory()
153    {
154  1962 if (this.temporaryDirectory == null) {
155  74 final String[] locations = new String[] { getTemporaryDirectoryName(), DEFAULT_TMP_DIRECTORY };
156  74 this.temporaryDirectory = initializeDirectory(locations, true);
157    }
158   
159  1961 return this.temporaryDirectory;
160    }
161   
162    /**
163    * Get the name of the temporary directory to use. The path given name will be preferred when choosing the temporary
164    * directory and if it is not able to be written to, this class will fail over to the default directory after
165    * printing an error in the log file.
166    *
167    * @return the temporary directory as specified
168    */
 
169  130 toggle protected String getTemporaryDirectoryName()
170    {
171  130 return null;
172    }
173   
174    /**
175    * @param locations the names of the directories to try to initialize ordered from best to worst. If none of these
176    * can be initialized, the system will be halted.
177    * @param isTemp true if the directory is a temporary directory.
178    * @return the initialized directory as a {@link File} or null if the directory doesn't exist, cannot be created or
179    * the passed name was null
180    */
 
181  129 toggle private File initializeDirectory(final String[] locations, final boolean isTemp)
182    {
183  129 final String tempOrPermanent = (isTemp) ? "temporary" : "permanent";
184  129 boolean first = true;
185  129 for (final String location : locations) {
186  203 if (location == null) {
187  74 continue;
188    }
189  129 if (!first) {
190  0 this.logger.warn("Falling back on [{}] as the {} directory.", location, tempOrPermanent);
191    }
192  129 first = false;
193  129 final File dir = initializeDirectory(location, isTemp, tempOrPermanent);
194  129 if (dir != null) {
195  128 return dir;
196    }
197    }
198   
199  1 throw new RuntimeException(String.format(
200    "Could not find a writable %s directory. Check the server logs for more information.", tempOrPermanent));
201    }
202   
203    /**
204    * @param directoryName the name of the directory to initialize (ensure it exists, create the directory)
205    * @param isTemp true if we are initializing a temporary directory.
206    * @param tempOrPermanent a string describing the type of directory, namely "temporary" or "permanent", to aid
207    * logging.
208    * @return the initialized directory as a {@link File} or null if the directory doesn't exist and cannot be created
209    * or if the process doesn't have permission to write to it.
210    */
 
211  129 toggle private File initializeDirectory(final String directoryName, final boolean isTemp, final String tempOrPermanent)
212    {
213  129 final File dir = (isTemp) ? new File(directoryName, TEMP_NAME) : new File(directoryName);
214   
215  129 if (dir.exists()) {
216  84 if (dir.isDirectory() && dir.canWrite()) {
217  83 return initDir(dir, isTemp);
218    }
219   
220    // Not a directory or can't write to it, lets log an error here.
221  1 this.logger.error("Configured {} directory [{}] is {}.", tempOrPermanent, dir.getAbsolutePath(),
222  1 (dir.isDirectory()) ? "not writable" : "not a directory");
223   
224  1 return null;
225   
226    }
227   
228  45 try {
229  45 Files.createDirectories(dir.toPath());
230   
231  45 return initDir(dir, isTemp);
232    } catch (IOException e) {
233  0 this.logger.error("Configured {} directory [{}] could not be created.", tempOrPermanent,
234    dir.getAbsolutePath(), e);
235    }
236   
237  0 return null;
238    }
239   
 
240  128 toggle private File initDir(final File directory, final boolean isTemp)
241    {
242  128 if (isTemp) {
243  73 try {
244  73 FileUtils.cleanDirectory(directory);
245    } catch (IOException e) {
246  0 throw new RuntimeException(String.format("Failed to empty the temporary directory [%s]. "
247    + "Are there files inside of it which XWiki " + "does not have permission to delete?",
248    directory.getAbsolutePath()), e);
249    }
250    }
251   
252  128 return directory;
253    }
254    }