001    /*
002     * Copyright (C) 2010 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.vfs;
021    
022    import org.crsh.util.IO;
023    import org.slf4j.Logger;
024    import org.slf4j.LoggerFactory;
025    
026    import java.io.IOException;
027    import java.io.InputStream;
028    import java.net.URL;
029    import java.net.URLConnection;
030    import java.util.ArrayList;
031    import java.util.Collections;
032    import java.util.LinkedHashMap;
033    import java.util.LinkedList;
034    import java.util.List;
035    
036    /**
037     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
038     * @version $Revision$
039     */
040    public final class File {
041    
042      /** . */
043      private static final Logger log = LoggerFactory.getLogger(Resource.class);
044    
045      /** . */
046      private final FS fs;
047    
048      /** . */
049      private final Path path;
050    
051      /** . */
052      private LinkedList<Handle<?>> handles;
053    
054      /** . */
055      private LinkedHashMap<Key, File> children;
056    
057      public File(FS fs, Path path) {
058        this.fs = fs;
059        this.path = path;
060        this.handles = null;
061      }
062    
063      public Path getPath() {
064        return path;
065      }
066    
067      public boolean isDir() {
068        return path.isDir();
069      }
070    
071      public String getName() {
072        return path.getName();
073      }
074    
075      public Resource getResource() throws IOException {
076        try {
077          URL url = getURL();
078          if (url == null) {
079            log.warn("Could not obtain resource " + path);
080          } else {
081            URLConnection conn = url.openConnection();
082            long timestamp = conn.getLastModified();
083            InputStream in = url.openStream();
084            String content = IO.readAsUTF8(in);
085            return new Resource(content, timestamp, url);
086          }
087        }
088        catch (IOException e) {
089          log.warn("Could not retrieve resource " + path, e);
090        }
091        return null;
092      }
093    
094      public URL getURL() throws IOException {
095        if (path.isDir()) {
096          throw new IllegalStateException("Cannot get url of a dir");
097        }
098        Handle handle = getHandles().peekFirst();
099        return handle != null ? handle.url() : null;
100    
101      }
102    
103      public Iterable<URL> getURLs() throws IOException {
104        if (path.isDir()) {
105          throw new IllegalStateException("Cannot get url of a dir");
106        }
107        List<URL> urls = Collections.emptyList();
108        for (Handle handle : getHandles()) {
109          if (urls.isEmpty()) {
110            urls = new ArrayList<URL>();
111          }
112          URL url = handle.url();
113          urls.add(url);
114        }
115        return urls;
116      }
117    
118      public File child(String name, boolean dir) throws IOException {
119        if (children == null) {
120          children();
121        }
122        return children.get(new Key(name, dir));
123      }
124    
125      public Iterable<File> children() throws IOException {
126        if (children == null) {
127          LinkedHashMap<Key, File> children = new LinkedHashMap<Key, File>();
128          for (Handle<?> handle : getHandles()) {
129            for (Handle<?> childHandle : handle.children()) {
130              File child = children.get(childHandle.key);
131              if (child == null) {
132                child = new File(fs, Path.get(path, childHandle.key.name, childHandle.key.dir));
133                children.put(childHandle.key, child);
134              }
135              if (child.handles == null) {
136                child.handles = new LinkedList<Handle<?>>();
137              }
138              child.handles.add(childHandle);
139            }
140          }
141          this.children = children;
142        }
143        return children.values();
144      }
145    
146      LinkedList<Handle<?>> getHandles() {
147        if (handles == null) {
148          LinkedList<Handle<?>> handles = new LinkedList<Handle<?>>();
149          for (Mount<?> mount : fs.mounts) {
150            Handle<?> handle = null;
151            try {
152              handle = mount.getHandle(path);
153            }
154            catch (IOException e) {
155              e.printStackTrace();
156            }
157            if (handle != null) {
158              handles.add(handle);
159            }
160          }
161          this.handles = handles;
162        }
163        return handles;
164      }
165    
166      @Override
167      public String toString() {
168        return "File[path=" + path.getValue() + "]";
169      }
170    }