OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 17 | Rev 177 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.utils;
15
 
16
import java.io.BufferedInputStream;
17
import java.io.BufferedOutputStream;
18
import java.io.ByteArrayInputStream;
142 ilm 19
import java.io.ByteArrayOutputStream;
17 ilm 20
import java.io.File;
21
import java.io.FileInputStream;
22
import java.io.FileNotFoundException;
23
import java.io.FileOutputStream;
24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.io.OutputStream;
142 ilm 27
import java.nio.ByteBuffer;
17 ilm 28
import java.util.Enumeration;
29
import java.util.Set;
30
import java.util.zip.CRC32;
142 ilm 31
import java.util.zip.DeflaterOutputStream;
32
import java.util.zip.InflaterInputStream;
17 ilm 33
import java.util.zip.ZipEntry;
34
import java.util.zip.ZipException;
35
import java.util.zip.ZipOutputStream;
36
 
37
/**
38
 * Permet d'écrire dans un fichier zip.
39
 *
40
 * @author ILM Informatique
41
 * @see org.openconcerto.utils.Unzip
42
 */
43
public class Zip {
44
 
142 ilm 45
    static public byte[] deflate(final String s) throws IOException {
46
        return deflate(s.getBytes(StringUtils.UTF8));
47
    }
48
 
49
    static public byte[] deflate(final byte[] b) throws IOException {
50
        final ByteArrayOutputStream bOut = new ByteArrayOutputStream();
51
        final DeflaterOutputStream out = new DeflaterOutputStream(bOut);
52
        out.write(b);
53
        out.close();
54
        return bOut.toByteArray();
55
    }
56
 
57
    static public ByteBuffer deflateToBuffer(final String s) throws IOException {
58
        return ByteBuffer.wrap(deflate(s));
59
    }
60
 
61
    static public String inflateToString(final ByteBuffer payload) throws IOException {
62
        return inflateToString(payload, payload.remaining());
63
    }
64
 
65
    static public String inflateToString(final ByteBuffer payload, final int length) throws IOException {
66
        final byte[] b = new byte[length];
67
        payload.get(b);
68
        return inflateToString(b);
69
    }
70
 
71
    static public String inflateToString(final byte[] b) throws IOException {
72
        return new String(inflate(b), StringUtils.UTF8);
73
    }
74
 
75
    static public byte[] inflate(final byte[] b) throws IOException {
76
        final InflaterInputStream in = new InflaterInputStream(new ByteArrayInputStream(b));
77
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
78
        StreamUtils.copy(in, out);
79
        out.close();
80
        return out.toByteArray();
81
    }
82
 
17 ilm 83
    /**
84
     * Copie de from dans to seulement les entrées dont le nom n'est pas dans
85
     * <code>excludedEntries</code>.
86
     *
87
     * @param from le zip source.
88
     * @param excludedEntries les noms des entrées à exclure.
89
     * @param to le zip de destination, s'il existe déjà les entrées de from seront ajoutées aux
90
     *        existantes.
91
     * @return le fichier zip dest.
92
     * @throws ZipException
93
     * @throws IOException
94
     */
142 ilm 95
    static public Zip createFrom(File from, File to, Set<String> excludedEntries) throws ZipException, IOException {
17 ilm 96
        Unzip unz = new Unzip(from);
97
        Zip res = new Zip(to);
142 ilm 98
        final Enumeration<? extends ZipEntry> en = unz.entries();
17 ilm 99
        while (en.hasMoreElements()) {
142 ilm 100
            final ZipEntry entry = en.nextElement();
17 ilm 101
            if (!excludedEntries.contains(entry.getName())) {
102
                res.zip(entry.getName(), unz.getInputStream(entry));
103
            }
104
        }
105
        unz.close();
106
        return res;
107
    }
108
 
109
    /**
110
     * Efface les entrées spécifées de src. Si dest existe, il sera ecrasé.
111
     *
112
     * @param src le zip source.
113
     * @param entriesName les noms des entrées à effacer.
114
     * @param dest le zip de destination.
115
     * @throws ZipException
116
     * @throws IOException
117
     */
142 ilm 118
    static public void delete(File src, Set<String> entriesName, File dest) throws ZipException, IOException {
17 ilm 119
        if (dest.exists())
120
            dest.delete();
121
        createFrom(src, dest, entriesName).close();
122
    }
123
 
124
    // *** Instance
125
 
126
    private final OutputStream outstream;
127
    private ZipOutputStream zos;
128
    // is an entry open, ie addEntry() has been called but closeEntry() not yet
129
    private boolean entryOpen;
130
 
131
    /**
132
     * Construit un fichier zip. ATTN Le fichier passé sera écrasé lors de la première écriture.
133
     *
134
     * @param f le fichier dans lequel sauver, peut ne pas exister.
135
     * @throws FileNotFoundException if f cannot be written to.
136
     */
137
    public Zip(File f) throws FileNotFoundException {
138
        this(new FileOutputStream(f));
139
    }
140
 
141
    /**
142
     * Construit un fichier zip.
143
     *
144
     * @param out un stream dans lequel écrire.
145
     */
146
    public Zip(OutputStream out) {
147
        this.outstream = out;
148
        this.zos = null;
149
        this.entryOpen = false;
150
    }
151
 
152
    public synchronized void close() throws IOException {
153
        if (this.zos != null) {
154
            // ferme aussi le FileOutputStream
155
            this.zos.close();
156
        }
157
    }
158
 
159
    // *** Ecriture
160
 
161
    private synchronized ZipOutputStream getOutStream() {
162
        if (this.zos == null) {
163
            this.zos = new ZipOutputStream(this.outstream);
164
        }
165
        return this.zos;
166
    }
167
 
168
    /**
169
     * Ajoute newFile dans ce fichier. Il sera enregistré dans le zip directement à la racine.
170
     *
171
     * @param newFile le fichier à ajouter.
172
     * @throws IOException si le fichier ne peut etre zippé.
173
     */
174
    public void zip(File newFile) throws IOException {
175
        // on ne garde que la derniere partie du chemin
176
        this.zip(newFile.getName(), new BufferedInputStream(new FileInputStream(newFile)));
177
    }
178
 
179
    /**
180
     * Zippe le contenu de <code>in</code>.
181
     *
182
     * @param name le nom de l'entrée.
183
     * @param in l'ajout.
184
     * @throws IOException si in ne peut etre zippé.
185
     */
186
    public synchronized void zip(String name, InputStream in) throws IOException {
187
        this.putNextEntry(name);
188
 
189
        byte b[] = new byte[512];
190
        int len = 0;
191
        while ((len = in.read(b)) != -1) {
192
            this.getOutStream().write(b, 0, len);
193
        }
194
 
195
        this.closeEntry();
196
    }
197
 
198
    public void zip(String name, byte[] in, final boolean compressed) throws IOException {
199
        // don't make #zip(String, InputStream) call this method, it would require to read the
200
        // entire stream into memory
201
        if (compressed)
202
            this.zip(name, new ByteArrayInputStream(in));
203
        else
204
            this.zipNonCompressed(name, in);
205
    }
206
 
207
    /**
208
     * Zip the passed array with the {@link ZipEntry#STORED} method. This method takes care of the
209
     * CRC and size.
210
     *
211
     * @param name the entry name.
212
     * @param in what to zip.
213
     * @throws IOException if an error occurs.
214
     */
215
    public synchronized void zipNonCompressed(String name, byte[] in) throws IOException {
216
        final ZipEntry entry = new ZipEntry(name);
217
        entry.setMethod(ZipEntry.STORED);
218
        final CRC32 crc = new CRC32();
219
        crc.update(in);
220
        entry.setCrc(crc.getValue());
221
        entry.setSize(in.length);
222
 
223
        this.putNextEntry(entry);
224
        this.getOutStream().write(in);
225
        this.closeEntry();
226
    }
227
 
228
    /**
229
     * Adds a new entry to this zip file. ATTN you must close the returned stream before you can add
230
     * to this zip again.
231
     *
232
     * @param name the name of the entry.
233
     * @return a stream to write to the entry.
234
     * @throws IOException if a pb occurs.
235
     */
236
    public synchronized OutputStream createEntry(String name) throws IOException {
237
        this.putNextEntry(name);
238
        return new BufferedOutputStream(this.getOutStream()) {
239
            public void close() throws IOException {
240
                this.flush();
241
                Zip.this.closeEntry();
242
            }
243
        };
244
    }
245
 
246
    private final synchronized void putNextEntry(String name) throws IOException, FileNotFoundException {
247
        this.putNextEntry(new ZipEntry(name));
248
    }
249
 
250
    private final synchronized void putNextEntry(ZipEntry entry) throws IOException, FileNotFoundException {
251
        if (this.entryOpen)
252
            throw new IllegalStateException("previous entry not closed");
253
        this.entryOpen = true;
254
        this.getOutStream().putNextEntry(entry);
255
    }
256
 
257
    protected final synchronized void closeEntry() throws IOException {
258
        this.getOutStream().closeEntry();
259
        this.entryOpen = false;
260
    }
261
 
262
}