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