OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 142 | Rev 180 | 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
177 ilm 176
        try (final BufferedInputStream ins = new BufferedInputStream(new FileInputStream(newFile))) {
177
            this.zip(newFile.getName(), ins);
178
        }
17 ilm 179
    }
180
 
181
    /**
182
     * Zippe le contenu de <code>in</code>.
183
     *
184
     * @param name le nom de l'entrée.
185
     * @param in l'ajout.
186
     * @throws IOException si in ne peut etre zippé.
187
     */
188
    public synchronized void zip(String name, InputStream in) throws IOException {
189
        this.putNextEntry(name);
190
 
191
        byte b[] = new byte[512];
192
        int len = 0;
193
        while ((len = in.read(b)) != -1) {
194
            this.getOutStream().write(b, 0, len);
195
        }
196
 
197
        this.closeEntry();
198
    }
199
 
200
    public void zip(String name, byte[] in, final boolean compressed) throws IOException {
201
        // don't make #zip(String, InputStream) call this method, it would require to read the
202
        // entire stream into memory
203
        if (compressed)
204
            this.zip(name, new ByteArrayInputStream(in));
205
        else
206
            this.zipNonCompressed(name, in);
207
    }
208
 
209
    /**
210
     * Zip the passed array with the {@link ZipEntry#STORED} method. This method takes care of the
211
     * CRC and size.
212
     *
213
     * @param name the entry name.
214
     * @param in what to zip.
215
     * @throws IOException if an error occurs.
216
     */
217
    public synchronized void zipNonCompressed(String name, byte[] in) throws IOException {
218
        final ZipEntry entry = new ZipEntry(name);
219
        entry.setMethod(ZipEntry.STORED);
220
        final CRC32 crc = new CRC32();
221
        crc.update(in);
222
        entry.setCrc(crc.getValue());
223
        entry.setSize(in.length);
224
 
225
        this.putNextEntry(entry);
226
        this.getOutStream().write(in);
227
        this.closeEntry();
228
    }
229
 
230
    /**
231
     * Adds a new entry to this zip file. ATTN you must close the returned stream before you can add
232
     * to this zip again.
233
     *
234
     * @param name the name of the entry.
235
     * @return a stream to write to the entry.
236
     * @throws IOException if a pb occurs.
237
     */
238
    public synchronized OutputStream createEntry(String name) throws IOException {
239
        this.putNextEntry(name);
240
        return new BufferedOutputStream(this.getOutStream()) {
241
            public void close() throws IOException {
242
                this.flush();
243
                Zip.this.closeEntry();
244
            }
245
        };
246
    }
247
 
248
    private final synchronized void putNextEntry(String name) throws IOException, FileNotFoundException {
249
        this.putNextEntry(new ZipEntry(name));
250
    }
251
 
252
    private final synchronized void putNextEntry(ZipEntry entry) throws IOException, FileNotFoundException {
253
        if (this.entryOpen)
254
            throw new IllegalStateException("previous entry not closed");
255
        this.entryOpen = true;
256
        this.getOutStream().putNextEntry(entry);
257
    }
258
 
259
    protected final synchronized void closeEntry() throws IOException {
260
        this.getOutStream().closeEntry();
261
        this.entryOpen = false;
262
    }
263
 
264
}