adcutil
Version:
Utilities tools for Askia Design Control
1,199 lines (1,038 loc) • 39.5 kB
HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
<style type="text/css">
.highlight { display: block; background-color: #ddd; }
</style>
<script type="text/javascript">
function highlight() {
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
}
</script>
</head>
<body onload="prettyPrint(); highlight();">
<pre class="prettyprint lang-js">/*
ASP Classic
asp
ASP.NET
aspx
axd
asx
asmx
ashx
axd
ascx
CSS
css
hss
sass
less
ccss
pcss
Coldfusion
cfm
Erlang
yaws
Flash
swf
HTML
html
htm
xhtml
jhtml
Java
jsp
jspx
wss
do
action
JavaScript
js
Perl
pl
PHP
php
php4
php3
phtml
Python
py
Ruby
rb
rhtml
rjs
erb
XML
xml
rss
atom
svg
Other (C, perl etc.)
cgi
dll
Executable
Extension Format Operating System(s)
ACTION Automator Action Mac OS
APK Application Android
APP Executable Mac OS
BAT Batch File Windows
BIN Binary Executable Windows, Mac OS, Linux
CMD Command Script Windows
COM Command File Windows
COMMAND Terminal Command Mac OS
CPL Control Panel Extension Windows
CSH C Shell Script Mac OS, Linux
EXE Executable Windows
GADGET Windows Gadget Windows
INF1 Setup Information File Windows
INS Internet Communication Settings Windows
INX InstallShield Compiled Script Windows
IPA Application iOS
ISU InstallShield Uninstaller Script Windows
JOB Windows Task Scheduler Job File Windows
JSE JScript Encoded File Windows
KSH Unix Korn Shell Script Linux
LNK File Shortcut Windows
MSC Microsoft Common Console Document Windows
MSI Windows Installer Package Windows
MSP Windows Installer Patch Windows
MST Windows Installer Setup Transform File Windows
OSX Executable Mac OS
OUT Executable Linux
PAF Portable Application Installer File Windows
PIF Program Information File Windows
PRG Executable GEM
PS1 Windows PowerShell Cmdlet Windows
REG Registry Data File Windows
RGS Registry Script Windows
RUN Executable Linux
SCT Windows Scriptlet Windows
SHB Windows Document Shortcut Windows
SHS Shell Scrap Object Windows
U3P U3 Smart Application Windows
VB VBScript File Windows
VBE VBScript Encoded Script Windows
VBS VBScript File Windows
VBSCRIPT Visual Basic Script Windows
WORKFLOW Automator Workflow Mac OS
WS Windows Script Windows
WSF Windows Script Windows
Audio File Types and Formats
.aif Audio Interchange File Format
.iff Interchange File Format
.m3u Media Playlist File
.m4a MPEG-4 Audio File
.mid MIDI File
.mp3 MP3 Audio File
.mpa MPEG-2 Audio File
.ra Real Audio File
.wav WAVE Audio File
.wma Windows Media Audio File
AddType audio/ogg ogg
AddType audio/ogg oga
AddType audio/webm webma
Video Files Types and Formats
.3g2 3GPP2 Multimedia File
.3gp 3GPP Multimedia File
.asf Advanced Systems Format File
.asx Microsoft ASF Redirector File
.avi Audio Video Interleave File
.flv Flash Video File
.mov Apple QuickTime Movie
.mp4 MPEG-4 Video File
.mpg MPEG Video File
.rm Real Media File
.swf Shockwave Flash Movie
.vob DVD Video Object File
.wmv Windows Media Video File
Markdown
md
white
xml|rss|atom|svg|js|xhtml|htm|html|swf|css|hss|sass|less|ccss|pcss|txt|csv|json|
gif|jpeg|jpg|tif|tiff|png|bmp|pdf|ico|cur|
aif|iff|m4a|mid|mp3|mpa|ra|wav|wma|ogg|oga|webma|
3g2|3gp|avi|flv|mov|mp4|mpg|rm|wmv|webm
md|
black
cgi|dll|erb|rjs|rhtml|rb|py|phtml|php3|php4|php|pl|action|do|wss|jspx|jsp|jhtml|yaws|cfm|aspx|axd|asx|asmx|ashx|axd|ascx|asp|config|
action|apk|app|bat|bin|cmd|com|command|cpl|csh|exe|gadget|inf1|ins|inx|ipa|isu|
job|jse|ksh|lnk|msc|msi|msp|mst|ocx|osx|out|paf|pif|prg|ps1|reg|rgs|run|sct|shb|shs|u3p|
vb|vbe|vbs|vbscript|workflow|ws|wsf|cs|cpp|
zip|rar|sql|ini|dmg|iso|vcd|class|java|htaccess
*/
var fs = require('fs');
var pathHelper = require('path');
var xml2js = require('xml2js');
var util = require('util');
var common = require('../common/common.js');
var errMsg = common.messages.error;
var warnMsg = common.messages.warning;
var successMsg = common.messages.success;
var msg = common.messages.message;
// Test the file extension
var fileExt = {
blacklist : /\.(cgi|dll|erb|rjs|rhtml|rb|py|phtml|php3|php4|php|pl|action|do|wss|jspx|jsp|jhtml|yaws|cfm|aspx|axd|asx|asmx|ashx|axd|ascx|asp|config|action|apk|app|bat|bin|cmd|com|command|cpl|csh|exe|gadget|inf1|ins|inx|ipa|isu|job|jse|ksh|lnk|msc|msi|msp|mst|ocx|osx|out|paf|pif|prg|ps1|reg|rgs|run|sct|shb|shs|u3p|vb|vbe|vbs|vbscript|workflow|ws|wsf|cs|cpp|zip|rar|sql|ini|dmg|iso|vcd|class|java|htaccess)$/gi,
whitelist : /\.(xml|rss|atom|svg|js|xhtml|htm|html|swf|css|hss|sass|less|ccss|pcss|txt|csv|json|gif|jpeg|jpg|tif|tiff|png|bmp|pdf|ico|cur|aif|iff|m4a|mid|mp3|mpa|ra|wav|wma|ogg|oga|webma|3g2|3gp|avi|flv|mov|mp4|mpg|rm|wmv|ogv|webm|md)$/gi
};
// Hash with all content type
var contentType = {
'text' : 'text',
'html' : 'text',
'javascript': 'text',
'css' : 'text',
'binary' : 'binary',
'image' : 'binary',
'video' : 'binary',
'audio' : 'binary',
'flash' : 'binary'
};
/*
* Hash with the rule of the <attribute> node in the <content>
* Indicates if the attribute is overridable or not
* true for not-overridable
*/
var contentSealAttr = {
'javascript' : {
'src' : true,
'type' : false
},
'css' : {
'href' : true,
'rel' : false
},
'image' : {
'src' : true,
'alt' : false
},
'video' : {
'src' : true
},
'audio' : {
'src' : true
}
};
// Hash with the rule of the constraint attribute node.
var constraintAttributeRules = {
questions : ['chapter', 'single', 'multiple', 'open', 'numeric', 'date', 'requireParentLoop'],
responses : ['min', 'max'],
controls : ['label', 'textbox', 'checkbox', 'listbox', 'radiobutton', 'responseblock']
};
/*
* Build a new error messag
* @param {String} message Error message
* @return {Error} New error
*/
function newError(message) {
return new Error(util.format.apply(null, arguments));
}
<span id='ADC-Validator'>/**
</span> * Validate the ADC files structure, configuration and logical
*
* @class ADC.Validator
* @private
*/
function Validator(adcDirPath) {
<span id='ADC-Validator-property-rootdir'> /**
</span> * Root dir of the current ADCUtil
*/
this.rootdir = pathHelper.resolve(__dirname, "../../");
<span id='ADC-Validator-property-adcName'> /**
</span> * Name of the ADC
* @type {string}
*/
this.adcName = '';
<span id='ADC-Validator-property-adcDirectoryPath'> /**
</span> * Path to the ADC directory
* @type {string}
*/
this.adcDirectoryPath = adcDirPath ? pathHelper.normalize(adcDirPath) : process.cwd();
<span id='ADC-Validator-property-validators'> /**
</span> * Validators
*
* @type {{current: number, sequence: string[]}}
*/
this.validators = {
current : -1,
sequence : [
'validatePathArg',
'validateADCDirectoryStructure',
'validateFileExtensions',
'validateXMLAgainstXSD',
'initConfigXMLDoc',
'validateADCInfo',
'validateADCInfoConstraints',
'validateADCOutputs',
'validateADCProperties',
'runAutoTests',
'runADCUnitTests'
]
};
<span id='ADC-Validator-property-report'> /**
</span> * Report of the validation
*
* @type {{startTime: null, endTime: null, runs: number, total: number, success: number, warnings: number, errors: number}}
*/
this.report = {
startTime : null,
endTime : null,
runs : 0,
total : 0,
success : 0,
warnings : 0,
errors : 0
};
<span id='ADC-Validator-property-dirResources'> /**
</span> * Map all files in the resources directory
*
* @type {{isExist: boolean, dynamic: {isExist: boolean}, statics: {isExist: boolean}, share: {isExist: boolean}}}
*/
this.dirResources = {
isExist : false,
dynamic : {
isExist : false
},
statics : {
isExist : false
},
share : {
isExist : false
}
};
<span id='ADC-Validator-property-configXmlDoc'> /**
</span> * Config xml document in json format
*/
this.configXmlDoc = null;
<span id='ADC-Validator-property-logger'> /**
</span> * Logger to override with an object
* @type {{writeMessage : function, writeSuccess : function, writeWarning: function, writeError : function}}
*/
this.logger = null;
}
<span id='ADC-Validator-method-constructor'>/**
</span> * Create a new instance of ADC validator
*
* @constructor
* @param {String} adcDirPath Path of the ADC directory
*/
Validator.prototype.constructor = Validator;
<span id='ADC-Validator-method-validate'>/**
</span> * Validate the current ADC instance
*
* @param {Object} [options] Options of validation
* @param {Boolean} [options.test=true] Run unit tests
* @param {Boolean} [options.autoTest=true] Run auto unit tests
* @param {Boolean} [options.xml=true] Validate the config.xml file
* @param {InteractiveADXShell} [options.adxShell] Interactive ADXShell process
* @param {Object} [options.logger] Logger
* @param {Function} [options.writeMessage] Function where regular messages will be print
* @param {Function} [options.writeSuccess] Function where success messages will be print
* @param {Function} [options.writeWarning] Function where warning messages will be print
* @param {Function} [options.writeError] Function where error messages will be print
* @param {Function} [callback] Callback function
* @param {Error} [callback.err] Error
* @param {Object} [callback.report] Validation report
*/
Validator.prototype.validate = function validate(options, callback) {
// Start timer
this.report.startTime = new Date().getTime();
// Swap optional options arguments
if (typeof options === 'function') {
callback = options;
options = null;
}
if (!options) {
options = {
test : true,
autoTest : true,
xml : true
}
}
// Register the end callback for future usage
this.validationCallback = callback;
this._adxShell = (options && options.adxShell) || null;
// Validate according to the options
if (options) {
// Set the logger
if (options.logger) {
this.logger = options.logger;
}
// --no-autoTest
if (options.autoTest === false) { // Check bool value not falsy
this.removeOnSequence(['runAutoTests']);
}
// --no-test
if (options.test === false) { // Check bool value not falsy
this.removeOnSequence(['runADCUnitTests']);
}
// --no-xml
if (options.xml === false) { // Check bool value not falsy
this.removeOnSequence([
'validateXMLAgainstXSD',
'initConfigXMLDoc',
'validateADCInfo',
'validateADCInfoConstraints',
'validateADCOutputs',
'validateADCProperties'
]);
}
}
this.report.total = this.validators.sequence.length;
this.resume(null);
};
<span id='ADC-Validator-method-removeOnSequence'>/**
</span> * Remove the specified validators on the validators sequence
*
* @param {Array} validators Validators to remove
*/
Validator.prototype.removeOnSequence = function removeOnSequence(validators) {
var sequence = this.validators.sequence,
index;
validators.forEach(function (value) {
index = sequence.indexOf(value);
if (index !== -1) {
sequence.splice(index, 1);
}
});
};
<span id='ADC-Validator-method-done'>/**
</span> * Summarize the validation
*
* @param {Error} [err] Last error
*/
Validator.prototype.done = function done(err) {
this.report.endTime = new Date().getTime();
var executionTime = this.report.endTime - this.report.startTime,
report = this.report,
message;
if (err) {
this.writeError(err.message);
}
// Write the summary
this.writeMessage(msg.validationFinishedIn, executionTime);
message = util.format(msg.validationReport,
report.runs,
report.total,
report.success,
report.warnings,
report.errors,
report.total - report.runs);
if (report.errors) {
this.writeError(message);
} else if (report.warnings) {
this.writeWarning(message);
} else {
this.writeSuccess(message);
}
if (typeof this.validationCallback === 'function') {
this.validationCallback(err, this.report);
}
};
<span id='ADC-Validator-method-resume'>/**
</span> * Execute the next validation
*
* @param {Error|void} err Error which occured during the previous validation
*/
Validator.prototype.resume = function resume(err) {
if (err) {
// Mark the error
this.report.errors++;
this.done(err);
return;
}
var validators = this.validators;
// Mark the success
if (validators.current !== -1 && this[validators.sequence[validators.current]]) {
this.report.success++;
}
validators.current++;
if (validators.current >= validators.sequence.length) {
this.done(err);
return;
}
// Search the next validators (recursive call)
var validatorName = validators.sequence[validators.current];
if (!this[validatorName]) {
this.resume(null);
return;
}
// Execute the find validator
// Mark the runs
this.report.runs++;
this[validatorName]();
};
<span id='ADC-Validator-method-writeError'>/**
</span> * Write an error output in the console or in the logger
* @param {String} text Text to write in the console
*/
Validator.prototype.writeError = function writeError(text) {
if (this.logger && typeof this.logger.writeError === 'function') {
this.logger.writeError.apply(this.logger, arguments);
} else {
common.writeError.apply(common, arguments);
}
};
<span id='ADC-Validator-method-writeWarning'>/**
</span> * Write a warning output in the console or in the logger
* @param {String} text Text to write in the console
*/
Validator.prototype.writeWarning = function writeWarning(text) {
if (this.logger && typeof this.logger.writeWarning === 'function') {
this.logger.writeWarning.apply(this.logger, arguments);
} else {
common.writeWarning.apply(common, arguments);
}
};
<span id='ADC-Validator-method-writeSuccess'>/**
</span> * Write a success output in the console or in the logger
* @param {String} text Text to write in the console
*/
Validator.prototype.writeSuccess = function writeSuccess(text) {
if (this.logger && typeof this.logger.writeSuccess === 'function') {
this.logger.writeSuccess.apply(this.logger, arguments);
} else {
common.writeSuccess.apply(common, arguments);
}
};
<span id='ADC-Validator-method-writeMessage'>/**
</span> * Write an arbitrary message in the console or in the logger without specific prefix or in the logger
* @param {String} text Text to write in the console
*/
Validator.prototype.writeMessage = function writeMessage(text) {
if (this.logger && typeof this.logger.writeMessage === 'function') {
this.logger.writeMessage.apply(this.logger, arguments);
} else {
common.writeMessage.apply(common, arguments);
}
};
<span id='ADC-Validator-method-validatePathArg'>/**
</span>* Validate that the `path` argument is correct
*/
Validator.prototype.validatePathArg = function validatePathArg() {
if (!this.adcDirectoryPath) {
this.resume(newError(errMsg.missingArgPath));
return;
}
// Validate the existence of the specify ADC directory
var self = this;
common.dirExists(self.adcDirectoryPath, function verifyADCDirectory(err, exists) {
var er;
if (!exists) {
er = newError(errMsg.noSuchFileOrDirectory, pathHelper.normalize(self.adcDirectoryPath));
} else {
self.writeSuccess(successMsg.pathValidate);
}
self.resume(er);
});
};
<span id='ADC-Validator-method-validateADCDirectoryStructure'>/**
</span> * Validate the structure of the ADC directory
*/
Validator.prototype.validateADCDirectoryStructure = function validateADCDirectoryStructure() {
// Verify if the config.xml exists
var self = this;
fs.exists(pathHelper.join(self.adcDirectoryPath, common.CONFIG_FILE_NAME), function verifyConfigFileExist(exists) {
var resourcesPath = pathHelper.join(self.adcDirectoryPath, common.RESOURCES_DIR_NAME),
dirResources = self.dirResources;
// Check the resources directory
function loadResources() {
common.dirExists(resourcesPath, function initResourcesFileMap(er, find) {
if (!find) {
self.resume(null);
return;
}
dirResources.isExist = true;
loadDynamic();
});
}
// Check the dynamic directory
function loadDynamic() {
common.dirExists(pathHelper.join(resourcesPath, common.DYNAMIC_DIR_NAME), function initDynamicFileMap(er, find) {
var dirDynamic = dirResources.dynamic;
dirDynamic.isExist = find;
if (find) {
try {
var files = fs.readdirSync(pathHelper.join(resourcesPath, common.DYNAMIC_DIR_NAME));
files.forEach(function (file) {
if (common.isIgnoreFile(file)) {
return;
}
dirDynamic[file.toLocaleLowerCase()] = file;
})
} catch (ex) {
// Do nothing
}
}
loadStatic();
});
}
// Check the static directory
function loadStatic(){
common.dirExists(pathHelper.join(resourcesPath, common.STATIC_DIR_NAME), function initStaticFileMap(er, find) {
var dirStatic = dirResources.statics;
dirStatic.isExist = find;
if (find) {
try {
var files = fs.readdirSync(pathHelper.join(resourcesPath, common.STATIC_DIR_NAME));
files.forEach(function (file) {
if (common.isIgnoreFile(file)) {
return;
}
dirStatic[file.toLocaleLowerCase()] = file;
})
} catch (ex) {
// Do nothing
}
}
loadShare();
});
}
// Check the share directory and resume the validation
function loadShare() {
common.dirExists(pathHelper.join(resourcesPath, common.SHARE_DIR_NAME), function initShareFileMap(er, find) {
var dirShare = dirResources.share;
dirShare.isExist = find;
if (find) {
try {
var files = fs.readdirSync(pathHelper.join(resourcesPath, common.SHARE_DIR_NAME));
files.forEach(function (file) {
if (common.isIgnoreFile(file)) {
return;
}
dirShare[file.toLocaleLowerCase()] = file;
})
} catch (ex) {
// Do nothing
}
}
self.resume(null);
});
}
if (!exists) {
self.resume(newError(errMsg.noConfigFile));
} else {
self.writeSuccess(successMsg.directoryStructureValidate);
loadResources();
}
});
};
<span id='ADC-Validator-method-validateFileExtensions'>/**
</span> * Validate all file extension against the while list and the black list
*/
Validator.prototype.validateFileExtensions = function validateFileExtensions() {
var dirResources = this.dirResources,
dir = [dirResources.dynamic, dirResources.statics, dirResources.share],
current, i, l, key, match;
if (!dirResources.isExist) {
this.resume(null);
}
for (i = 0, l = dir.length; i < l; i++) {
current = dir[i];
if (current.isExist) {
for (key in current) {
if (current.hasOwnProperty(key) && key !== 'isExist') {
// Test against the black list
match = key.toString().match(fileExt.blacklist);
if (match) {
this.resume(newError(errMsg.fileExtensionForbidden, match[0]));
return;
}
// Test against the white list
match = key.toString().match(fileExt.whitelist);
if (!match) {
this.report.warnings++;
this.writeWarning(warnMsg.untrustExtension, key);
}
}
}
}
}
this.writeSuccess(successMsg.fileExtensionValidate);
this.resume(null);
};
<span id='ADC-Validator-method-validateXMLAgainstXSD'>/**
</span> * Validate the config.xml file of the ADC against the XSD schema
*/
Validator.prototype.validateXMLAgainstXSD = function validateXMLAgainstXSD() {
var exec = require('child_process').exec,
xmlLintPath = pathHelper.join(this.rootdir, common.XML_LINT_PATH),
xmlSchemaPath = pathHelper.join(this.rootdir, common.SCHEMA_PATH, common.SCHEMA_CONFIG),
xmlPath = pathHelper.join(this.adcDirectoryPath, common.CONFIG_FILE_NAME),
self = this,
commandLine = '"' + xmlLintPath + '" --noout --schema "' + xmlSchemaPath + '" "' + xmlPath + '"';
exec(commandLine, function callback(err) {
if (!err) {
self.writeSuccess(successMsg.xsdValidate);
}
self.resume(err);
});
};
<span id='ADC-Validator-method-initConfigXMLDoc'>/**
</span> * Initialize the XMLDoc using the config.xml
*/
Validator.prototype.initConfigXMLDoc = function initConfigXMLDoc() {
var self = this;
fs.readFile(pathHelper.join(self.adcDirectoryPath, common.CONFIG_FILE_NAME), 'utf8', function readConfigXMLFile(err, data) {
if (err) {
self.resume(err);
return;
}
// Remove the BOM characters in UTF-8 string
data = data.replace(/^\uFEFF/, '');
xml2js.parseString(data, function parseXML(err, result) {
self.configXmlDoc = result;
if (!err) {
self.writeSuccess(successMsg.xmlInitialize);
}
self.resume(err);
});
});
};
<span id='ADC-Validator-method-validateADCInfo'>/**
</span> * Validate the info of the ADC config file
*/
Validator.prototype.validateADCInfo = function validateADCInfo() {
var infosEl = this.configXmlDoc.control.info && this.configXmlDoc.control.info[0],
nameEl = infosEl && infosEl.name && infosEl.name[0];
if (!infosEl) {
this.resume(newError(errMsg.missingInfoNode));
return;
}
if (!nameEl) {
this.resume(newError(errMsg.missingOrEmptyNameNode));
return;
}
this.adcName = nameEl;
this.writeSuccess(successMsg.xmlInfoValidate);
this.resume(null);
};
<span id='ADC-Validator-method-validateADCInfoConstraints'>/**
</span> * Validate the info/constraints of the ADC config file
*/
Validator.prototype.validateADCInfoConstraints = function validateADCInfoConstraints() {
var constraintsEl = this.configXmlDoc.control.info[0].constraints[0],
constraints = constraintsEl.constraint || [],
constraintsOn = {
questions : 0,
responses : 0,
controls : 0
}, attr, i, l, key, hasRule = false;
for (i = 0, l = constraints.length; i < l; i++) {
hasRule = false;
attr = constraints[i].$ || {};
if (!attr.on) {
continue;
}
// Validate the duplicate constraints
constraintsOn[attr.on]++;
if (constraintsOn[attr.on] > 1) {
this.resume(newError(errMsg.duplicateConstraints, attr.on));
return;
}
// Validate the attribute logic
for (key in attr) {
if (attr.hasOwnProperty(key) && key !== 'on') {
if (constraintAttributeRules[attr.on].indexOf(key) === -1) {
this.resume(newError(errMsg.invalidConstraintAttribute, attr.on, key));
return;
}
if (key !== 'min' && key !== 'max') {
if (attr[key] == '1' || attr[key] == 'true') {
hasRule = true;
}
} else {
hasRule = true;
}
}
}
// No rule specified
if (!hasRule) {
this.resume(newError(errMsg.noRuleOnConstraint, attr.on));
return;
}
}
if (!constraintsOn.questions) {
this.resume(newError(errMsg.requireConstraintOn, 'questions'));
return;
}
if (!constraintsOn.controls) {
this.resume(newError(errMsg.requireConstraintOn, 'controls'));
return;
}
this.writeSuccess(successMsg.xmlInfoConstraintsValidate);
this.resume(null);
};
<span id='ADC-Validator-method-validateADCOutputs'>/**
</span> * Validate the outputs of the ADC config file
*/
Validator.prototype.validateADCOutputs = function validateADCOutputs() {
var outputsEl = this.configXmlDoc.control.outputs[0],
outputs = outputsEl.output,
conditions = {},
outputsEmptyCondition = [],
htmlFallBackCount = 0,
lastOutput,
defaultGeneration, i, l, output, id, condition, err;
for (i = 0, l = outputs.length; i < l; i++) {
output = outputs[i];
id = output.$.id;
condition = output.condition && output.condition[0];
defaultGeneration = output.$.defaultGeneration || false;
if (!condition) {
outputsEmptyCondition.push(id);
}
if (condition && conditions[condition]) {
this.report.warnings++;
this.writeWarning(warnMsg.duplicateOutputCondition, conditions[condition], id);
}
conditions[condition] = id;
lastOutput = {
id : id,
defaultGeneration : defaultGeneration,
contents : output.content || [],
condition : condition,
dynamicContentCount : 0,
javascriptContentCount : 0,
flashContentCount : 0
};
err = this.validateADCContents(lastOutput);
if (defaultGeneration || !lastOutput.javascriptContentCount) {
htmlFallBackCount++;
}
if (err) {
this.resume(err);
return;
}
}
if (outputsEmptyCondition.length > 1) {
err = newError(errMsg.tooManyEmptyCondition, outputsEmptyCondition.join(", "));
}
if (!htmlFallBackCount) {
this.report.warnings++;
this.writeWarning(warnMsg.noHTMLFallBack);
}
if (!err) {
this.writeSuccess(successMsg.xmlOutputsValidate);
}
this.resume(err);
};
<span id='ADC-Validator-method-validateADCContents'>/**
</span> * Validate the contents of an ADC output
*
* @param {Object} output Helper output object
* @return {Error|void} Return the error or null when no error.
*/
Validator.prototype.validateADCContents = function validateADCContents(output) {
var contents = output.contents,
i, l,
err = null,
condition = output.condition || "";
if (contents.length && !this.dirResources.isExist) {
return newError(errMsg.noResourcesDirectory);
}
for (i = 0, l = contents.length; i < l; i++) {
err = this.validateADCContent(output, contents[i]);
if (err) {
return err;
}
}
if (!output.defaultGeneration && !output.dynamicContentCount) {
return newError(errMsg.dynamicFileRequire, output.id);
}
if (!output.defaultGeneration && output.javascriptContentCount && !/browser\.support\("javascript"\)/gi.test(condition)) {
this.report.warnings++;
this.writeWarning(warnMsg.javascriptUseWithoutBrowserCheck, output.id);
}
if (!output.defaultGeneration && output.flashContentCount && !/browser\.support\("flash"\)/gi.test(condition)) {
this.report.warnings++;
this.writeWarning(warnMsg.flashUseWithoutBrowserCheck, output.id);
}
return err;
};
<span id='ADC-Validator-method-validateADCContent'>/**
</span> * Validate the content of an ADC output
*
* @param {Object} output Helper output object
* @param {Object} content Content node
* @return {Error|void} Return the error or null when no error.
*/
Validator.prototype.validateADCContent = function validateADCContent(output, content) {
var atts = content.$,
type = atts.type,
position = atts.position,
mode = atts.mode,
key = (mode !== 'static') ? mode : 'statics',
fileName = atts.fileName,
yieldNode = content['yield'] || [],
dirResources = this.dirResources;
// Missing directory
if (!dirResources[key].isExist) {
return newError(errMsg.cannotFindDirectory, mode);
}
// Missing file
if (!dirResources[key][fileName.toLocaleLowerCase()]) {
return newError(errMsg.cannotFindFileInDirectory, output.id, fileName, mode);
}
// A binary file could not be dynamic
if (mode === 'dynamic' && contentType[type] === 'binary') {
return newError(errMsg.typeCouldNotBeDynamic, output.id, type, fileName);
}
// A binary file require a 'yield' node or 'position=none'
if (type === 'binary' && position !== 'none' && !yieldNode.length) {
return newError(errMsg.yieldRequireForBinary, output.id, fileName);
}
// Increment the information about the dynamic content
if (position !== 'none' && mode === 'dynamic' && (type === 'javascript' || type === 'html')) {
output.dynamicContentCount++;
}
// Increment the information about the javascript content
if (type === 'javascript') {
output.javascriptContentCount++;
}
// Increment the information about the flash content
if (type === 'flash') {
output.flashContentCount++;
}
// Validate attribute
return this.validateADCContentAttribute(output, content);
};
<span id='ADC-Validator-method-validateADCContentAttribute'>/**
</span> * Validate the attribute tag of the content node
*
* @param {Object} output Helper output object
* @param {Object} content Content node
* @return {Error|void} Return error or null when no error
*/
Validator.prototype.validateADCContentAttribute = function validateADCContentAttribute(output, content) {
if (!content.attribute || !content.attribute.length) {
return null;
}
var atts = content.$,
type = atts.type,
mode = atts.mode,
fileName = atts.fileName,
attributes = content.attribute,
attribute,
attName,
attMap = {},
i, l;
// Attribute nodes are ignored for the following type
if (/(text|binary|html|flash)/.test(type)) {
this.report.warnings++;
this.writeWarning(warnMsg.attributeNodeWillBeIgnored, output.id, type, fileName);
}
// Attribute nodes are ignored for dynamic mode
if (mode === 'dynamic') {
this.report.warnings++;
this.writeWarning(warnMsg.attributeNodeAndDynamicContent, output.id, fileName);
}
// Attribute nodes are ignored with yield
if (content['yield'] && content['yield'].length) {
this.report.warnings++;
this.writeWarning(warnMsg.attributeNodeAndYieldNode, output.id, fileName);
}
for (i = 0, l = attributes.length; i < l; i++) {
attribute = attributes[i];
attName = (attribute.$ && attribute.$.name && attribute.$.name.toLocaleLowerCase()) || '';
if (contentSealAttr[type] && contentSealAttr[type][attName]) {
return newError(errMsg.attributeNotOverridable, output.id, attName, fileName);
}
if (attMap[attName]) {
return newError(errMsg.duplicateAttributeNode, output.id, attName, fileName);
}
if (attName) {
attMap[attName] = attName;
}
}
return null;
};
<span id='ADC-Validator-method-validateADCProperties'>/**
</span> * Validate the ADC properties node
*/
Validator.prototype.validateADCProperties = function validateADCProperties() {
var propertiesEl = (this.configXmlDoc.control.properties && this.configXmlDoc.control.properties[0]) || {},
categories = propertiesEl.category || [],
properties = propertiesEl.property || [];
if (!properties.length && !categories.length) {
this.report.warnings++;
this.writeWarning(warnMsg.noProperties);
}
this.writeSuccess(successMsg.xmlPropertiesValidate);
this.resume(null);
};
<span id='ADC-Validator-method-runTests'>/**
</span> * Run the ADC Unit tests process with specify arguments
* @param {Array} args
* @param {String} message
*/
Validator.prototype.runTests = function runTests(args, message) {
var self = this;
// Validate the existence of the specify unit test directory
common.dirExists(pathHelper.join(self.adcDirectoryPath, common.UNIT_TEST_DIR_PATH), function verifyUnitTestDirectory(err, exists) {
if (!exists) {
self.resume(null);
return ;
}
function execCallback(err, data, stderr) {
if (stderr) {
err = new Error(stderr);
}
self.writeMessage(message);
if (err) {
self.report.warnings++;
self.writeWarning("\r\n" + err.message);
if (data) {
self.writeMessage(data);
}
} else {
self.writeMessage(data);
self.writeSuccess(successMsg.adcUnitSucceed);
}
self.resume(null);
}
if (!self._adxShell) {
var execFile = require('child_process').execFile;
execFile('.\\' + common.ADC_UNIT_PROCESS_NAME, args, {
cwd : pathHelper.join(self.rootdir, common.ADC_UNIT_DIR_PATH),
env : process.env
}, execCallback);
} else {
var escapedArgs = [];
for (var i = 0, l = args.length; i < l; i += 1) {
escapedArgs.push('"' + args[i] + '"');
}
self._adxShell.exec('test ' + escapedArgs.join(' '), execCallback);
}
});
};
<span id='ADC-Validator-method-runAutoTests'>/**
</span> * Run the ADC unit tests auto-generated
*/
Validator.prototype.runAutoTests = function runAutoTests() {
this.runTests(['--auto', this.adcDirectoryPath], msg.runningAutoUnit);
};
<span id='ADC-Validator-method-runADCUnitTests'>/**
</span> * Run the ADC unit tests
*/
Validator.prototype.runADCUnitTests = function runADCUnitTests() {
this.runTests([this.adcDirectoryPath], msg.runningADCUnit);
};
// Export the Validator object
exports.Validator = Validator;
/*
* Validate an ADC (CLI)
*
* @param {Command} program Commander object which hold the arguments pass to the program
* @param {String} path Path to the ADC directory
* @param {Function} callback Callback function to run at the end it take a single Error argument
*/
exports.validate = function validate(program, path, callback) {
var validator = new Validator(path);
validator.validate(program, callback);
};
</pre>
</body>
</html>