001/*
002 *                    PDB web development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 *
015 * Created on Jul 8, 2009
016 * Created by ap3
017 *
018 */
019
020package org.biojava.nbio.structure.align.util;
021
022import org.biojava.nbio.structure.align.ce.StartupParameters;
023import org.biojava.nbio.structure.io.LocalPDBDirectory.FetchBehavior;
024import org.biojava.nbio.structure.io.LocalPDBDirectory.ObsoleteBehavior;
025import org.biojava.nbio.core.util.PrettyXMLWriter;
026import org.biojava.nbio.core.util.XMLWriter;
027import org.slf4j.Logger;
028import org.slf4j.LoggerFactory;
029
030import java.io.File;
031import java.io.IOException;
032import java.io.PrintWriter;
033import java.util.Map;
034
035
036/** A container to persist config to the file system
037 *
038 * @author Andreas Prlic
039 *
040 */
041public class UserConfiguration
042{
043
044        private static final Logger logger = LoggerFactory.getLogger(UserConfiguration.class);
045
046        public static final String PDB_FORMAT   = "PDB";
047        public static final String MMCIF_FORMAT = "mmCif";
048
049        public static final String TMP_DIR = "java.io.tmpdir";
050
051        public static final String PDB_DIR   = "PDB_DIR";
052        public static final String PDB_CACHE_DIR = "PDB_CACHE_DIR";
053
054        public static final String lineSplit = System.getProperty("file.separator");
055
056        private String pdbFilePath;
057        private String cacheFilePath;
058
059        private FetchBehavior fetchBehavior;
060        private ObsoleteBehavior obsoleteBehavior;
061
062        private String fileFormat;
063
064
065
066        /**
067         * Default UserConfiguration:
068         * <ul>
069         * <li>split directory</li>
070         * <li>autofetch files</li>
071         * <li>default download location. This is the first specified of:
072         *      <ol><li>{@value #PDB_DIR} system property (for instance, -D{@value #PDB_DIR}=/tmp)</li>
073         *   <li>{@value #PDB_DIR} environment variable</li>
074         *   <li>System temp directory (java.io.tmpdir property)</li>
075         *   </ol>
076         *   if the provided path is not a directory then
077         *   the system's temp directory is used. A non-writable path is allowed,
078         *   only a warning will be logged.
079         * </li>
080         * <li>default cache location. This is the first specified of:
081         *      <ol><li>{@value #PDB_CACHE_DIR} system property (for instance, -D{@value #PDB_CACHE_DIR}=/tmp)</li>
082         *   <li>{@value #PDB_CACHE_DIR} environment variable</li>
083         *   <li>the value set for {@value #PDB_DIR}</li>
084         *   </ol>
085         *   if the provided path is not a directory or is not writable then
086         *   the system's temp directory is used.
087         * </li>
088         * </ul>
089         */
090        public UserConfiguration(){
091                fetchBehavior = FetchBehavior.DEFAULT;
092                obsoleteBehavior = ObsoleteBehavior.DEFAULT;
093
094                pdbFilePath = initPdbFilePath();
095                // note that in initCacheFilePath, we set to the provided one (if readable) or to the same as pdbFilePath
096                cacheFilePath = initCacheFilePath();
097
098                fileFormat = MMCIF_FORMAT;
099        }
100
101        private String initPdbFilePath() {
102
103                String path = null;
104
105                String propertyName = PDB_DIR;
106
107                String userProvidedDir = System.getProperty(propertyName);
108
109                if ( userProvidedDir != null && !userProvidedDir.trim().isEmpty()) {
110
111                        path = userProvidedDir;
112                        logger.debug("Read PDB dir from system property {}: {}", propertyName, path);
113                        File f = new File(path);
114                        if (!f.isDirectory()) {
115                                logger.warn(
116                                                "Provided path {} (with system property {}) is not a directory. Using system's temp directory instead {}",
117                                                path, propertyName, System.getProperty(TMP_DIR));
118                                path = System.getProperty(TMP_DIR);
119                        } else if (!f.canWrite()) {
120                                logger.warn(
121                                                "Provided path {} (with system property {}) is not writable. Will not be able to write cached files.",
122                                                path, propertyName);
123                                // we don't require the PDB_DIR to be writable, so that it can be used with a pre-rsynced dir
124                                // thus if not writable, we only warn and go ahead using it
125                        }
126
127
128                } else {
129                        Map<String,String> env = System.getenv();
130
131                        if( env.containsKey(propertyName) && !env.get(propertyName).trim().isEmpty()) {
132                                path = env.get(propertyName);
133                                logger.debug("Read dir from environment variable {}: {}", propertyName, path);
134
135                                File f = new File(path);
136                                if (!f.isDirectory()) {
137                                        logger.warn(
138                                                        "Provided path {} (with environment variable {}) is not a directory. Using system's temp directory instead {}",
139                                                        path, propertyName, System.getProperty(TMP_DIR));
140                                        path = System.getProperty(TMP_DIR);
141                                } else if (!f.canWrite()) {
142                                        logger.warn(
143                                                        "Provided path {} (with environment variable {}) is not writable. Will not be able to write cached files",
144                                                        path, propertyName);
145                                        // we don't require the PDB_DIR to be writable, so that it can be used with a pre-rsynced dir
146                                        // thus if not writable, we only warn and go ahead using it
147                                }
148
149                        } else {
150                                path = System.getProperty(TMP_DIR);
151                                logger.warn("Could not read dir from system property {} or environment variable {}, "
152                                                + "using system's temp directory {}",
153                                                propertyName, propertyName, path);
154
155                                System.setProperty(propertyName,path);
156                        }
157                }
158
159                if ( ! path.endsWith(lineSplit) )
160                        path = path + lineSplit;
161
162                return path;
163
164        }
165
166        private String initCacheFilePath() {
167
168                String path = null;
169
170                String propertyName = PDB_CACHE_DIR;
171
172                String userProvidedDir = System.getProperty(propertyName);
173
174                if ( userProvidedDir != null ) {
175
176                        path = userProvidedDir;
177                        logger.debug("Read cache dir from system property {}: {}", propertyName, path);
178                        File f = new File(path);
179                        if (!f.isDirectory()) {
180                                logger.warn(
181                                                "Provided path {} (with system property {}) is not a directory. Using system's temp directory instead {}",
182                                                path, propertyName, System.getProperty(TMP_DIR));
183                                path = System.getProperty(TMP_DIR);
184                        } else if (!f.canWrite()) {
185                                logger.warn(
186                                                "Provided path {} (with system property {}) is not writable. Using system's temp directory instead {}",
187                                                path, propertyName, System.getProperty(TMP_DIR));
188                                path = System.getProperty(TMP_DIR);
189                                System.setProperty(propertyName,path);
190                        }
191
192
193                } else {
194                        Map<String,String> env = System.getenv();
195
196                        if( env.containsKey(propertyName)) {
197                                path = env.get(propertyName);
198                                logger.debug("Read dir from environment variable {}: {}", propertyName, path);
199
200                                File f = new File(path);
201                                if (!f.isDirectory()) {
202                                        logger.warn(
203                                                        "Provided path {} (with environment variable {}) is not a directory. Using system's temp directory instead {}",
204                                                        path, propertyName, System.getProperty(TMP_DIR));
205                                        path = System.getProperty(TMP_DIR);
206                                } else if (!f.canWrite()) {
207                                        logger.warn(
208                                                        "Provided path {} (with environment variable {}) is not writable. Using system's temp directory instead {}",
209                                                        path, propertyName, System.getProperty(TMP_DIR));
210                                        path = System.getProperty(TMP_DIR);
211                                }
212
213                        } else {
214                                // NOTE in case of not provided, then it is set to same as pdbFilePath
215                                // as PDB_DIR is not checked for being writable, we have to do that check here in case
216                                if (new File(pdbFilePath).canWrite()){
217                                        path = pdbFilePath;
218                                        logger.info("Could not read cache dir from system property {} or environment variable {}, "
219                                                        + "using PDB directory instead {}",
220                                                        propertyName, propertyName, path);
221                                        System.setProperty(propertyName,path);
222
223                                } else {
224                                        path = System.getProperty(TMP_DIR);
225                                        logger.warn("Could not read cache dir from system property {} or environment variable {}, "
226                                                        + "and PDB directory {} is not writable. Using system's temp directory instead {}",
227                                                        propertyName, propertyName, pdbFilePath, path);
228                                        System.setProperty(propertyName,path);
229
230                                }
231                        }
232                }
233
234                if ( ! path.endsWith(lineSplit) )
235                        path = path + lineSplit;
236
237                return path;
238
239        }
240
241        public String getPdbFilePath()
242        {
243                return pdbFilePath;
244        }
245
246        public void setPdbFilePath(String pdbFilePath)
247        {
248                this.pdbFilePath = pdbFilePath;
249        }
250
251        public String getCacheFilePath() {
252                return cacheFilePath;
253        }
254
255        public void setCacheFilePath(String cacheFilePath) {
256                this.cacheFilePath = cacheFilePath;
257        }
258
259        /**
260         * @deprecated Use {@link #getFetchBehavior()}
261         */
262        @Deprecated
263        public boolean getAutoFetch() {
264                return fetchBehavior != FetchBehavior.LOCAL_ONLY;
265        }
266
267        /**
268         * @deprecated Use {@link #getFetchBehavior()}
269         */
270        @Deprecated
271        public void setAutoFetch(boolean autoFetch) {
272                if(autoFetch) {
273                        setFetchBehavior(FetchBehavior.DEFAULT);
274                } else {
275                        setFetchBehavior(FetchBehavior.LOCAL_ONLY);
276                }
277        }
278
279        public FetchBehavior getFetchBehavior() {
280                return fetchBehavior;
281        }
282
283        public void setFetchBehavior(FetchBehavior fetchBehavior) {
284                this.fetchBehavior = fetchBehavior;
285        }
286
287        public ObsoleteBehavior getObsoleteBehavior() {
288                return obsoleteBehavior;
289        }
290
291        public void setObsoleteBehavior(ObsoleteBehavior obsoleteBehavior) {
292                this.obsoleteBehavior = obsoleteBehavior;
293        }
294
295        /** convert Configuration to an XML file so it can be serialized
296         *
297         * @param pw
298         * @return XMLWriter
299         * @throws IOException
300         */
301        public XMLWriter toXML(PrintWriter pw)
302                        throws IOException
303                        {
304
305                XMLWriter     xw = new PrettyXMLWriter( pw);
306
307                toXML(xw);
308                return xw ;
309                        }
310
311
312        /** convert Configuration to an XML file so it can be serialized
313         * add to an already existing xml file.
314         *
315         * @param xw the XML writer to use
316         * @return the writer again
317         * @throws IOException
318         * @see org.biojava.nbio.structure.align.webstart.ConfigXMLHandler
319         */
320
321        public XMLWriter toXML(XMLWriter xw)
322                        throws IOException
323                        {
324                xw.printRaw("<?xml version='1.0' standalone='no' ?>");
325                //xw.printRaw("<!DOCTYPE " + XML_CONTENT_TYPE + " SYSTEM '" + XML_DTD + "' >");
326                xw.openTag("JFatCatConfig");
327
328                xw.openTag("PDBFILEPATH");
329                // we don;t serialize the tempdir...
330                String tempdir = System.getProperty(TMP_DIR);
331                if (! pdbFilePath.equals(tempdir))
332                        xw.attribute("path", pdbFilePath);
333
334                xw.attribute("fetchBehavior", fetchBehavior+"");
335                xw.attribute("obsoleteBehavior", obsoleteBehavior+"");
336                xw.attribute("fileFormat", fileFormat);
337                xw.closeTag("PDBFILEPATH");
338
339                xw.closeTag("JFatCatConfig");
340                return xw ;
341
342                        }
343
344        public static UserConfiguration fromStartupParams(StartupParameters params) {
345                UserConfiguration config = new UserConfiguration();
346                config.setPdbFilePath(params.getPdbFilePath());
347                config.setAutoFetch(params.isAutoFetch());
348                // TODO support MMCif Files
349                config.setFileFormat(UserConfiguration.PDB_FORMAT);
350                return config;
351        }
352
353        public void setFileFormat (String fileFormat){
354                this.fileFormat = fileFormat;
355        }
356
357        public String getFileFormat()
358        {
359                return fileFormat;
360        }
361
362
363
364
365
366
367}