| 1695 |
bivey |
1 |
package com.erggroup.mass.ant.tasks;
|
|
|
2 |
|
|
|
3 |
import com.erggroup.mass.ant.tasks.util.CCITT;
|
|
|
4 |
import java.io.*;
|
|
|
5 |
import java.util.Vector;
|
|
|
6 |
import java.util.Iterator;
|
|
|
7 |
import org.apache.tools.ant.Task;
|
|
|
8 |
import org.apache.tools.ant.BuildException;
|
|
|
9 |
|
|
|
10 |
/**
|
|
|
11 |
* Creates an APMCFG payload using information passed to it in ANT
|
|
|
12 |
*
|
|
|
13 |
* @author bivey
|
|
|
14 |
*/
|
|
|
15 |
public class Apmcfg extends Task {
|
|
|
16 |
|
|
|
17 |
private String dir; // The directory in which to write the APMCFG file
|
|
|
18 |
private int version; // Specifies the overall software build version
|
|
|
19 |
private Vector devices; // A list of device types contained in the APMCFG
|
|
|
20 |
private boolean valid; // Indicates whether the payload has been validated
|
|
|
21 |
|
|
|
22 |
public Apmcfg()
|
|
|
23 |
{
|
|
|
24 |
this.devices = new Vector();
|
|
|
25 |
this.version = 0;
|
|
|
26 |
this.dir = System.getProperty("user.dir");
|
|
|
27 |
this.valid = false;
|
|
|
28 |
}
|
|
|
29 |
|
|
|
30 |
/**
|
|
|
31 |
* Main function executed by ANT task
|
|
|
32 |
*
|
|
|
33 |
* @see org.apache.tools.ant.Task#execute()
|
|
|
34 |
*/
|
|
|
35 |
public void execute()
|
|
|
36 |
{
|
|
|
37 |
// First validate our entered data
|
|
|
38 |
validatePayload();
|
|
|
39 |
|
|
|
40 |
try
|
|
|
41 |
{
|
|
|
42 |
// Now write the APMCFG file
|
|
|
43 |
String file = this.dir + File.separatorChar + "@APMCFG_1_" + this.version + ".mug";
|
|
|
44 |
FileOutputStream fos = new FileOutputStream(file);
|
|
|
45 |
DataOutputStream dos = new DataOutputStream(fos);
|
|
|
46 |
|
|
|
47 |
this.writePayload(dos);
|
|
|
48 |
log("Wrote APMCFG payload: " + file);
|
|
|
49 |
|
|
|
50 |
dos.close();
|
|
|
51 |
fos.close();
|
|
|
52 |
}
|
|
|
53 |
catch (Exception e)
|
|
|
54 |
{
|
|
|
55 |
throw new BuildException(e);
|
|
|
56 |
}
|
|
|
57 |
}
|
|
|
58 |
|
|
|
59 |
// Attribute setters - called by ANT when attributes are provided
|
|
|
60 |
public void setDir(String dir) { this.dir = dir; }
|
|
|
61 |
public void setVersion(int version) { this.version = version; }
|
|
|
62 |
|
|
|
63 |
/**
|
|
|
64 |
* Validates data provided by ANT, ensuring a payload can be successfully created
|
|
|
65 |
*
|
|
|
66 |
* @throws BuildException If invalid parameters are provided
|
|
|
67 |
*/
|
|
|
68 |
public void validatePayload()
|
|
|
69 |
{
|
|
|
70 |
// Check the specified target directory exists
|
|
|
71 |
File directory = new File(this.dir);
|
|
|
72 |
if( !directory.isDirectory() )
|
|
|
73 |
{
|
|
|
74 |
if( !directory.mkdirs() )
|
|
|
75 |
{
|
|
|
76 |
throw new BuildException("Unable to create directory: " + this.dir);
|
|
|
77 |
}
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
for (Iterator it = this.devices.iterator(); it.hasNext(); )
|
|
|
81 |
{
|
|
|
82 |
Device device = (Device)it.next();
|
| 4810 |
sqiu |
83 |
//if(device.version == 0)
|
| 1695 |
bivey |
84 |
{
|
|
|
85 |
// Assume our version was hexadecimal - this is a hacky workaround for
|
|
|
86 |
// the difficulty in converting between decimal-hex in an ANT script
|
|
|
87 |
device.setVersion(Integer.parseInt(Integer.toString(this.version), 16));
|
| 4810 |
sqiu |
88 |
|
|
|
89 |
//log("device.version = " + this.version);
|
| 1695 |
bivey |
90 |
}
|
|
|
91 |
device.validatePayload();
|
|
|
92 |
}
|
|
|
93 |
|
|
|
94 |
this.valid = true;
|
|
|
95 |
}
|
|
|
96 |
|
|
|
97 |
/**
|
|
|
98 |
* Writes the payload contents to file
|
|
|
99 |
*
|
|
|
100 |
* @param out The data output stream to write the payload to
|
|
|
101 |
* @throws IOException On file write errors
|
|
|
102 |
* @throws BuildException If payload contents have not been validated (see validatePayload())
|
|
|
103 |
*/
|
|
|
104 |
public void writePayload(DataOutputStream out) throws IOException
|
|
|
105 |
{
|
|
|
106 |
if(!this.valid)
|
|
|
107 |
{
|
|
|
108 |
throw new BuildException("Attempted to write an unvalidated APMCFG payload");
|
|
|
109 |
}
|
|
|
110 |
|
|
|
111 |
// Write DevCdApmcfgHeaderRecord_t
|
|
|
112 |
out.writeInt(this.version); // systemVer
|
|
|
113 |
out.writeInt(this.devices.size()); // numDevTypes
|
|
|
114 |
|
|
|
115 |
// Write DevCdApmcfgModuleSet_t for each contained device
|
|
|
116 |
for (Iterator it = this.devices.iterator(); it.hasNext(); )
|
|
|
117 |
{
|
|
|
118 |
Device device = (Device)it.next();
|
|
|
119 |
device.writePayload(out);
|
|
|
120 |
}
|
|
|
121 |
}
|
|
|
122 |
|
|
|
123 |
/**
|
|
|
124 |
* Creates a new Device object instance
|
|
|
125 |
*
|
|
|
126 |
* @return A new Device instance
|
|
|
127 |
*/
|
|
|
128 |
public Device createDevice()
|
|
|
129 |
{
|
|
|
130 |
Device device = new Device(this.version);
|
|
|
131 |
this.devices.add(device);
|
|
|
132 |
return device;
|
|
|
133 |
}
|
|
|
134 |
|
|
|
135 |
/**
|
|
|
136 |
* A class defining device modules contained within the APMCFG payload
|
|
|
137 |
*
|
|
|
138 |
* @author bivey
|
|
|
139 |
*/
|
|
|
140 |
public class Device
|
|
|
141 |
{
|
|
|
142 |
private int tier; // Where the device type is connected in the network hierarchy
|
|
|
143 |
private String type; // Device type name
|
|
|
144 |
private int version; // Software release version for this device type
|
|
|
145 |
private Vector modules; // A list of modules for this device type
|
|
|
146 |
private boolean valid; // Indicates whether the payload has been validated
|
|
|
147 |
|
|
|
148 |
public Device(int version)
|
|
|
149 |
{
|
|
|
150 |
this.version = version;
|
|
|
151 |
this.tier = 3;
|
|
|
152 |
this.type = "";
|
|
|
153 |
this.modules = new Vector();
|
|
|
154 |
this.valid = false;
|
|
|
155 |
}
|
|
|
156 |
|
|
|
157 |
// Attribute setters - called by ANT when attributes are provided
|
|
|
158 |
public void setTier(int tier) { this.tier = tier; }
|
|
|
159 |
public void setType(String type) { this.type = type; }
|
|
|
160 |
public void setVersion(int version) { this.version = version; }
|
|
|
161 |
|
|
|
162 |
/**
|
|
|
163 |
* Validates data provided by ANT, ensuring a payload can be successfully created
|
|
|
164 |
*
|
|
|
165 |
* @throws BuildException If invalid parameters are provided
|
|
|
166 |
*/
|
|
|
167 |
public void validatePayload()
|
|
|
168 |
{
|
|
|
169 |
if(this.type == null || this.type.length() == 0)
|
|
|
170 |
{
|
|
|
171 |
throw new BuildException("Device 'type' attribute must be defined");
|
|
|
172 |
}
|
|
|
173 |
if(this.type.length() > 9)
|
|
|
174 |
{
|
|
|
175 |
throw new BuildException("Device 'type' attribute exceeds maximum of 9 characters: "
|
|
|
176 |
+ this.type );
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
for (Iterator it = this.modules.iterator(); it.hasNext(); )
|
|
|
180 |
{
|
|
|
181 |
Module module = (Module)it.next();
|
| 4810 |
sqiu |
182 |
//if(module.version == 0)
|
| 1695 |
bivey |
183 |
{
|
|
|
184 |
module.setVersion(this.version);
|
| 4810 |
sqiu |
185 |
|
|
|
186 |
//log("module.version = " + this.version);
|
| 1695 |
bivey |
187 |
}
|
|
|
188 |
module.validatePayload();
|
|
|
189 |
}
|
|
|
190 |
|
|
|
191 |
this.valid = true;
|
|
|
192 |
}
|
|
|
193 |
|
|
|
194 |
/**
|
|
|
195 |
* Writes the payload contents to file
|
|
|
196 |
*
|
|
|
197 |
* @param out The data output stream to write the payload to
|
|
|
198 |
* @throws IOException On file write errors
|
|
|
199 |
* @throws BuildException If payload contents have not been validated (see validatePayload())
|
|
|
200 |
*/
|
|
|
201 |
public void writePayload(DataOutputStream out) throws IOException
|
|
|
202 |
{
|
|
|
203 |
if(!this.valid)
|
|
|
204 |
{
|
|
|
205 |
throw new BuildException("Attempted to write an unvalidated device payload");
|
|
|
206 |
}
|
|
|
207 |
|
|
|
208 |
// Write DevCdSoftwareModuleSetHeaderRecord_t
|
|
|
209 |
out.write(this.type.getBytes()); // devType
|
|
|
210 |
out.write(new byte[9-this.type.length()]);
|
|
|
211 |
out.writeByte(0); // reserved
|
|
|
212 |
out.writeInt(this.version); // version
|
|
|
213 |
out.writeInt(this.tier); //tier
|
|
|
214 |
out.writeInt(this.modules.size()); //numMods
|
|
|
215 |
out.writeShort(0); // deleteBitmap
|
|
|
216 |
|
|
|
217 |
// Write DevCdApmcfgModuleDescriptionRecord_t for each contained module
|
|
|
218 |
for (Iterator it = modules.iterator(); it.hasNext(); )
|
|
|
219 |
{
|
|
|
220 |
Module module = (Module)it.next();
|
|
|
221 |
module.writePayload(out);
|
|
|
222 |
}
|
|
|
223 |
}
|
|
|
224 |
|
|
|
225 |
/**
|
|
|
226 |
* Creates a new Module object instance
|
|
|
227 |
*
|
|
|
228 |
* @return A new Module instance
|
|
|
229 |
*/
|
|
|
230 |
public Module createModule()
|
|
|
231 |
{
|
|
|
232 |
Module module = new Module(this.version);
|
|
|
233 |
this.modules.add(module);
|
|
|
234 |
return module;
|
|
|
235 |
}
|
|
|
236 |
|
|
|
237 |
/**
|
|
|
238 |
* A class defining modules for the parent device type within the APMCFG payload
|
|
|
239 |
*
|
|
|
240 |
* @author bivey
|
|
|
241 |
*/
|
|
|
242 |
public class Module
|
|
|
243 |
{
|
|
|
244 |
private String tag; // Software module name
|
|
|
245 |
private int version; // Software module version
|
|
|
246 |
private byte type; // A bitmap controlling the software module loading process
|
|
|
247 |
private byte special; // Indicates if the software module has special memory requirements
|
|
|
248 |
private String file; // The file associated with this module
|
|
|
249 |
private int crc; // Software module checksum
|
|
|
250 |
private int size; // Software module size (number of bytes)
|
|
|
251 |
private boolean valid; // Indicates whether the payload has been validated
|
|
|
252 |
|
|
|
253 |
public Module(int version)
|
|
|
254 |
{
|
|
|
255 |
this.version = version;
|
|
|
256 |
this.valid = false;
|
|
|
257 |
this.tag = "";
|
|
|
258 |
this.type = 0;
|
|
|
259 |
this.special = 0;
|
|
|
260 |
this.crc = 0;
|
|
|
261 |
this.size = 0;
|
|
|
262 |
}
|
|
|
263 |
|
|
|
264 |
// Attribute setters - called by ANT when attributes are provided
|
|
|
265 |
public void setFile(String file) { this.file = file; }
|
|
|
266 |
public void setSpecial(byte special) { this.special = special; }
|
|
|
267 |
public void setTag(String tag) { this.tag = tag; }
|
|
|
268 |
public void setType(byte type) { this.type = type; }
|
|
|
269 |
public void setVersion(int version) { this.version = version; }
|
|
|
270 |
|
|
|
271 |
/**
|
|
|
272 |
* Validates data provided by ANT, ensuring a payload can be successfully created
|
|
|
273 |
*
|
|
|
274 |
* @throws BuildException If invalid parameters are provided
|
|
|
275 |
*/
|
|
|
276 |
private void validatePayload()
|
|
|
277 |
{
|
|
|
278 |
if(this.file == null || this.file.length() == 0)
|
|
|
279 |
{
|
|
|
280 |
throw new BuildException("Module 'file' attribute must be defined");
|
|
|
281 |
}
|
|
|
282 |
|
|
|
283 |
// Extract required file information
|
|
|
284 |
try
|
|
|
285 |
{
|
|
|
286 |
CCITT crc = new CCITT();
|
|
|
287 |
FileInputStream fis = new FileInputStream(this.file);
|
|
|
288 |
BufferedInputStream bis = new BufferedInputStream(fis);
|
|
|
289 |
|
|
|
290 |
int len = 0;
|
|
|
291 |
byte[] buffer = new byte[8192];
|
|
|
292 |
while ((len = bis.read(buffer)) > -1)
|
|
|
293 |
{
|
|
|
294 |
crc.update(buffer, 0, len);
|
|
|
295 |
}
|
|
|
296 |
|
|
|
297 |
this.crc = (short)crc.getValue();
|
|
|
298 |
this.size = (int)crc.getLength();
|
|
|
299 |
|
|
|
300 |
bis.close();
|
|
|
301 |
fis.close();
|
|
|
302 |
}
|
|
|
303 |
catch(FileNotFoundException e)
|
|
|
304 |
{
|
|
|
305 |
throw new BuildException("Unable to read file: " + file);
|
|
|
306 |
}
|
|
|
307 |
catch(IOException e)
|
|
|
308 |
{
|
|
|
309 |
throw new BuildException(e);
|
|
|
310 |
}
|
|
|
311 |
|
|
|
312 |
// Check tag or form one if it was not provided
|
|
|
313 |
if( this.tag.length() > 8 )
|
|
|
314 |
{
|
|
|
315 |
throw new BuildException("Module 'tag' attribute exceeds maximum of 8 characters: "
|
|
|
316 |
+ this.tag );
|
|
|
317 |
}
|
|
|
318 |
else if( this.tag.length() == 0 )
|
|
|
319 |
{
|
|
|
320 |
// Extract the tag from the typical filename format of 'PATH\TAG_VERSION.mug'
|
|
|
321 |
int index = 0;
|
|
|
322 |
int start = 0;
|
|
|
323 |
int end = this.file.length();
|
|
|
324 |
|
|
|
325 |
if( (index = this.file.lastIndexOf('\\')) != -1 ) start = index;
|
|
|
326 |
if( (index = this.file.lastIndexOf('/')) > start ) start = index;
|
|
|
327 |
if( (index = this.file.indexOf('.', start)) != -1 ) end = index;
|
|
|
328 |
if( ((index = this.file.indexOf('_', start)) != -1) && (index < end) ) end = index;
|
|
|
329 |
if( (end - start) > 8 ) end = (start + 8);
|
|
|
330 |
|
|
|
331 |
this.tag = this.file.substring(start, end);
|
|
|
332 |
}
|
|
|
333 |
this.tag = this.tag.toUpperCase();
|
|
|
334 |
|
|
|
335 |
this.valid = true;
|
|
|
336 |
}
|
|
|
337 |
|
|
|
338 |
/**
|
|
|
339 |
* Writes the payload contents to file
|
|
|
340 |
*
|
|
|
341 |
* @param out The data output stream to write the payload to
|
|
|
342 |
* @throws IOException On file write errors
|
|
|
343 |
* @throws BuildException If payload contents have not been validated (see validatePayload())
|
|
|
344 |
*/
|
|
|
345 |
private void writePayload(DataOutputStream out) throws IOException
|
|
|
346 |
{
|
|
|
347 |
if(!this.valid)
|
|
|
348 |
{
|
|
|
349 |
throw new BuildException("Attempted to write an unvalidated module payload");
|
|
|
350 |
}
|
|
|
351 |
|
|
|
352 |
// Write DevCdApmcfgModuleDescriptionRecord_t
|
|
|
353 |
out.write(this.tag.getBytes()); // tag
|
|
|
354 |
out.write(new byte[8-this.tag.length()]);
|
|
|
355 |
out.writeShort(this.version); // version
|
|
|
356 |
out.writeShort(this.crc); // crc
|
|
|
357 |
out.writeInt(this.size); // size
|
|
|
358 |
out.writeByte(this.type); // type
|
|
|
359 |
out.writeByte(this.special); // special
|
|
|
360 |
out.writeShort(0); // reserved
|
|
|
361 |
}
|
|
|
362 |
}
|
|
|
363 |
}
|
|
|
364 |
}
|