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