001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package acl_data;
028:
029: import java.util.Vector;
030: import java.util.Hashtable;
031: import java.io.ByteArrayOutputStream;
032: import java.io.DataOutputStream;
033: import java.io.IOException;
034:
035: /**
036: * Represents WIM file system.
037: */
038: public class FileSystem {
039:
040: /** File attribute constant. */
041: static final int DIR = 1;
042: /** File attribute constant. */
043: static final int PIN = 3;
044: /** File attribute constant. */
045: static final int PrK = 4;
046: /** File attribute constant. */
047: static final int WIM = 9;
048: /** File attribute constant. */
049: static final int READ = 16;
050: /** File attribute constant. */
051: static final int UPDATE = 48;
052: /** File attribute constant. */
053: static final int EMPTY = 64;
054:
055: /** Root directory for this file system. */
056: CardFile root;
057: /** Base directory for WIM files. */
058: CardFile base;
059:
060: /** Hash table used to determine file offsets in resuting data. */
061: Hashtable labels = new Hashtable(3);
062:
063: /**
064: * Constructor.
065: * @param path root directory for this file system
066: */
067: public FileSystem(short[] path) {
068:
069: root = new CardFile(path[0], DIR);
070: base = root;
071:
072: for (int i = 1; i < path.length; i++) {
073:
074: CardFile f = new CardFile(path[i], DIR);
075: base.addFile(f);
076: base = f;
077: }
078: base.type = WIM;
079: }
080:
081: /**
082: * Adds a new file to the file system.
083: * @param path file path
084: * @param type file type
085: * @param data file body
086: */
087: public void addFile(short[] path, int type, byte[] data) {
088:
089: if (path == null) {
090: return;
091: }
092: addFile(path, type, data, null);
093: }
094:
095: /**
096: * Adds a new file to the file system.
097: * @param path file path
098: * @param type file type
099: * @param data file body
100: * @param label label that can be used to retrieve file offset
101: */
102: public void addFile(short[] path, int type, byte[] data,
103: String label) {
104:
105: if (path == null) {
106: return;
107: }
108:
109: CardFile top;
110:
111: if (path.length > 1) {
112: if (path[0] == 0x3fff) {
113: top = base;
114: } else if (path[0] == root.id) {
115: top = root;
116: } else {
117: throw new IllegalArgumentException("Invalid path");
118: }
119:
120: for (int i = 1; i < path.length - 1; i++) {
121:
122: CardFile f = top.getFile(path[i]);
123: if (f == null) {
124: f = new CardFile(path[i], DIR);
125: top.addFile(f);
126: }
127: if (f.type != DIR) {
128: throw new IllegalArgumentException("Invalid path 1");
129: }
130: top = f;
131: }
132: } else {
133: top = base;
134: }
135:
136: CardFile f = new CardFile(path[path.length - 1], type);
137: f.setData(data);
138: top.addFile(f);
139:
140: if (label != null) {
141: labels.put(label, f);
142: }
143: }
144:
145: /**
146: * Returs file offset in resulting data array.
147: * @param label file label
148: * @return offset value
149: */
150: public int getOffset(String label) {
151: CardFile c = (CardFile) labels.get(label);
152: if (c == null) {
153: System.out.println("Warning: label not found: " + label);
154: return -32768;
155: }
156: return c.offset;
157: }
158:
159: /**
160: * Returns binary representation of this file system.
161: * @return binary representation of this file system
162: * @throws IOException if I/O error occurs
163: */
164: public byte[] getEncoded() throws IOException {
165:
166: ByteArrayOutputStream baos = new ByteArrayOutputStream();
167: DataOutputStream out = new DataOutputStream(baos);
168:
169: root.write(out);
170: return baos.toByteArray();
171: }
172:
173: /**
174: * This class represents card file.
175: */
176: class CardFile {
177:
178: /** File identifier. */
179: int id;
180:
181: /** File type. */
182: int type;
183:
184: /** File body. */
185: byte[] data;
186:
187: /** Files that this file contains (if any). */
188: Vector files;
189:
190: /** File offset in binary representation of the file system. */
191: int offset;
192:
193: /**
194: * Constructor.
195: * @param id file identifier
196: * @param type file type
197: */
198: CardFile(int id, int type) {
199:
200: this .id = id;
201: this .type = type;
202: files = new Vector();
203: }
204:
205: /**
206: * Set file data.
207: * @param data file data
208: */
209: void setData(byte[] data) {
210: this .data = data;
211: }
212:
213: /**
214: * Add file to this DF.
215: * @param f the file
216: */
217: void addFile(CardFile f) {
218: files.add(f);
219: }
220:
221: /**
222: * Returns file with this ID in this DF or null.
223: * @param id file identifier
224: * @return file with this ID in this DF or null
225: */
226: CardFile getFile(int id) {
227:
228: CardFile f;
229:
230: for (int i = 0; i < files.size(); i++) {
231:
232: f = (CardFile) files.elementAt(i);
233: if (f.id == id) {
234: return f;
235: }
236: }
237: return null;
238: }
239:
240: /**
241: * Writes binary representation of this file into the stream.
242: * @param out output stream
243: * @throws IOException if I/O error occurs
244: */
245: void write(DataOutputStream out) throws IOException {
246:
247: out.writeShort(id);
248: out.writeByte(type);
249: if ((type & DIR) == 0) {
250: out.writeShort(data.length);
251: offset = out.size();
252:
253: if ((type & EMPTY) == 0) {
254: out.write(data);
255: } else {
256: int i = data.length - 1;
257: while (i > -1 && data[i] == 0) {
258: i--;
259: }
260: i++;
261: out.writeShort(i);
262: out.write(data, 0, i);
263: }
264: } else {
265: out.writeShort(files.size());
266: for (int i = 0; i < files.size(); i++) {
267:
268: CardFile f = (CardFile) files.elementAt(i);
269: f.write(out);
270: }
271: }
272: }
273: }
274: }
|