Subversion Repositories DevTools

Rev

Rev 1695 | Details | Compare with Previous | 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();
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
}