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