Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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();
83
			if(device.version == 0)
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));
88
			}
89
			device.validatePayload();
90
		}
91
 
92
		this.valid = true;
93
	}
94
 
95
	/**
96
	 * Writes the payload contents to file
97
	 * 
98
	 * @param out The data output stream to write the payload to
99
	 * @throws IOException On file write errors
100
	 * @throws BuildException If payload contents have not been validated (see validatePayload())
101
	 */
102
	public void writePayload(DataOutputStream out) throws IOException
103
	{
104
		if(!this.valid)
105
		{
106
			throw new BuildException("Attempted to write an unvalidated APMCFG payload");
107
		}
108
 
109
		// Write DevCdApmcfgHeaderRecord_t
110
		out.writeInt(this.version);  // systemVer
111
		out.writeInt(this.devices.size());  // numDevTypes
112
 
113
		// Write DevCdApmcfgModuleSet_t for each contained device
114
		for (Iterator it = this.devices.iterator(); it.hasNext(); ) 
115
		{
116
			Device device = (Device)it.next();
117
			device.writePayload(out);
118
		}		
119
	}
120
 
121
	/**
122
	 * Creates a new Device object instance
123
	 * 
124
	 * @return A new Device instance
125
	 */
126
	public Device createDevice() 
127
	{
128
		Device device = new Device(this.version);
129
		this.devices.add(device);
130
		return device;
131
	}
132
 
133
	/**
134
	 * A class defining device modules contained within the APMCFG payload 
135
	 * 
136
	 * @author bivey
137
	 */
138
	public class Device
139
	{
140
		private int tier;			// Where the device type is connected in the network hierarchy		
141
		private String type;		// Device type name
142
		private int version;		// Software release version for this device type	
143
		private Vector modules;		// A list of modules for this device type
144
		private boolean valid;		// Indicates whether the payload has been validated
145
 
146
		public Device(int version) 
147
		{
148
			this.version = version;
149
			this.tier = 3;
150
			this.type = "";
151
			this.modules = new Vector();
152
			this.valid = false;
153
		}
154
 
155
		// Attribute setters - called by ANT when attributes are provided
156
		public void setTier(int tier) { this.tier = tier; }
157
		public void setType(String type) { this.type = type; }
158
		public void setVersion(int version) { this.version = version; }
159
 
160
		/**
161
		 * Validates data provided by ANT, ensuring a payload can be successfully created
162
		 * 
163
		 * @throws BuildException If invalid parameters are provided
164
		 */
165
		public void validatePayload()
166
		{
167
			if(this.type == null || this.type.length() == 0)
168
			{
169
				throw new BuildException("Device 'type' attribute must be defined");
170
			}
171
			if(this.type.length() > 9)
172
			{
173
				throw new BuildException("Device 'type' attribute exceeds maximum of 9 characters: " 
174
							+ this.type );
175
			}
176
 
177
			for (Iterator it = this.modules.iterator(); it.hasNext(); ) 
178
			{
179
				Module module = (Module)it.next();
180
				if(module.version == 0)
181
				{
182
					module.setVersion(this.version);
183
				}				
184
				module.validatePayload();
185
			}
186
 
187
			this.valid = true;
188
		}
189
 
190
		/**
191
		 * Writes the payload contents to file
192
		 * 
193
		 * @param out The data output stream to write the payload to
194
		 * @throws IOException On file write errors
195
		 * @throws BuildException If payload contents have not been validated (see validatePayload())
196
		 */
197
		public void writePayload(DataOutputStream out) throws IOException
198
		{
199
			if(!this.valid)
200
			{
201
				throw new BuildException("Attempted to write an unvalidated device payload");
202
			}
203
 
204
			// Write DevCdSoftwareModuleSetHeaderRecord_t
205
			out.write(this.type.getBytes());  // devType
206
			out.write(new byte[9-this.type.length()]);
207
			out.writeByte(0);  // reserved
208
			out.writeInt(this.version);  // version
209
			out.writeInt(this.tier);  //tier
210
			out.writeInt(this.modules.size());  //numMods
211
			out.writeShort(0);  // deleteBitmap
212
 
213
			// Write DevCdApmcfgModuleDescriptionRecord_t for each contained module
214
			for (Iterator it = modules.iterator(); it.hasNext(); ) 
215
			{
216
				Module module = (Module)it.next();
217
				module.writePayload(out);
218
			}				
219
		}
220
 
221
		/**
222
		 * Creates a new Module object instance
223
		 * 
224
		 * @return A new Module instance
225
		 */
226
		public Module createModule() 
227
		{
228
			Module module = new Module(this.version);
229
			this.modules.add(module);
230
			return module;
231
		}
232
 
233
		/**
234
		 * A class defining modules for the parent device type within the APMCFG payload 
235
		 * 
236
		 * @author bivey
237
		 */
238
		public class Module 
239
		{
240
			private String tag;		// Software module name
241
			private int version;	// Software module version
242
			private byte type;		// A bitmap controlling the software module loading process
243
			private byte special;	// Indicates if the software module has special memory requirements
244
			private String file;	// The file associated with this module
245
			private int crc;		// Software module checksum			
246
			private int size;		// Software module size (number of bytes)
247
			private boolean valid;  // Indicates whether the payload has been validated
248
 
249
			public Module(int version) 
250
			{
251
				this.version = version;
252
				this.valid = false;
253
				this.tag = "";
254
				this.type = 0;
255
				this.special = 0;
256
				this.crc = 0;
257
				this.size = 0;
258
			}
259
 
260
			// Attribute setters - called by ANT when attributes are provided
261
			public void setFile(String file) { this.file = file; }
262
			public void setSpecial(byte special) { this.special = special; }
263
			public void setTag(String tag) { this.tag = tag; }
264
			public void setType(byte type) { this.type = type; }
265
			public void setVersion(int version) { this.version = version; }
266
 
267
			/**
268
			 * Validates data provided by ANT, ensuring a payload can be successfully created
269
			 * 
270
			 * @throws BuildException If invalid parameters are provided
271
			 */
272
			private void validatePayload()
273
			{
274
				if(this.file == null || this.file.length() == 0)
275
				{
276
					throw new BuildException("Module 'file' attribute must be defined");
277
				}
278
 
279
				// Extract required file information
280
				try
281
				{
282
					CCITT crc = new CCITT();
283
					FileInputStream fis = new FileInputStream(this.file);
284
					BufferedInputStream bis = new BufferedInputStream(fis);					
285
 
286
			        int len = 0;
287
			        byte[] buffer = new byte[8192];
288
			        while ((len = bis.read(buffer)) > -1) 
289
			        {
290
			        	crc.update(buffer, 0, len);
291
			        }
292
 
293
			        this.crc = (short)crc.getValue();
294
			        this.size = (int)crc.getLength();
295
 
296
			        bis.close();
297
			        fis.close();
298
				}
299
				catch(FileNotFoundException e)
300
				{
301
					throw new BuildException("Unable to read file: " + file);
302
				}
303
				catch(IOException e)
304
				{
305
					throw new BuildException(e);
306
				}
307
 
308
				// Check tag or form one if it was not provided
309
				if( this.tag.length() > 8 )
310
				{
311
					throw new BuildException("Module 'tag' attribute exceeds maximum of 8 characters: " 
312
							+ this.tag );
313
				}
314
				else if( this.tag.length() == 0 )
315
				{
316
					// Extract the tag from the typical filename format of 'PATH\TAG_VERSION.mug'
317
					int index = 0;
318
					int start = 0;
319
					int end = this.file.length();
320
 
321
					if( (index = this.file.lastIndexOf('\\')) != -1 ) start = index;
322
					if( (index = this.file.lastIndexOf('/')) > start ) start = index;
323
					if( (index = this.file.indexOf('.', start)) != -1 ) end = index;
324
					if( ((index = this.file.indexOf('_', start)) != -1) && (index < end) ) end = index;
325
					if( (end - start) > 8 ) end = (start + 8);
326
 
327
					this.tag = this.file.substring(start, end);
328
				}
329
				this.tag = this.tag.toUpperCase();
330
 
331
				this.valid = true;
332
			}
333
 
334
			/**
335
			 * Writes the payload contents to file
336
			 * 
337
			 * @param out The data output stream to write the payload to
338
			 * @throws IOException On file write errors
339
			 * @throws BuildException If payload contents have not been validated (see validatePayload())
340
			 */
341
			private void writePayload(DataOutputStream out) throws IOException
342
			{
343
				if(!this.valid)
344
				{
345
					throw new BuildException("Attempted to write an unvalidated module payload");
346
				}
347
 
348
				// Write DevCdApmcfgModuleDescriptionRecord_t
349
				out.write(this.tag.getBytes());  // tag
350
				out.write(new byte[8-this.tag.length()]);
351
				out.writeShort(this.version);  // version
352
				out.writeShort(this.crc); // crc
353
				out.writeInt(this.size);  // size
354
				out.writeByte(this.type);  // type
355
				out.writeByte(this.special);  // special
356
				out.writeShort(0);	// reserved
357
			}
358
		}		
359
	}
360
}