001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.shell.fs;
020
021import java.io.BufferedReader;
022import java.io.File;
023import java.io.FileInputStream;
024import java.io.FileOutputStream;
025import java.io.IOException;
026import java.io.InputStream;
027import java.io.InputStreamReader;
028import java.io.OutputStream;
029import java.util.ArrayList;
030import java.util.List;
031
032import org.nuxeo.shell.Shell;
033import org.nuxeo.shell.ShellFeature;
034import org.nuxeo.shell.fs.cmds.FileSystemCommands;
035
036/**
037 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
038 */
039public class FileSystem implements ShellFeature {
040
041    protected List<File> wdStack;
042
043    public FileSystem() {
044        wdStack = new ArrayList<File>();
045        try {
046            wdStack.add(new File(".").getCanonicalFile());
047        } catch (IOException e) {
048            e.printStackTrace();
049        }
050    }
051
052    public void install(Shell shell) {
053        shell.putContextObject(FileSystem.class, this);
054        shell.addValueAdapter(new FileValueAdapter());
055        shell.addRegistry(FileSystemCommands.INSTANCE);
056    }
057
058    public List<File> getStack() {
059        return wdStack;
060    }
061
062    public File pwd() {
063        return wdStack.get(wdStack.size() - 1);
064    }
065
066    public void cd(File dir) {
067        wdStack.clear();
068        try {
069            wdStack.add(dir.getCanonicalFile());
070        } catch (IOException e) {
071            e.printStackTrace();
072        }
073    }
074
075    public File pushd(File dir) {
076        File lastWd = pwd();
077        try {
078            wdStack.add(dir.getCanonicalFile());
079        } catch (IOException e) {
080            e.printStackTrace();
081        }
082        return lastWd;
083    }
084
085    public File popd() {
086        if (wdStack.size() > 1) {
087            return wdStack.remove(wdStack.size() - 1);
088        }
089        return null;
090    }
091
092    public File resolveFile(String path) {
093        if (path.startsWith("/")) {
094            return new File(path);
095        } else if (path.startsWith("~/")) {
096            return new File(System.getProperty("user.home"), path.substring(2));
097        } else {
098            return new File(pwd(), path);
099        }
100    }
101
102    public static void deleteTree(File dir) {
103        emptyDirectory(dir);
104        dir.delete();
105    }
106
107    public static void emptyDirectory(File dir) {
108        File[] files = dir.listFiles();
109        if (files == null) {
110            return;
111        }
112        int len = files.length;
113        for (int i = 0; i < len; i++) {
114            File file = files[i];
115            if (file.isDirectory()) {
116                deleteTree(file);
117            } else {
118                file.delete();
119            }
120        }
121    }
122
123    public static void copyTree(File src, File dst) throws IOException {
124        if (src.isFile()) {
125            copyFile(src, dst);
126        } else if (src.isDirectory()) {
127            if (dst.exists()) {
128                dst = new File(dst, src.getName());
129                dst.mkdir();
130            } else { // allows renaming dest dir
131                dst.mkdirs();
132            }
133            File[] files = src.listFiles();
134            for (File file : files) {
135                copyTree(file, dst);
136            }
137        }
138    }
139
140    public static void copyFile(File src, File dst) throws IOException {
141        if (dst.isDirectory()) {
142            dst = new File(dst, src.getName());
143        }
144        FileInputStream in = null;
145        FileOutputStream out = new FileOutputStream(dst);
146        try {
147            in = new FileInputStream(src);
148            copy(in, out);
149        } finally {
150            if (in != null) {
151                in.close();
152            }
153            out.close();
154        }
155    }
156
157    public static void copy(InputStream in, OutputStream out) throws IOException {
158        byte[] buffer = createBuffer(in.available());
159        int read;
160        while ((read = in.read(buffer)) != -1) {
161            out.write(buffer, 0, read);
162        }
163    }
164
165    public static String readContent(InputStream in) throws IOException {
166        StringBuilder buf = new StringBuilder();
167        byte[] bytes = new byte[1024 * 16];
168        int r = -1;
169        while ((r = in.read(bytes)) > -1) {
170            buf.append(new String(bytes, 0, r));
171        }
172        return buf.toString();
173    }
174
175    public static List<String> readLines(InputStream in) throws IOException {
176        List<String> lines = new ArrayList<String>();
177        BufferedReader reader = null;
178        try {
179            reader = new BufferedReader(new InputStreamReader(in));
180            String line;
181            while ((line = reader.readLine()) != null) {
182                lines.add(line);
183            }
184        } finally {
185            if (reader != null) {
186                try {
187                    reader.close();
188                } catch (IOException e) {
189                }
190            }
191        }
192        return lines;
193    }
194
195    public static List<String> readAndMergeLines(InputStream in) throws IOException {
196        List<String> lines = readLines(in);
197        ArrayList<String> result = new ArrayList<String>();
198        StringBuilder lastLine = null;
199        for (String line : lines) {
200            line = line.trim();
201            if (line.length() == 0 || line.startsWith("#")) {
202                continue;
203            }
204            if (line.endsWith("\\")) {
205                line = line.substring(0, line.length() - 1);
206                if (lastLine != null) {
207                    lastLine.append(line);
208                } else {
209                    lastLine = new StringBuilder(line);
210                }
211            } else {
212                if (lastLine != null) {
213                    result.add(lastLine.append(line).toString());
214                    lastLine = null;
215                } else {
216                    result.add(line);
217                }
218            }
219        }
220        if (lastLine != null) {
221            result.add(lastLine.toString());
222        }
223        return result;
224    }
225
226    public static String readFile(File file) throws IOException {
227        FileInputStream in = null;
228        try {
229            in = new FileInputStream(file);
230            return read(in);
231        } finally {
232            if (in != null) {
233                in.close();
234            }
235        }
236    }
237
238    public static String read(InputStream in) throws IOException {
239        StringBuilder sb = new StringBuilder();
240        byte[] buffer = createBuffer(in.available());
241        try {
242            int read;
243            while ((read = in.read(buffer)) != -1) {
244                sb.append(new String(buffer, 0, read));
245            }
246        } finally {
247            in.close();
248        }
249        return sb.toString();
250    }
251
252    public static void writeFile(File file, byte[] buf) throws IOException {
253        FileOutputStream fos = null;
254        try {
255            fos = new FileOutputStream(file);
256            fos.write(buf);
257        } finally {
258            if (fos != null) {
259                fos.close();
260            }
261        }
262    }
263
264    public static void writeFile(File file, String buf) throws IOException {
265        writeFile(file, buf.getBytes());
266    }
267
268    private static final int BUFFER_SIZE = 1024 * 64; // 64K
269
270    private static final int MAX_BUFFER_SIZE = 1024 * 1024; // 64K
271
272    private static final int MIN_BUFFER_SIZE = 1024 * 8; // 64K
273
274    private static byte[] createBuffer(int preferredSize) {
275        if (preferredSize < 1) {
276            preferredSize = BUFFER_SIZE;
277        }
278        if (preferredSize > MAX_BUFFER_SIZE) {
279            preferredSize = MAX_BUFFER_SIZE;
280        } else if (preferredSize < MIN_BUFFER_SIZE) {
281            preferredSize = MIN_BUFFER_SIZE;
282        }
283        return new byte[preferredSize];
284    }
285
286}