-
Notifications
You must be signed in to change notification settings - Fork 18
/
ZipDatasets.java
245 lines (227 loc) · 8.33 KB
/
ZipDatasets.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/*
* %Z%%W% %I%
*
* =========================================================================
* Licensed Materials - Property of IBM
* "Restricted Materials of IBM"
* (C) Copyright IBM Corp. 2008. All Rights Reserved
*
* DISCLAIMER:
* The following [enclosed] code is sample code created by IBM
* Corporation. This sample code is not part of any standard IBM product
* and is provided to you solely for the purpose of assisting you in the
* development of your applications. The code is provided 'AS IS',
* without warranty of any kind. IBM shall not be liable for any damages
* arising out of your use of the sample code, even if they have been
* advised of the possibility of such damages.
* =========================================================================
*/
package com.ibm.jzos.sample;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipOutputStream;
import com.ibm.jzos.ZFile;
/**
* A sample Java main class that can be invoked to create a Zip archive from one
* or more datasets or PDS members. Datasets are treated as text and converted
* from EBCDIC to ASCII (ISO8859-1) or to the specified target codepage.
*
* <p>
* Details on the input arguments to this class are available by executing
* the main method with no arguments. (see {@link #usage()})
* </p>
*
* <p>
* Example: Zip several partitioned datasets to a Unix zip file:
* <pre>com.ibm.jzos.sample.ZipDatasets test.zip sys1.proclib(asm*) hlq.**.jcl </pre>
* </p>
*
* <p>
* Example: Zip all datasets matching two patterns to a dataset:
* <pre>com.ibm.jzos.sample.ZipDatasets //hlq.backup.zip payroll.*.data gl.**.dat*</pre>
* </p>
*
* <p>
* Example: Zip data using DDs and input and output:
* <pre>com.ibm.jzos.sample.ZipDatasets //DD:ZIPOUT //DD:INSEQ1 //DD:INPDS1 //DD:INPDS2(FOO*)</pre>
* </p>
*
* @see com.ibm.jzos.ZFile
* @see com.ibm.jzos.ZUtil
* @see com.ibm.jzos.CatalogSearch
* @see java.util.zip.ZipOutputStream java.util.zip.ZipOutputStream
* @see java.util.regex.Pattern java.util.regex.Pattern
* @see java.util.regex.Matcher java.util.regex.Matcher
* @see ZipDatasetSource ZipDatasetSource (the class which creates Zip archive entries for each input dataset/pattern)
*
* @since 2.3.0
*/
public class ZipDatasets {
/**
* Display usage syntax for invoking this class as a java main() method.
*/
public static void usage() {
System.err.println("Usage: com.ibm.jzos.sample.ZipDatasets [-t targetEncoding] outfile indsname...");
System.err.println(" where: ");
System.err.println(" -t targetEncoding can optionally specify the codepage name to encode the");
System.err.println(" text data as it is written to the Zip file. If not specified,");
System.err.println(" this defaults to ISO8859-1 (Latin/ASCII)");
System.err.println(" and outfile is either:");
System.err.println(" - a Unix file path name: /path/to/some/file.zip");
System.err.println(" - a dataset name: //A.B.C");
System.err.println(" - a PDS member name: //A.B.C(MEM)");
System.err.println(" - a DD name: //DD:XYZ");
System.err.println(" - a DD name and member: //DD:XYZ(MEM)");
System.err.println(" and each (at least one) indsname is either:");
System.err.println(" - a dataset name: //A.B.C");
System.err.println(" - a dataset pattern: //A.*.D");
System.err.println(" - a PDS member name: //A.B.C(MEM)");
System.err.println(" - a PDS member pattern: //A.B.C(D*X)");
System.err.println(" - a DD name: //DD:XYZ");
System.err.println(" - a DD name and member: //DD:XYZ(MEM)");
System.err.println(" - a DD name and member pattern: //DD:XYZ(D*X)");
System.err.println(" \"//\" prefixes may be omitted from indsnames");
System.err.println(" All dataset names are assumed to be fully qualified.");
}
/**
* A Java main method for invoking this class.
* @param args
* @throws Exception
* @see ZipDatasets#usage()
*/
public static void main(String[] args) throws Exception {
String targetEncoding = null;
int iOutfileName = 0;
// need at least one outdsname and one indsname
if (args == null || args.length < 2) {
usage();
System.exit(12);
}
// handle the -t targetEncoding option
if (args[0].equals("-t")) {
targetEncoding = args[1];
iOutfileName = 2;
}
// still need at least one outdsname and one indsname
if (args.length < iOutfileName + 2) {
usage();
System.exit(12);
}
// copy the indsnames to a separate String[]
String[] indsnames = new String[args.length - iOutfileName - 1];
System.arraycopy(args, iOutfileName+1, indsnames, 0, indsnames.length);
// construct an instance and run it
ZipDatasets instance = new ZipDatasets(args[iOutfileName], indsnames);
if (targetEncoding != null) {
instance.setTargetEncoding(targetEncoding);
}
int errors = instance.run();
if (errors > 0) {
System.exit(8);
}
}
public static final String DEFAULT_TARGET_ENCODING = "ISO8859-1";
private String outFileName;
private String[] indsnames;
private String targetEncoding;
private int errors = 0;
/**
* Construct an instance
* @param outFileName the name of the /output/file, //DATASET, //DD:name, etc
* where the Zip archive is written.
* @param indsnames an array of input dataset names / patterns
* @see ZipDatasetSource for more details on allowed input dataset names
*/
public ZipDatasets(String outFileName, String[] indsnames) {
this.outFileName = outFileName;
this.indsnames = indsnames;
this.targetEncoding = DEFAULT_TARGET_ENCODING;
}
/**
* Sets the name of the codepage used to encode the text data written
* to the Zip file. If not called, defaults to {@link #DEFAULT_TARGET_ENCODING}.
* @param targetEncoding
*/
public void setTargetEncoding(String targetEncoding) {
this.targetEncoding = targetEncoding;
}
/**
* Process the given input datasets and create a Zip archive on the
* given output file or dataset.
*/
public int run() throws IOException {
ZipOutputStream zipOutStream = openZipOutputStream();
try {
processInputFiles(zipOutStream);
zipOutStream.finish();
System.out.println(" done: " + errors + " errors");
return errors;
} finally {
try {
zipOutStream.close();
} catch (Throwable ignore) {}
}
}
/**
* Open a ZipOutputStream on the given target file or dataset.
* @return ZipOutputStream
* @throws IOException
*/
private ZipOutputStream openZipOutputStream() throws IOException {
// First create a (binary) OutputStream on either a Unix file
// or dataset, depending on the name given.
OutputStream os;
if (outFileName.startsWith("//")) {
os = openDataset(outFileName);
} else {
os = new FileOutputStream(outFileName);
}
// Wrap the OutputStream in a new ZipOutputStream
return new ZipOutputStream(os);
}
/**
* Given a "//data.set" or "//DD:name" or even //data.set(member)
* or "//DD:name(member), open a ZFile on it in binary streaming mode.
* The dataset is opened with DCB RECFM=VB,LRECL=1028,BLKSIZE=0.
* mode and return it as an {@link OutputStream}.
* Dataset names are assumed to be fully qualified.
*
* @param name the dataset name
* @return OutputStream
* @throws IOException
* @see ZFile#getSlashSlashQuotedDSN(String, boolean)
*/
private OutputStream openDataset(String name) throws IOException {
ZFile zfile = new ZFile(
ZFile.getSlashSlashQuotedDSN(name, true),
"wb,recfm=vb,lrecl=1028,blksize=0");
return zfile.getOutputStream();
}
/**
* Loop over each input dataset name (or pattern) given and
* add entries for it to the Zip file.
* If an exception occurs processing one entry, try to clean it
* up and continue with the next entry.
* The {@link ZipDatasetSource} class does all of the real work.
* <p/>
* @param zipOutStream
*/
private void processInputFiles(ZipOutputStream zipOutStream) {
for (int i=0; i<indsnames.length; i++) {
String inputName = indsnames[i];
ZipDatasetSource source = new ZipDatasetSource(inputName);
try {
source.addTo(zipOutStream, targetEncoding);
} catch( Throwable t) {
errors++;
try {
zipOutStream.closeEntry();
} catch (IOException ignore) {}
System.out.println(">>> Error occuring processing input dataset: " + inputName);
System.err.println(">>> Error occuring processing input dataset: " + inputName);
t.printStackTrace();
}
}
}
}