OSDN Git Service

Add new source files
[armadillo/armadillo1.git] / src / jp / sfjp / armadillo / archive / cab / CabOutputStream.java
1 package jp.sfjp.armadillo.archive.cab;
2
3 import java.io.*;
4 import java.util.*;
5 import jp.sfjp.armadillo.archive.*;
6
7 public final class CabOutputStream extends ArchiveOutputStream {
8
9     private final CabHeader header;
10     private final List<CabCfFolder> folders;
11     private CabCfFolder currentFolder;
12
13     public CabOutputStream(OutputStream out) {
14         super(out);
15         this.header = new CabHeader();
16         this.folders = new ArrayList<CabCfFolder>();
17         this.currentFolder = new CabCfFolder("*");
18     }
19
20     public void putNextEntry(CabEntry entry) throws IOException {
21         ensureOpen();
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;
29         }
30         else {
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);
40         }
41     }
42
43     void changeFolder(String name) throws IOException {
44         currentFolder.close();
45         CabCfFolder folder = new CabCfFolder(normalizePath(name, true));
46         folder.method = 1;
47         folders.add(folder);
48         currentFolder = folder;
49         frontStream = currentFolder.bos;
50     }
51
52     void closeFolder(CabCfFolder folder) throws IOException {
53         ensureOpen();
54         flush();
55         folder.close();
56         frontStream = out;
57     }
58
59     String getParentPath(CabEntry entry) {
60         final String path = normalizePath(entry.getName(), false);
61         return path.replaceFirst("/[^/]+$", "/");
62     }
63
64     static String normalizePath(String path, boolean isDirectory) {
65         String s = path.replace('\\', '/');
66         if (isDirectory && !s.endsWith("/"))
67             s += "/";
68         return s;
69     }
70
71     public void closeEntry() throws IOException {
72         // do nothing
73     }
74
75     @Override
76     public void close() throws IOException {
77         try {
78             currentFolder.close();
79             header.write(out, folders);
80             for (CabCfFolder folder : folders)
81                 folder.writeCfDataInto(out, header);
82             out.flush();
83             flush();
84             folders.clear();
85         }
86         finally {
87             super.close();
88         }
89     }
90
91 }