1 package jp.sfjp.armadillo.archive.cab;
5 import jp.sfjp.armadillo.archive.*;
7 public final class CabOutputStream extends ArchiveOutputStream {
9 private final CabHeader header;
10 private final List<CabCfFolder> folders;
11 private CabCfFolder currentFolder;
13 public CabOutputStream(OutputStream out) {
15 this.header = new CabHeader();
16 this.folders = new ArrayList<CabCfFolder>();
17 this.currentFolder = new CabCfFolder("*");
20 public void putNextEntry(CabEntry entry) throws IOException {
22 final String name = entry.getName();
23 if (name.length() > 255)
24 throw new IllegalArgumentException("too long name: " + name);
25 if (entry.isDirectory()) {
26 CabCfFolder folder = (CabCfFolder)entry;
27 if (folders.isEmpty() || folder.method != currentFolder.method)
28 currentFolder.method = folder.method;
31 if (folders.isEmpty())
32 changeFolder(getParentPath(entry));
33 CabCfFile file = (CabCfFile)entry;
34 final int folderCount = folders.size() - 1;
35 assert folderCount <= Short.MAX_VALUE;
36 file.folderIndex = (short)folderCount;
37 file.uncompressedOffset = currentFolder.offset;
38 currentFolder.offset += file.uncompressedSize;
39 currentFolder.add(file);
43 void changeFolder(String name) throws IOException {
44 currentFolder.close();
45 CabCfFolder folder = new CabCfFolder(normalizePath(name, true));
48 currentFolder = folder;
49 frontStream = currentFolder.bos;
52 void closeFolder(CabCfFolder folder) throws IOException {
59 String getParentPath(CabEntry entry) {
60 final String path = normalizePath(entry.getName(), false);
61 return path.replaceFirst("/[^/]+$", "/");
64 static String normalizePath(String path, boolean isDirectory) {
65 String s = path.replace('\\', '/');
66 if (isDirectory && !s.endsWith("/"))
71 public void closeEntry() throws IOException {
76 public void close() throws IOException {
78 currentFolder.close();
79 header.write(out, folders);
80 for (CabCfFolder folder : folders)
81 folder.writeCfDataInto(out, header);