1
2
3
4
5
6
7
8
9
10
11 package com.legstar.zosjes;
12
13 import java.io.ByteArrayOutputStream;
14 import java.io.File;
15 import java.io.FileInputStream;
16 import java.io.IOException;
17 import java.io.OutputStream;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
20
21 import org.apache.commons.net.ftp.FTPClient;
22 import org.apache.commons.net.ftp.FTPClientConfig;
23 import org.apache.commons.net.ftp.FTPReply;
24
25
26
27
28
29
30
31 public class FtpZosClient {
32
33
34 FTPClient _ftpClient;
35
36
37 private static final String SUBMIT_REPLY = "250-It is known to JES as ";
38
39
40 private static final Pattern COND_CODE_PATTERN =
41 Pattern.compile("COND CODE (\\d{4})", Pattern.CASE_INSENSITIVE);
42
43
44
45
46 public FtpZosClient() {
47 _ftpClient = new FTPClient();
48 FTPClientConfig ftpConf = new FTPClientConfig(FTPClientConfig.SYST_MVS);
49 ftpConf.setServerTimeZoneId("GMT");
50 _ftpClient.configure(ftpConf);
51 }
52
53
54
55
56
57
58
59
60 public void open(
61 final String hostname,
62 final String hostUserID,
63 final String hostPassword) throws IOException {
64 if (_ftpClient.isConnected()) {
65 _ftpClient.disconnect();
66 }
67 _ftpClient.connect(hostname);
68 if (!FTPReply.isPositiveCompletion(_ftpClient.getReplyCode())) {
69 throw new IOException(hostname + " not responding");
70 }
71 if (!_ftpClient.login(hostUserID, hostPassword)) {
72 processFtpError();
73 }
74 }
75
76
77
78
79
80
81
82 public void upload(final String remote, final File local) throws IOException {
83 if (!_ftpClient.sendSiteCommand("FILEtype=SEQ")) {
84 processFtpError();
85 }
86 if (!_ftpClient.storeFile(remote, new FileInputStream(local))) {
87 processFtpError();
88 }
89 }
90
91
92
93
94
95
96
97
98
99
100 public String submitJob(final String jcl) throws IOException {
101
102 String jobId = null;
103 if (!_ftpClient.sendSiteCommand("FILEtype=JES")) {
104 processFtpError();
105 }
106
107 OutputStream os = _ftpClient.storeFileStream("P390JCL8");
108 if (os == null) {
109 processFtpError();
110 }
111 os.write(jcl.getBytes());
112 os.close();
113 if (!_ftpClient.completePendingCommand()) {
114 processFtpError();
115 }
116
117 String[] replies = _ftpClient.getReplyStrings();
118 if (replies == null || replies.length == 0) {
119 processFtpError();
120 }
121
122 if (replies[0].startsWith(SUBMIT_REPLY)) {
123 jobId = replies[0].substring(SUBMIT_REPLY.length());
124 } else {
125 processFtpError();
126 }
127
128 return jobId;
129 }
130
131
132
133
134
135
136
137 public String getJobOutput(final String jobId) throws IOException {
138 return getJesResource(jobId + ".x");
139 }
140
141
142
143
144
145
146
147
148 public String submitWaitForOutput(final String remoteFile) throws IOException {
149 return getJesResource(remoteFile);
150 }
151
152
153
154
155
156
157
158 public String getJesResource(final String jesResource) throws IOException {
159 if (!_ftpClient.sendSiteCommand("FILEtype=JES")) {
160 processFtpError();
161 }
162 ByteArrayOutputStream baos = new ByteArrayOutputStream();
163 if (!_ftpClient.retrieveFile(jesResource, baos)) {
164 processFtpError();
165 }
166 baos.close();
167 String result = baos.toString("UTF-8");
168 return result;
169 }
170
171
172
173
174
175
176 public int getHighestCondCode(final String heldOutput) {
177 int maxCondCode = -1;
178 Matcher matcher = COND_CODE_PATTERN.matcher(heldOutput);
179 while(matcher.find()) {
180 int condCode = Integer.parseInt(matcher.group(1));
181 maxCondCode = (condCode > maxCondCode) ? condCode : maxCondCode;
182 }
183 return maxCondCode;
184 }
185
186
187
188
189
190
191
192
193 public void close() throws IOException {
194 if (_ftpClient.isConnected()) {
195 _ftpClient.logout();
196 _ftpClient.disconnect();
197 }
198 }
199
200
201
202
203
204 protected void processFtpError() throws IOException {
205 String errors[] = _ftpClient.getReplyStrings();
206 _ftpClient.disconnect();
207
208 if (errors == null || errors.length == 0) {
209 throw new IOException("Unknown error.");
210 }
211 throw new IOException(errors[0]);
212 }
213 }