001: /* Copyright 2005-2006 David N. Welton
002:
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014: */
015:
016: package org.hecl.files;
017:
018: import java.io.File;
019: import java.io.BufferedInputStream;
020: import java.io.BufferedOutputStream;
021: import java.io.FileInputStream;
022: import java.io.FileOutputStream;
023: import java.io.IOException;
024:
025: import java.util.Vector;
026:
027: import org.hecl.HeclException;
028: import org.hecl.Interp;
029: import org.hecl.Thing;
030:
031: /**
032: * <code>HeclFile</code> implements all the filesystem interaction
033: * methods. It's not used in J2ME code, so we can add all we like
034: * here.
035: *
036: * @author <a href="mailto:davidw@dedasys.com">David N. Welton</a>
037: * @version 1.0
038: */
039: public class HeclFile implements org.hecl.HeclModule {
040: /* Keep track of the file currently being run. */
041: public static String currentFile = new String("");
042:
043: /**
044: * <code>changeDir</code> changes where Java thinks the current
045: * directory is, but DOES NOT CHANGE the process' actual working
046: * directory, so this may cause problems if you exec something.
047: *
048: * @param dirname a <code>String</code> value
049: */
050: public static void changeDir(String dirname) {
051: System.setProperty("user.dir", dirname);
052: }
053:
054: /**
055: * <code>readFile</code> reads in a text file, given a filename,
056: * and returns its contents as a StringBuffer. FIXME - we
057: * probably ought to do this better, by making it more configurable.
058: *
059: * @param filename a <code>String</code> value
060: * @return a <code>StringBuffer</code> value
061: * @exception HeclException if an error occurs
062: */
063: public static StringBuffer readFile(String filename)
064: throws HeclException {
065: File realfn = new File(filename).getAbsoluteFile();
066: StringBuffer data = new StringBuffer();
067: BufferedInputStream fis = null;
068:
069: try {
070: fis = new BufferedInputStream(new FileInputStream(realfn));
071: int total;
072: int ch;
073: for (total = 0; (ch = fis.read()) != -1; total++) {
074: data.append((char) ch);
075: }
076: } catch (IOException e) {
077: throw new HeclException("error reading " + realfn + " : "
078: + e.toString());
079: } finally {
080: try {
081: if (fis != null) {
082: fis.close();
083: }
084: } catch (IOException e) {
085: throw new HeclException("error closing " + realfn
086: + " stream : " + e.toString());
087: }
088: }
089: return data;
090: }
091:
092: /**
093: * The <code>writeFile</code> method writes the 'data' String to
094: * the file given by 'filename'.
095: *
096: * @param filename a <code>String</code> value
097: * @param data a <code>String</code> value
098: * @exception HeclException if an error occurs
099: */
100: public static void writeFile(String filename, String data)
101: throws HeclException {
102: File realfn = new File(filename).getAbsoluteFile();
103: BufferedOutputStream fos = null;
104:
105: try {
106: char[] chars = new char[data.length()];
107: data.getChars(0, data.length(), chars, 0);
108:
109: fos = new BufferedOutputStream(new FileOutputStream(realfn));
110: for (int i = 0; i < chars.length; i++) {
111: fos.write(chars[i]);
112: }
113: } catch (IOException e) {
114: throw new HeclException("error writing to " + realfn
115: + " : " + e.toString());
116: } finally {
117: try {
118: if (fos != null) {
119: fos.close();
120: }
121: } catch (IOException e) {
122: throw new HeclException("error closing " + realfn
123: + " stream" + " : " + e.toString());
124: }
125: }
126: }
127:
128: /**
129: * <code>listToFile</code> takes a list like {a b c} and converts
130: * it to a filename such as a/b/c.
131: *
132: * @param filenamelist a <code>Vector</code> value
133: * @return a <code>String</code> value
134: */
135: public static String listToFile(Vector filenamelist) {
136: StringBuffer res = new StringBuffer("");
137: boolean first = true;
138: for (int i = 0; i < filenamelist.size(); i++) {
139: if (first == false) {
140: res.append(File.separator);
141: } else {
142: /* FIXME - broken on windows */
143: if (!filenamelist.elementAt(i).toString().equals("/")) {
144: first = false;
145: }
146: }
147: res.append(filenamelist.elementAt(i).toString());
148: }
149: return res.toString();
150: }
151:
152: /**
153: * <code>fileToList</code> splits a path like /a/b/c into the list
154: * {/ a b c} so that it's easy to manipulate programatically.
155: *
156: * @param filename a <code>String</code> value
157: * @return a <code>Vector</code> value
158: */
159: public static Vector fileToList(String filename) {
160: Vector resultv = new Vector();
161: Vector reversed = new Vector();
162: File fn = new File(filename);
163: File pf = fn.getParentFile();
164:
165: String fns;
166: String pfs;
167:
168: /* Walk through all elements, compare the element with its
169: * parent, and tack the difference onto the Vector. */
170: String ss = null;
171: while (pf != null) {
172: fns = fn.toString();
173: pfs = pf.toString();
174:
175: ss = fns.substring(pfs.length(), fns.length());
176: /* The 'diff' operation leaves path components with a
177: * leading slash. Remove it. */
178: if (ss.charAt(0) == File.separatorChar) {
179: ss = ss.substring(1, ss.length());
180: }
181: reversed.addElement(new Thing(ss));
182: fn = pf;
183: pf = pf.getParentFile();
184: }
185: reversed.addElement(new Thing(fn.toString()));
186:
187: /* Ok, now we correct the order of the list by reversing
188: * it. */
189: int j = 0;
190: for (int i = reversed.size() - 1; i >= 0; i--) {
191: Thing t = (Thing) reversed.elementAt(i);
192: resultv.addElement(t);
193: j++;
194: }
195:
196: return resultv;
197: }
198:
199: /**
200: * The <code>sourceFile</code> method is the equivalent of the
201: * "source" command.
202: *
203: * @param interp an <code>Interp</code> value
204: * @param filename a <code>String</code> value
205: * @exception HeclException if an error occurs
206: */
207: public static void sourceFile(Interp interp, String filename)
208: throws HeclException {
209: File realfn = new File(filename).getAbsoluteFile();
210: currentFile = realfn.toString();
211: try {
212: interp.eval(new Thing(new String(readFile(filename)
213: .toString().getBytes("ISO-8859-1"))));
214: } catch (HeclException e) {
215: throw e;
216: } catch (Exception e) {
217: throw new HeclException("Unexpected error: " + e);
218: }
219: }
220:
221: public void loadModule(Interp interp) throws HeclException {
222: FileCmds.load(interp);
223: }
224:
225: public void unloadModule(Interp interp) throws HeclException {
226: FileCmds.unload(interp);
227: }
228: }
|