/*
  Copyright (C) 2007 Helge Hess

  This file is part of JOPE.

  JOPE is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the
  Free Software Foundation; either version 2, or (at your option) any
  later version.

  JOPE is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with JOPE; see the file COPYING.  If not, write to the
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
*/
package org.opengroupware.jope.ofs.fs;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

import org.opengroupware.jope.foundation.UString;

public class OFSHostFileManager extends OFSFileManager {

  protected File      rootFile;
  protected Exception lastException;
  
  public OFSHostFileManager(File _root) {
    this.rootFile = _root;
  }
  
  /* hierarchy */

  public String[] childNamesAtPath(String[] _path) {
    File file = this.fileForPath(_path);
    if (file == null) return null;
    if (!file.isDirectory()) return null;
    
    String[] names = file.list();
    
    return names;
  }
  
  public File fileForPath(String[] _path) {
    /* Note: we do no special name processing here! (eg '.', '..', '/', '~') */
    if (_path == null) return this.rootFile; /* Note: do not return null! */
    
    int len = _path.length;
    if (len == 0) return this.rootFile;
    
    File cur = this.rootFile;
    for (int i = 0; i < len; i++) {
      /* Note: the File class *does* special name processing, so we need to
       *       perform some validation.
       */
      if (!this.isValidFilename(_path[i])) {
        log().warn("got path which contains invalid names: " + 
            UString.componentsJoinedByString(_path, " / "));
      }
      cur = new File(cur, _path[i]);
    }
    
    return cur;
  }
  
  /* name validation */
  
  public boolean isValidFilename(String _name) {
    /* Note: we allow no escaping of special chars ... */
    if (_name == null) return false;
    
    int nameLen = _name.length();
    if (nameLen == 0) return false;
    
    char c0 = _name.charAt(0);
    if (c0 == '/')
      return false;
    if (c0 == '.') {
      if (nameLen == 1) return false; /* single dots not allowed */
      if (nameLen == 2 && _name.charAt(1) == '.') return false; /* .. */
    }
    
    /* filename may not contain a slash (TODO: Windows?) */
    return _name.indexOf('/') == -1;
  }

  /* info */
  
  public IOFSFileInfo fileInfoForPath(String[] _path) {
    File file = this.fileForPath(_path);
    if (file == null) return null;
    
    return new OFSHostFileInfo(_path, file);
  }
  
  /* file contents */
  
  public InputStream openStreamOnPath(String[] _path) {
    File file = this.fileForPath(_path);
    if (file == null) return null;
    
    FileInputStream in;
    try {
      in = new FileInputStream(file);
    }
    catch (FileNotFoundException e) {
      log().warn("could not open file: " + file);
      return null;
    }
    
    return in;
  }
  
  /* description */

  @Override
  public void appendAttributesToDescription(StringBuilder _d) {
    super.appendAttributesToDescription(_d);
    
    _d.append(" root=" + this.rootFile);
    if (this.lastException != null)
      _d.append(" error=" + this.lastException);
  }
}
