diff --git a/Gemfile b/Gemfile
index 07b1b93b5..ff1ed012c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -36,6 +36,7 @@ gem 'digest-sha3', :git => "http://github.com/izetex/digest-sha3-ruby"
gem 'packetfu'
gem 'net-ntp'
gem 'CFPropertyList'
+gem 'artii'
#development only gems go here
group :test, :development do
diff --git a/Gemfile.lock b/Gemfile.lock
index 1868009da..02838b4b9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -26,6 +26,7 @@ GEM
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
+ artii (2.1.2)
bases (1.0.2)
bcrypt (3.1.13)
chunky_png (1.3.11)
@@ -151,6 +152,7 @@ PLATFORMS
DEPENDENCIES
CFPropertyList
+ artii
bases
bcrypt
braille!
diff --git a/lib/helpers/constants.rb b/lib/helpers/constants.rb
index 5f5fc865d..606fe1f0a 100644
--- a/lib/helpers/constants.rb
+++ b/lib/helpers/constants.rb
@@ -44,6 +44,7 @@ WORDLISTS_DIR = "#{ROOT_DIR}/lib/resources/wordlists"
LINELISTS_DIR = "#{ROOT_DIR}/lib/resources/linelists"
BLACKLISTED_WORDS_FILE = "#{ROOT_DIR}/lib/resources/blacklisted_words/blacklist.txt"
IMAGES_DIR = "#{ROOT_DIR}/lib/resources/images"
+ASCII_ART_DIR = "#{ROOT_DIR}/lib/resources/ascii_art"
PASSWORDLISTS_DIR = "#{ROOT_DIR}/lib/resources/passwordlists"
# Path to build puppet modules
@@ -77,4 +78,4 @@ RETRIES_LIMIT = 10
# Version number of SecGen
# e.g. [release state (0 = alpha, 3 = final release)].[Major bug fix].[Minor bug fix].[Cosmetic or other features]
-VERSION_NUMBER = '0.0.1.1'
\ No newline at end of file
+VERSION_NUMBER = '0.0.1.1'
diff --git a/lib/objects/post_provision_test.rb b/lib/objects/post_provision_test.rb
index 99e4c9041..a7351f4c0 100644
--- a/lib/objects/post_provision_test.rb
+++ b/lib/objects/post_provision_test.rb
@@ -111,7 +111,10 @@ class PostProvisionTest
def get_json_inputs
json_inputs_path = "#{File.expand_path('../', self.module_path)}/secgen_functions/files/json_inputs/*"
json_inputs_files = Dir.glob(json_inputs_path)
- json_inputs_files.delete_if {|path| !path.include?(self.module_name)}
+ json_inputs_files.delete_if do |path|
+ end_path = path.split('/')[-1]
+ !end_path.include?(self.module_name)
+ end
if json_inputs_files.size > 0
return JSON.parse(Base64.strict_decode64(File.read(json_inputs_files.first)))
end
diff --git a/lib/objects/system.rb b/lib/objects/system.rb
index 1012fe9eb..39208946f 100644
--- a/lib/objects/system.rb
+++ b/lib/objects/system.rb
@@ -329,7 +329,8 @@ class System
puts stderr
outputs = stdout.chomp
- unless status
+ # stop if any generators/encoders fail to execute
+ unless status == 0
Print.err "Module failed to run (#{command})"
# TODO: this works, but subsequent attempts at resolving the scenario always fail ("Error can't add no data...")
raise 'failed'
diff --git a/lib/resources/ascii_art/README-sources.md b/lib/resources/ascii_art/README-sources.md
new file mode 100644
index 000000000..3f4f99315
--- /dev/null
+++ b/lib/resources/ascii_art/README-sources.md
@@ -0,0 +1,2 @@
+Ascii art:
+https://www.asciiart.eu
diff --git a/lib/resources/ascii_art/computers/laptop b/lib/resources/ascii_art/computers/laptop
new file mode 100644
index 000000000..b072cafde
--- /dev/null
+++ b/lib/resources/ascii_art/computers/laptop
@@ -0,0 +1,13 @@
+ +--------------+
+ |.------------.|
+ || ||
+ || ||
+ || ||
+ || ||
+ |+------------+|
+ +-..--------..-+
+ .--------------.
+ / /============\ \
+ / /==============\ \
+/____________________\
+\____________________/
diff --git a/lib/resources/ascii_art/computers/pc b/lib/resources/ascii_art/computers/pc
new file mode 100644
index 000000000..3525bb826
--- /dev/null
+++ b/lib/resources/ascii_art/computers/pc
@@ -0,0 +1,13 @@
+ __________
+ .'----------`.
+ | .--------. |
+ | |########| | __________
+ | |########| | /__________\
+.--------| `--------' |------| --=-- |-------------.
+| `----,-.-----' |o ====== | |
+| ______|_|_______ |__________| |
+| / %%%%%%%%%%%% \ |
+| / %%%%%%%%%%%%%% \ |
+| ^^^^^^^^^^^^^^^^^^^^ |
++-----------------------------------------------------+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/lib/resources/ascii_art/computers/pc2 b/lib/resources/ascii_art/computers/pc2
new file mode 100644
index 000000000..07fb52a00
--- /dev/null
+++ b/lib/resources/ascii_art/computers/pc2
@@ -0,0 +1,15 @@
+ ___________________
+ | _______________ |
+ | |XXXXXXXXXXXXX| |
+ | |XXXXXXXXXXXXX| |
+ | |XXXXXXXXXXXXX| |
+ | |XXXXXXXXXXXXX| |
+ | |XXXXXXXXXXXXX| |
+ |_________________|
+ _[_______]_
+ ___[___________]___
+| [_____] []|__
+| [_____] []| \__
+L___________________J \ \___\/
+ ___________________ /\
+/###################\ (__)
diff --git a/lib/resources/ascii_art/computers/pc3 b/lib/resources/ascii_art/computers/pc3
new file mode 100644
index 000000000..5af04ba0a
--- /dev/null
+++ b/lib/resources/ascii_art/computers/pc3
@@ -0,0 +1,18 @@
+ _______
+ | ___ o|
+ |[_-_]_ |
+ ______________ |[_____]|
+ |.------------.| |[_____]|
+ || || |[====o]|
+ || || |[_.--_]|
+ || || |[_____]|
+ || || | :|
+ ||____________|| | :|
+ .==.|"" ...... |.==.| :|
+ |::| '-.________.-' |::|| :|
+ |''| (__________)-.|''||______:|
+ `""`_.............._\""`______
+ /:::::::::::'':::\`;'-.-. `\
+ /::=========.:.-::"\ \ \--\ \
+ \`""""""""""""""""`/ \ \__) \
+jgs `""""""""""""""""` '========'
diff --git a/lib/resources/ascii_art/computers/server b/lib/resources/ascii_art/computers/server
new file mode 100644
index 000000000..06e648e74
--- /dev/null
+++ b/lib/resources/ascii_art/computers/server
@@ -0,0 +1,30 @@
+ ,=====================.
+ | |
+ |.-------------------.|
+ ||[ _ o . . _ ]_||
+ |`-------------------'|
+ || ||
+ |`-------------------'|
+ || ||
+ |`-------------------'|
+ || ||
+ |`-----------------_-'|
+ ||[=========]| o (@) |
+ |`---------=='/u\ --- |
+ |------_--------------|
+ | (/) (_) []|
+ |---==--==----------==|
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||||||||
+ |||||||||||||||||dxm|||
+ |||||||||||||||||||||||
+ |=====================|
+ .' `.
+"""""""""""""""""""""""""""
diff --git a/lib/schemas/scenario_schema.xsd b/lib/schemas/scenario_schema.xsd
index e1038d354..f48d8f537 100644
--- a/lib/schemas/scenario_schema.xsd
+++ b/lib/schemas/scenario_schema.xsd
@@ -88,6 +88,8 @@
+
+
diff --git a/lib/templates/Vagrantfile.erb b/lib/templates/Vagrantfile.erb
index df4312e0f..356dddb0f 100644
--- a/lib/templates/Vagrantfile.erb
+++ b/lib/templates/Vagrantfile.erb
@@ -173,7 +173,7 @@ end
<% # Static oVirt networking -%>
<% if (@options.has_key? :ovirtuser) && (@options.has_key? :ovirtpass) -%>
<% interface = 'ens3' -%>
-<% if @ovirt_base_template and @ovirt_base_template =~ /kali|debian_desktop_kde|debian_server/ -%>
+<% if @ovirt_base_template and @ovirt_base_template =~ /kali|debian_desktop_kde|debian_wheezy_server/ -%>
<% interface = 'eth0' -%>
<% end -%>
# use some shell scripting to identify the name of the network interface (eth0/ens3/...), and set the IP address statically
diff --git a/modules/bases/debian_stretch/secgen_metadata.xml b/modules/bases/debian_stretch_server/secgen_metadata.xml
similarity index 100%
rename from modules/bases/debian_stretch/secgen_metadata.xml
rename to modules/bases/debian_stretch_server/secgen_metadata.xml
diff --git a/modules/bases/debian_puppet_32/secgen_metadata.xml b/modules/bases/debian_wheezy_server/secgen_metadata.xml
similarity index 95%
rename from modules/bases/debian_puppet_32/secgen_metadata.xml
rename to modules/bases/debian_wheezy_server/secgen_metadata.xml
index 284255326..8fa3c38a0 100644
--- a/modules/bases/debian_puppet_32/secgen_metadata.xml
+++ b/modules/bases/debian_wheezy_server/secgen_metadata.xml
@@ -17,7 +17,7 @@
Debian 7.8 (wheezy) 32-bit (i386)https://app.vagrantup.com/secgen/boxes/debian_wheezy_puppet/versions/1.0.2/providers/virtualbox.boxhttps://app.vagrantup.com/redwiz666/boxes/debian_wheezy_puppet/versions/1.0.0/providers/vmware_esxi.box
- debian_server
+ debian_wheezy_serverhttps://atlas.hashicorp.com/puppetlabsvarious
diff --git a/modules/encoders/format/ascii_art/ascii_art.pp b/modules/encoders/format/ascii_art/ascii_art.pp
new file mode 100644
index 000000000..e69de29bb
diff --git a/modules/encoders/format/ascii_art/manifests/.no_puppet b/modules/encoders/format/ascii_art/manifests/.no_puppet
new file mode 100644
index 000000000..e69de29bb
diff --git a/modules/encoders/format/ascii_art/secgen_local/local.rb b/modules/encoders/format/ascii_art/secgen_local/local.rb
new file mode 100644
index 000000000..d64c903d9
--- /dev/null
+++ b/modules/encoders/format/ascii_art/secgen_local/local.rb
@@ -0,0 +1,37 @@
+#!/usr/bin/ruby
+require_relative '../../../../../lib/objects/local_string_encoder.rb'
+require 'artii'
+
+class ASCIIArtEncoder < StringEncoder
+ attr_accessor :font
+
+ def initialize
+ super
+ self.module_name = 'Ascii Art Encoder'
+ self.font = []
+ end
+
+ def encode(str)
+ # if more than one font is specified, randomly choose one for every string that is encoded
+ artii = Artii::Base.new :font => self.font.sample
+ artii.asciify(str)
+ end
+
+ def process_options(opt, arg)
+ super
+ case opt
+ # Removes any non-alphabet characters
+ when '--font'
+ self.font << arg
+ else
+ # do nothing
+ end
+ end
+
+ def get_options_array
+ super + [['--font', GetoptLong::OPTIONAL_ARGUMENT]]
+ end
+
+end
+
+ASCIIArtEncoder.new.run
diff --git a/modules/encoders/format/ascii_art/secgen_metadata.xml b/modules/encoders/format/ascii_art/secgen_metadata.xml
new file mode 100644
index 000000000..09c4cfda5
--- /dev/null
+++ b/modules/encoders/format/ascii_art/secgen_metadata.xml
@@ -0,0 +1,61 @@
+
+
+
+ Text to ASCII Art
+ Z. Cliffe Schreuders
+ MIT
+ Outputs an ASCII art version of the text. Works best with short strings.
+
+
+ string_format_encoder
+ linux
+ windows
+
+ strings_to_encode
+ font
+
+
+
+
+ banner
+ big
+ bubble
+ bulbhead
+ contessa
+ doom
+ drpepper
+ fourtops
+ invita
+ italic
+ larry3d
+ maxfour
+ mini
+ moscow
+ ntgreek
+ ogre
+ pawp
+ pebbles
+ puffy
+ rectangles
+ serifcap
+ short
+ slant
+ slscript
+ small
+ smisome1
+ smslant
+ speed
+ standard
+ straight
+ twopoint
+
+
+
+
+
+
+ encoded_strings
+
+
diff --git a/modules/generators/compression/zip/secgen_local/local.rb b/modules/generators/compression/zip/secgen_local/local.rb
index 08c933f0b..b12416166 100644
--- a/modules/generators/compression/zip/secgen_local/local.rb
+++ b/modules/generators/compression/zip/secgen_local/local.rb
@@ -33,9 +33,9 @@ class ZipGenerator < StringEncoder
zip_file.get_output_stream(self.file_name) { |os|
os.write data
}
- file_contents = File.binread(zip_file_path)
- FileUtils.rm(zip_file_path)
end
+ file_contents = File.binread(zip_file_path)
+ FileUtils.rm(zip_file_path)
end
self.outputs << Base64.strict_encode64(file_contents)
end
@@ -65,4 +65,4 @@ class ZipGenerator < StringEncoder
end
end
-ZipGenerator.new.run
\ No newline at end of file
+ZipGenerator.new.run
diff --git a/modules/generators/image/random_jpg/secgen_local/local.rb b/modules/generators/image/random_jpg/secgen_local/local.rb
index 136b4914f..04d80a02d 100644
--- a/modules/generators/image/random_jpg/secgen_local/local.rb
+++ b/modules/generators/image/random_jpg/secgen_local/local.rb
@@ -1,6 +1,7 @@
#!/usr/bin/ruby
require 'base64'
require 'rmagick'
+require 'fileutils'
require_relative '../../../../../lib/objects/local_string_encoder.rb'
class ImageGenerator < StringEncoder
attr_accessor :selected_image_path
@@ -23,6 +24,7 @@ class ImageGenerator < StringEncoder
image.write(tmp_file_path)
self.outputs << Base64.strict_encode64(File.binread(tmp_file_path))
+ FileUtils.rm(tmp_file_path)
end
def encoding_print_string
@@ -30,4 +32,4 @@ class ImageGenerator < StringEncoder
end
end
-ImageGenerator.new.run
\ No newline at end of file
+ImageGenerator.new.run
diff --git a/modules/generators/messages/random_ascii_art/manifests/.no_puppet b/modules/generators/messages/random_ascii_art/manifests/.no_puppet
new file mode 100644
index 000000000..e69de29bb
diff --git a/modules/generators/messages/random_ascii_art/random_ascii_art.pp b/modules/generators/messages/random_ascii_art/random_ascii_art.pp
new file mode 100644
index 000000000..e69de29bb
diff --git a/modules/generators/messages/random_ascii_art/secgen_local/local.rb b/modules/generators/messages/random_ascii_art/secgen_local/local.rb
new file mode 100644
index 000000000..106ea6c6d
--- /dev/null
+++ b/modules/generators/messages/random_ascii_art/secgen_local/local.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/ruby
+require 'base64'
+require_relative '../../../../../lib/objects/local_string_encoder.rb'
+class AsciiImageGenerator < StringEncoder
+ attr_accessor :selected_art_path
+
+ def initialize
+ super
+ self.module_name = 'Random Ascii Art Image Generator'
+ self.selected_art_path = Dir["#{ASCII_ART_DIR}/computers/*"].sample
+ end
+
+ def encode_all
+ self.outputs << File.read(self.selected_art_path)
+ end
+
+ def encoding_print_string
+ 'Random ascii image generator: ' + self.selected_art_path
+ end
+end
+
+AsciiImageGenerator.new.run
diff --git a/modules/generators/messages/random_ascii_art/secgen_metadata.xml b/modules/generators/messages/random_ascii_art/secgen_metadata.xml
new file mode 100644
index 000000000..cf0ff1233
--- /dev/null
+++ b/modules/generators/messages/random_ascii_art/secgen_metadata.xml
@@ -0,0 +1,19 @@
+
+
+
+ Random ASCII Art Generator
+ Z. Cliffe Schreuders
+ MIT
+ Selects and outputs random ascii art image from the lib/resources/ascii_art/computers directory.
+
+ message_generator
+ ascii_art_generator
+ local_calculation
+ linux
+ windows
+
+ ascii_art
+
+
diff --git a/modules/generators/structured_content/person/secgen_metadata.xml b/modules/generators/structured_content/person/secgen_metadata.xml
index 31c1eefd0..229df1fd8 100644
--- a/modules/generators/structured_content/person/secgen_metadata.xml
+++ b/modules/generators/structured_content/person/secgen_metadata.xml
@@ -41,7 +41,7 @@
-
+
diff --git a/modules/services/unix/irc/irc2/manifests/config.pp b/modules/services/unix/irc/irc2/manifests/config.pp
index b695b652c..cf66fbc7a 100644
--- a/modules/services/unix/irc/irc2/manifests/config.pp
+++ b/modules/services/unix/irc/irc2/manifests/config.pp
@@ -1,4 +1,4 @@
-class irc2::config{
+class irc2::config {
service { 'ircd-irc2':
enable => true,
ensure => 'running',
diff --git a/modules/services/unix/irc/irc2/manifests/install.pp b/modules/services/unix/irc/irc2/manifests/install.pp
index 0c8efb535..8ccd8657c 100644
--- a/modules/services/unix/irc/irc2/manifests/install.pp
+++ b/modules/services/unix/irc/irc2/manifests/install.pp
@@ -1,5 +1,5 @@
-class irc2::install{
- package { ['ircd-irc2']:
+class irc2::install {
+ package { 'ircd-irc2':
ensure => 'installed',
}
}
diff --git a/modules/services/unix/irc/irc2/secgen_metadata.xml b/modules/services/unix/irc/irc2/secgen_metadata.xml
index 7003e5abf..2fecad5ac 100644
--- a/modules/services/unix/irc/irc2/secgen_metadata.xml
+++ b/modules/services/unix/irc/irc2/secgen_metadata.xml
@@ -20,6 +20,7 @@
ircd
+
.*Debian.*Stretch.*
diff --git a/modules/services/unix/irc/ircd_hybrid/ircd_hybrid.pp b/modules/services/unix/irc/ircd_hybrid/ircd_hybrid.pp
new file mode 100644
index 000000000..6b07edba1
--- /dev/null
+++ b/modules/services/unix/irc/ircd_hybrid/ircd_hybrid.pp
@@ -0,0 +1,2 @@
+include ircd_hybrid::install
+include ircd_hybrid::config
diff --git a/modules/services/unix/irc/ircd_hybrid/manifests/config.pp b/modules/services/unix/irc/ircd_hybrid/manifests/config.pp
new file mode 100644
index 000000000..2996e601b
--- /dev/null
+++ b/modules/services/unix/irc/ircd_hybrid/manifests/config.pp
@@ -0,0 +1,6 @@
+class ircd_hybrid::config {
+ service { 'ircd-hybrid':
+ enable => true,
+ ensure => 'running',
+ }
+}
diff --git a/modules/services/unix/irc/ircd_hybrid/manifests/install.pp b/modules/services/unix/irc/ircd_hybrid/manifests/install.pp
new file mode 100644
index 000000000..5711c30d4
--- /dev/null
+++ b/modules/services/unix/irc/ircd_hybrid/manifests/install.pp
@@ -0,0 +1,5 @@
+class ircd_hybrid::install {
+ package { 'ircd-hybrid':
+ ensure => 'installed',
+ }
+}
diff --git a/modules/services/unix/irc/ircd_hybrid/secgen_metadata.xml b/modules/services/unix/irc/ircd_hybrid/secgen_metadata.xml
new file mode 100644
index 000000000..c3c0ebb9a
--- /dev/null
+++ b/modules/services/unix/irc/ircd_hybrid/secgen_metadata.xml
@@ -0,0 +1,33 @@
+
+
+
+ IRC Server ircd-hybrid
+ Z. Cliffe Schreuders
+ MIT
+ A lightweight, high-performance internet relay chat daemon.
+
+
+ ircd
+ linux
+
+
+ ircd-hybrid
+ MIT
+
+
+ ircd
+
+
+
+ .*Kali.*
+
+
+
+ .*Wheezy.*
+
+
+ update
+
+
diff --git a/modules/services/unix/irc/ircd_hybrid/secgen_test/ircd_hybrid.rb b/modules/services/unix/irc/ircd_hybrid/secgen_test/ircd_hybrid.rb
new file mode 100644
index 000000000..7761fac90
--- /dev/null
+++ b/modules/services/unix/irc/ircd_hybrid/secgen_test/ircd_hybrid.rb
@@ -0,0 +1,17 @@
+require_relative '../../../../../lib/post_provision_test'
+
+class IRC2Test < PostProvisionTest
+ def initialize
+ self.module_name = 'irc2'
+ self.module_path = get_module_path(__FILE__)
+ super
+ self.port = 6667
+ end
+
+ def test_module
+ super
+ test_service_up
+ end
+end
+
+IRC2Test.new.run
\ No newline at end of file
diff --git a/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/manifests/install.pp b/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/manifests/install.pp
index b45b4a3d4..e2ce410e1 100644
--- a/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/manifests/install.pp
+++ b/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/manifests/install.pp
@@ -1,5 +1,5 @@
class kali_top10::install{
- package { ['kali-linux-top10']:
+ package { ['kali-linux-top10', 'nfs-common', 'ftp']:
ensure => 'installed',
}
}
diff --git a/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/secgen_metadata.xml b/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/secgen_metadata.xml
index bac3c97b4..f77e3af9f 100644
--- a/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/secgen_metadata.xml
+++ b/modules/utilities/unix/attack_tools/kali_metapackages/kali_top10/secgen_metadata.xml
@@ -7,7 +7,7 @@
Z. Cliffe SchreudersGPLv3Installs a collection of software onto Kali.
- kali-linux-top10
+ kali-linux-top10 (and some other common attack tools)
In Kali Linux, we have a sub-menu called “Top 10 Security Tools”. The kali-linux-top10 metapackage will install all of these tools for you in one fell swoop.
Installation Size: 3.5 GB
diff --git a/modules/utilities/unix/container/chroot_debootstrap/secgen_metadata.xml b/modules/utilities/unix/container/chroot_debootstrap/secgen_metadata.xml
index 81e7f290e..41021dd4c 100644
--- a/modules/utilities/unix/container/chroot_debootstrap/secgen_metadata.xml
+++ b/modules/utilities/unix/container/chroot_debootstrap/secgen_metadata.xml
@@ -14,9 +14,14 @@
chroot_dir
- /srv/chroot
+ /opt/chroot
+
+
+ .*Debian.*Wheezy.*
+
+
update
diff --git a/modules/utilities/unix/container/docker/secgen_metadata.xml b/modules/utilities/unix/container/docker/secgen_metadata.xml
index f262f84da..b2e44ed53 100644
--- a/modules/utilities/unix/container/docker/secgen_metadata.xml
+++ b/modules/utilities/unix/container/docker/secgen_metadata.xml
@@ -29,8 +29,13 @@
busybox
+
+
+ .*Debian.*Wheezy.*
+ update
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/README.md b/modules/utilities/unix/labtainers/files/Labtainers-master/README.md
new file mode 100644
index 000000000..8e3ad7c6b
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/README.md
@@ -0,0 +1,465 @@
+Labtainers: A Docker-based cyber lab framework
+==============================================
+
+Labtainers include more than 45 cyber lab exercises and tools to build your own. Import a single VM appliance or install on a Linux system and your students are done with provisioning and administrative setup, for these and future lab exercises.
+
+* Consistent lab execution environments and automated provisioning via Docker containers
+* Multi-component network topologies on a modestly performing laptop computer
+* Automated assessment of student lab activity and progress
+* Individualized lab exercises to discourage sharing solutions
+
+Labtainers provide controlled and consistent execution environments in which students perform labs entirely within the confines of their computer, regardless of the Linux distribution and packages installed on the student's computer. The only requirement is that the Linux system supports Docker. See the [Papers][Papers] for additional information about the framework.
+The Labtainers website, and downloads (including VM appliances with Labtainers pre-installed) are at .
+
+[Papers]: https://my.nps.edu/web/c3o/labtainers#papers
+
+Distribution created: mm/dd/yyyy
+Revision:
+
+## Content
+[Distribution and Use](#distribution-and-use)
+
+[Guide to directories](#guide-to-directories)
+
+[Support](#support)
+
+[Release notes](#release-notes)
+
+## Distribution and Use
+Labtainers was created by United States Government employees at
+The Center for Cybersecurity and Cyber Operations (C3O)
+at the Naval Postgraduate School NPS. Please note that within the
+United States, copyright protection is not available for any works
+created by United States Government employees, pursuant to Title 17
+United States Code Section 105. This software is in the public
+domain and is not subject to copyright.
+
+However, several of the labs are derived from SEED labs from
+Syracuse University, and include copyrighted and licensed elements
+as set forth in their respective Lab Manuals. These labs include:
+bufoverflow, capabilities, formatstring, local-dns, onewayhash,
+retlibc, setuid-env, sql-inject, tcpip, webtrack, xforge and xsite.
+
+## Guide to directories
+
+* scripts/labtainers-student -- the work directory for running and
+ testing student labs. You must be in that directory to run
+ student labs.
+
+* scripts/labtainers-instructor -- the work directory for
+ running and testing automated assessment and viewing student
+ results.
+
+* labs -- Files specific to each of the labs
+
+* setup_scripts -- scripts for installing Labtainers and Docker and updating Labtainers
+
+* docs -- latex source for the labdesigner.pdf, and other documentation.
+
+* config -- system-wide configuration settings (these are not the
+ lab-specific configuration settings.
+
+* distrib -- distribution support scripts, e.g., for publishing labs to the Docker hub.
+
+* testsets -- Test procedures and expected results. (Per-lab drivers for SimSec are not
+distributed).
+
+* pkg-mirrors -- utility scripts for internal NPS package mirroring to reduce external
+package pulling during tests and distribution.
+
+## Support
+Use the GitHub issue reports, or email me at mfthomps@nps.edu
+
+Also see
+
+
+## Release notes
+
+The standard Labtainers distribution does not include files required for development
+of new labs. For those, run ./update-designer.sh from the labtainer/trunk/setup\_scripts directory.
+
+The installation script and the update-designer.sh script set environment variables,
+so you may want to logout/login, or start a new bash shell before using Labtainers the
+first time.
+May 2, 2019
+- Acl lab fix to bobstuff.txt permissions. Use explicit chmod in fixlocal.sh
+- Revise student guide to clarify use of stop and -r option in body of the manual.
+March 9, 2019
+- The checkwork function was reusing containers, thereby preventing students from eliminating artifacts
+from previous lab work.
+- Add appendix to the symkey lab to describe the BMP image format.
+February 22
+- The http server failed to start in the vpn and vpn2 labs. Automated assessment removed from those labs until reworked.
+January 7, 2019
+- Fix gdblesson automated assessment to at least be operational.
+January 27, 2018
+- Fix lab manual for routing-basics2 and fix routing to enable external access to internal web server.
+
+December 29, 2018
+- Fix routing-basics2, same issues as routing-basics, plus an incorret ip address in the gateway resolv.conf
+
+December 5, 2018
+- Fix routing-basics lab, dns resolution at isp and gatway components was broken.
+
+November 14, 2018
+- Remove /run/nologin from archive machine in backups2 -- need general solution for this nologin issue
+
+November, 5, 2018
+- Change file-integrity lab default aid.conf to track metadata changes rather than file modification times
+
+October 22, 2018
+- macs-hash lab resolution verydodgy.com failed on lab restart
+- Notify function failed if notify_cb.sh is missing
+
+October 12, 2018
+- Set ulimit on file size, limit to 1G
+
+October 10, 2018
+- Force collection of parameterized files
+- Explicitly include leafpad and ghex in centos-xtra baseline and rebuild dependent images.
+
+September 28, 2018
+- Fix access modes of shared file in ACL lab
+- Clarify question in pass-crack
+- Modify artifact collection to ignore files older than start of lab.
+- Add quantum computing algorithms lab
+
+September 12, 2018
+- Fix setuid-env grading syntax errors
+- Fix syntax error in iptables2 example firewall rules
+- Rebuild centos labs, move lamp derivatives to use lamp.xtr for waitparam and force
+httpd to wait for that to finish.
+
+September 7, 2018
+- Add CyberCIEGE as a lab
+- read\_pre.txt information display prior to pull of images, and chance to bail.
+
+September 5, 2018
+- Restore sakai bulk download processing to gradelab function.
+- Remove unused instructor scripts.
+
+September 4, 2018
+- Allow multiple IP addresses per network interface
+- Add base image for Wine
+- Add GRFICS virtual ICS simulation
+
+August 23, 2018
+- Add GrassMarlin lab (ICS network discovery)
+
+August 23, 2018
+- Add GrassMarlin lab (ICS network discovery)
+
+August 21, 2018
+- Another fix around AWS authentication issues (DockerHub uses AWS).
+- Fix new\_lab\_setup.py to use git instead of svn.
+- Split plc-forensics lab into a basic lab and and advanced lab (plc-forensics-adv)
+
+August 17, 2018
+- Transition to git & GitHub as authoritative repo.
+
+August 15, 2018
+- Modify plc-forensics lab assessment to be more general; revise lab manual to reflect wireshark on the Labtainer.
+
+August 15, 2018
+- Add "checkwork" command allowing students to view automated assessment results for their lab work.
+- Include logging of iptables packet drops in the iptables2 and the iptables-ics lab.
+- Remove obsolete instances of is\_true and is\_false from goal.config
+- Fix boolean evaluation to handle "NOT foo", it had expected more operands.
+
+August 9, 2018
+- Support parameter replacement in results.config files
+- Add TIME\_DELIM result type for results.config
+- Rework the iptables lab, remove hidden nmap commands, introduce custom service
+
+August 7, 2018
+- Add link to student guide in labtainer-student directory
+- Add link to student guide on VM desktops
+- Fixes to iptables-ics to avoid long delay on shutdown; and fixes to regression tests
+- Add note to guides suggesting student use of VM browser to transfer artifact zip file to instructor.
+
+August 1, 2018
+- Use a generic Docker image for automated assessment; stop creating "instructor" images per lab.
+
+July 30, 2018
+- Document need to unblock the waitparam.service (by creating flag directory)
+if a fixlocal.sh script is to start a service for which waitparam is a
+prerequisite.
+- Add plc-app lab for PLC application firewall and whitelisting exercise.
+
+July 25, 2018
+- Add string\_contains operator to goals processing
+- Modify assessment of formatstring lab to account for leaked secret not always being
+at the end of the displayed string.
+
+July 24, 2018
+- Add SSH Agent lab (ssh-agent)
+
+July 20, 2018
+- Support offline building, optionally skip all image pulling
+- Restore apt/yum repo restoration to Dockerfile templates.
+- Handle redirect URL's from Docker registry blob retrieval to avoid
+authentication errors (Do not rely on curl --location).
+
+July 12, 2018
+- Add prestop feature to allow execution of designer-specified scripts on
+selected components prior to lab shutdown.
+- Correct host naming in the ssl lab, it was breaking automated assessment.
+- Fix dmz-lab initial state to permit DNS resolutions from inner network.
+- FILE\REGEX processing was not properly handling multiline searches.
+- Framework version derived from newly rebuilt images had incorrect default value.
+
+July 10, 2018
+- Add an LDAP lab
+- Complete transition to systemd based Ubuntu images, remove unused files
+- Move lab\_sys tar file to per-container tmp directory for concurrency.
+
+July 6, 2018
+- All Ubuntu base images replaced with versions based on systemd
+- Labtainer container images in registry now tagged with base image ID & have labels reflecting
+the base image.
+- A given installation will pull and use images that are consistent with the base images it possesses.
+- If you are using a VM image, you may want to replace that with a newer VM image from our website.
+- New labs will not run without downloading newer base images; which can lead to your VM storing multiple
+versions of large base images (> 500 MB each).
+- Was losing artifacts from processes that were running when lab was stopped -- was not properly killing capinout
+processes.
+
+June 27, 2018
+- Add support for Ubuntu systemd images
+- Remove old copy of SimLab.py from labtainer-student/bin
+- Move apt and yum sources to /var/tmp
+- Clarify differences between use of "boolean" and "count\_greater" in assessments
+- Extend Add-HOST in start.config to include all components on a network.
+- Add option to new\_lab\_setup.py to add a container based on a copy of an existing container.
+
+June 21, 2018
+- Set DISPLAY env for root
+- Fix to build dependency handling of svn status output
+- Add radius lab
+- Bug in SimLab append corrected
+- Use svn, where appropriate, to change file names with new\_lab\_setup.py
+
+June 19, 2018
+- Retain order of containers defined in start.conf when creating terminal with multiple tabs
+- Clarify designer manual to identify path to assessment configuration files.
+- Remove prompt for instructor to provide email
+- Botched error checking when testing for version number
+- Include timestamps of lab starts and redos in the assessment json
+- Add an SSL lab that includes bi-directional authentication and creation of certificates.
+
+June 14, 2018
+- Add diagnostics to parameterizing, track down why some install seem to fail on that.
+- If a container is already created, make sure it is parameterized, otherwise bail to avoid corrupt or half-baked containers.
+- Fix program version number to use svn HEAD
+
+June 15, 2018
+- Convert plain text instructions that appeared in xterms into pdf file.
+- Fix bug in version handling of images that have not yet been pulled.
+- Detect occurance of a container that was created, but not parameterized,
+and prompt the user to restart the lab with the "-r" option.
+- Add designer utility: rm\_svn.py so that removed files trigger an image rebuild.
+
+June 13, 2018
+- Install xterm on Ubuntu 18 systems
+- Work around breakage in new versions of gnome-terminal tab handling
+
+June 11, 2018
+- Add version checking to compare images to the framework.
+- Clarify various lab manuals
+
+June 2, 2018
+- When installing on Ubuntu 18, use docker.io instead of docker-ce
+- The capinout caused a crash when a "sudo su" monitored command is followed by
+a non-elevated user command.
+- Move routing and resolv.conf settings into /etc/rc.local instead of fixlocal.sh
+so they persist across start/stop of the containers.
+
+May 31, 2018
+- Work around Docker bug that caused text to wrap in a terminal without a line feed.
+- Extend COMMAND\_COUNT to account for pipes
+- Create new version of backups lab that includes backups to a remote server and
+backs up an entire partition.
+- Alter sshlab instructions to use ssh-copy-id utility
+- Delte /run/nologin file from parameterize.sh to permit ssh login on CentOS
+
+May 30, 2018
+- Extended new\_lab\_setup.py to permit identification of the base image to use
+- Create new version of centos-log that includes centralized logging.
+- Assessment validation was not accepting "time\_not\_during" option.
+- Begin to integrate Labtainer Master for managing Labtainers from a Docker container.
+
+May 25, 2018
+- Remove 10 second sleeps from various services. Was delaying xinetd responses, breaking
+automated tests.
+- Fix snort lab grading to only require "CONFIDENTIAL" in the alarm. Remove unused
+files from lab.
+- Program finish times were not recorded if the program was running when the lab
+was stopped.
+
+May 21, 2018
+- Fix retlibc grading to remove duplicate goal, was failing automated assessment
+- Remove copies of mynotify.py from individual labs and lab template, it is
+has been part of lab\_sys/sbin, but had not been updated to reflect fixes made
+for acl lab.
+
+May 18, 2018
+- Mask signal message from exec\_wrap so that segv error message looks right.
+- The capinout was sometimes losing stdout, check command stdout on death of cmd.
+- Fix grading of formatstring to catch segmentation fault message.
+- Add type\_function feature to SimLab to type stdout of a script (see formatstring simlab).
+- Remove SimLab limitation on combining single/double quotes.
+- Add window\_wait directive to SimLab to pause until window with given title
+can be found.
+- Modify plc lab to alter titles on physical world terminal to reflect status,
+this also makes testing easier.
+- Fix bufoverflow lab manual link.
+
+May 15, 2018
+- Add appendix on use of the SimLab tool to simulate user performance of labs for
+regression testing and lab development.
+- Add wait\_net function to SimLab to pause until selected network connections terminate.
+- Change acl automated assessment to use FILE\_REGEX for multiline matching.
+- SimLab test for xsite lab.
+
+May 11, 2018
+- Add "noskip" file to force collection of files otherwise found in home.tar, needed
+for retrieving Firefox places.sqlite.
+- Merge sqlite database with write ahead buffer before extracting.
+- Corrections to lab manual for the symkeylab
+- Grading additions for symkeylab and pubkey
+- Improvements to simlab tool: support include, fix window naming.
+
+May 9, 2018
+- Fix parameterization of the file-deletion lab. Correct error its lab manual.
+- Replace use of shell=True in python scripts to reduce processes and allow tracking PIDs
+- Clean up manuals for backups, pass-crack and macs-hash.
+
+May 8, 2018
+- Handle race condition to prevent gnome-terminal from executing its docker command
+before an xterm instruction terminal runs its command.
+- Don't display errors when instuctor stops a lab started with "-d".
+- Change grading of nmap-ssh to better reflect intent of the lab.
+- Several document and script fixes suggested by olberger on github.
+
+May 7, 2018
+- Use C-based capinout program instead of the old capinout.sh to capture stdin and
+stdout. See trunk/src-tool/capinout. Removes limitations associated with use ctrl-C
+to break monitored programs and the display of passwords in telnet and ssh.
+- Include support for saki bulk\_download zip processing to extract seperatly submitted
+reports, and summarizes missing submits.
+- Add checks to user-provided email to ensure they are printable characters.
+- While grading, if user-supplied email does not match zip file name, proceed to grade
+the results, but include note in the table reflecting *cheating*. Require to recover from
+cases where student enters garbage for an email address.
+- Change telnetlab grading to not look at tcpdump output for passwords -- capinout fix
+leads to correct character-at-a-time transmission to server.
+- Fix typo in install-docker.sh and use sudo to alter docker dns setting in that script.
+
+April 26, 2018
+- Transition to use of "labtainer" to start lab, and "stoplab" to stop it.
+- Add --version option to labtainer command.
+- Add log\_ts and log\_range result types, and time\_not\_during goal operators.
+Revamp the centos-log and sys-log grading to use these features.
+- Put labsys.tar into /var/tmp instead of /tmp, sometimes would get deleted before expanded
+- Running X applications as root fails after reboot of VM.
+- Add "User Command" man pages to CentOS based labs
+- Fix recent bug that prevented collection of docs files from students
+- Modify smoke-tests to only compare student-specific result line, void of whitespace
+
+April 20, 2018
+- The denyhosts service fails to start the first time, moved start to student\_startup.sh.
+- Move all faux\_init services until after parameterization -- rsyslog was failing to start
+on second boot of container.
+April 19, 2018
+- The acl lab failed to properly assess performance of the trojan horse step.
+- Collect student documents by default.
+- The denyhost lab changed to reflect that denyhosts (or tcp wrappers?) now
+modifies iptables. Also, the denyhosts service was failing to start on some occasions.
+- When updating Labtainers, do not overwrite files that are newer than those
+ in the archive -- preserve student lab reports.
+
+April 12, 2018
+
+- Add documentation for the purpose of lab goals, and display this for the instructor
+ when the instructor starts a lab.
+- Correct use of the precheck function when the program is in treataslocal, pass capintout.sh
+ the full program path.
+- Copy instr_config files at run time rather than during image build.
+- Add Designer Guide section on debugging automated assessment.
+- Incorrect case in lab report file names.
+- Unncessary chown function caused instructor.py to sometimes crash.
+- Support for automated testing of labs (see SimLab and smoketest).
+- Move testsets and distrib under trunk
+
+April 5, 2018
+
+- Revise Firefox profile to remove "you've not use firefox in a while..." message.
+- Remove unnessary pulls from registry -- get image dates via docker hub API instead.
+
+March 28, 2018
+
+- Use explicit tar instead of "docker cp" for system files (Docker does
+ not follow links.)
+- Fix backups lab use separate file system and update the manual.
+
+March 26, 2018
+
+- Support for multi-user modes (see Lab Designer User Guide).
+- Removed build dependency on the lab_bin and lab_sys files. Those are now copied
+ during parameterization of the lab.
+- Move capinout.sh to /sbin so it can be found when running as root.
+
+March 21, 2018
+
+- Add CLONE to permit multiple instances of the same container, e.g., for
+ labs shared by multiple concurrent students.
+- Adapt kali-test lab to provide example of macvlan and CLONE
+- Copy the capinout.sh script to /sbin so root can find it after a sudo su.
+
+March 15, 2018
+
+- Support macvlan networks for communications with external hosts
+- Add a Kali linux base, and a Metasploitable 2 image (see kali-test)
+
+March 8, 2018
+
+- Do not require labname when using stop.py
+- Catch errors caused by stray networks and advise user on a fix
+- Add support for use of local apt & yum repos at NPS
+
+February 21, 2018
+
+- Add dmz-lab
+- Change "checklocal" to "precheck", reflecting it runs prior to the command.
+- Decouple inotify event reporting from use of precheck.sh, allow inotify
+ event lists to include optional outputfile name.
+- Extend bash hook to root operations, flush that bash_history.
+- Allow parameterization of start.config fields, e.g., for random IP addresses
+- Support monitoring of services started via systemctl or /etc/init.d
+- Introduce time delimeter qualifiers to organize a timestamped log file into
+ ranges delimited by some configuration change of interest (see dmz-lab)
+
+February 5, 2018
+
+- Boolean values from results.config files are now treated as goal values
+- Add regular expression support for identifying artifact results.
+- Support for alternate Docker registries, including a local test registry for testing
+- Msc fixes to labs and lab manuals
+- The capinout monitoring hook was not killing child processes on exit.
+- Kill monitored processes before collecting artifacts
+- Add labtainer.wireshark as a baseline container, clean up dockerfiles
+
+January 30, 2018
+
+- Add snort lab
+- Integrate log file timestamps, e.g., from syslogs, into timestamped results.
+- Remove undefined result values from intermediate timestamped json result files.
+- Alter the time_during goal assessment operation to associate timestamps with
+ the resulting goal value.
+
+January 24, 2018
+
+- Use of tabbed windows caused instructor side to fail, use of double quotes.
+- Ignore files in \_tar directories (other than .tar) when determining build
+ dependencies.
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/build.xml b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/build.xml
new file mode 100644
index 000000000..91517e999
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/build.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+ Builds, tests, and runs the project GoalsUI_Sep13.
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/manifest.mf b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/manifest.mf
new file mode 100644
index 000000000..1574df4a2
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/build-impl.xml b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/build-impl.xml
new file mode 100644
index 000000000..5497c9c60
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/build-impl.xml
@@ -0,0 +1,1420 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set test.src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No tests executed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set JVM to use for profiling in profiler.info.jvm
+ Must set profiler agent JVM arguments in profiler.info.jvmargs.agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set profile.class
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+
+
+
+
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+ Must select some files in the IDE or set test.class
+ Must select some method in the IDE or set test.method
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+ Must select one file in the IDE or set test.class
+ Must select some method in the IDE or set test.method
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/genfiles.properties b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/genfiles.properties
new file mode 100644
index 000000000..bee36be94
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=eec53d04
+build.xml.script.CRC32=e676bb1d
+build.xml.stylesheet.CRC32=8064a381@1.80.1.48
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=eec53d04
+nbproject/build-impl.xml.script.CRC32=4d702800
+nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/private/private.properties b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/private/private.properties
new file mode 100644
index 000000000..9436b19f6
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/private/private.properties
@@ -0,0 +1,2 @@
+compile.on.save=true
+user.properties.file=C:\\Users\\Dan\\AppData\\Roaming\\NetBeans\\8.2\\build.properties
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/project.properties b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/project.properties
new file mode 100644
index 000000000..73526481e
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/project.properties
@@ -0,0 +1,75 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processor.options=
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# Files in build.classes.dir which should be excluded from distribution jar
+dist.archive.excludes=
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/GoalsUI_Sep13.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=\
+ ${libs.absolutelayout.classpath}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.external.vm=true
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.8
+javac.target=1.8
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=GoalsUI.GoalsUI
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/project.xml b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/project.xml
new file mode 100644
index 000000000..a1ebdf5c8
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/nbproject/project.xml
@@ -0,0 +1,15 @@
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+ GoalsUI_Sep13
+
+
+
+
+
+
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalPanels.form b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalPanels.form
new file mode 100644
index 000000000..f3f16c0b9
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalPanels.form
@@ -0,0 +1,422 @@
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalPanels.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalPanels.java
new file mode 100644
index 000000000..43a39f334
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalPanels.java
@@ -0,0 +1,713 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package GoalsUI;
+
+import static GoalsUI.ParamReferenceStorage.GoalType_ITEMS;
+import static GoalsUI.ParamReferenceStorage.Operator_ITEMS;
+import static GoalsUI.ParamReferenceStorage.answerTypes;
+import static GoalsUI.ParamReferenceStorage.goalInput;
+import static GoalsUI.ParamReferenceStorage.opInput;
+import static GoalsUI.ParamReferenceStorage.resultTagInput;
+import GoalsUI.ToolTipHandlers.ToolTipWrapper;
+import static GoalsUI.ToolTipHandlers.setComboItems;
+import java.awt.Dimension;
+import java.util.List;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+/**
+ *
+ * @author Dan
+ */
+
+//NOTE: Previous Matchany ComboBox has not been implemented at all- 9/13/17
+
+
+
+public class GoalPanels extends javax.swing.JPanel {
+ static Dimension dim = new Dimension(975, 100);
+ private GoalsUI goalsUI;
+ private int rowNum;
+
+ private List resultTags;
+ private List parameterIDs;
+ private List booleanResultTags;
+
+ //Creating fresh goal line
+ public GoalPanels(GoalsUI ui, GoalsData dataUI) {
+ initiateGoalPanel(ui, dataUI, dataUI.getRowCount());
+ this.revalidate();
+ this.repaint();
+ }
+
+ //Loading goal line
+ public GoalPanels(GoalsUI ui, GoalsData dataUI, GoalValues goalVal, int rowNum) {
+ initiateGoalPanel(ui, dataUI, rowNum);
+
+ //Set Values
+ setGoalIDTextField(goalVal.goalID);
+
+ setGoalTypeComboBox(goalVal.goalType);
+
+ setOperatorComboBox(goalVal.operator);
+
+ setExecutableFileTextField(goalVal.executableFile);
+
+ setResultTagComboBox(goalVal.resultTag);
+
+ setArithmeticResultTagTextField(goalVal.resultTag);
+
+ setAnswerTypeComboBox(goalVal.answerType);
+
+ if(goalVal.answerType.equals(answerTypes[0])) //Literal
+ setAnswerTagTextField(goalVal.answerTag);
+ else if(goalVal.answerType.equals(answerTypes[1])) //Result Tag
+ setResultTag2ComboBox(goalVal.answerTag);
+ else //Parameter & Parameter_ASCII
+ setParameterComboBox(goalVal.answerTag);
+
+ setBooleanTextField(goalVal.booleanExp);
+
+ setGoal1TextField(goalVal.goal1);
+
+ setGoal2TextField(goalVal.goal2);
+
+ setValueTextField(goalVal.value);
+
+ setSubgoalTextField(goalVal.subgoalList);
+
+ this.revalidate();
+ this.repaint();
+
+ }
+
+ //Use for loading a line
+ private void initiateGoalPanel(GoalsUI ui, GoalsData dataUI, int rowNum){
+ initComponents();
+ this.goalsUI = ui;
+ this.rowNum = rowNum;
+
+ resultTags = dataUI.getResultTagList();
+ parameterIDs = dataUI.getParameters();
+ booleanResultTags = dataUI.getBooleanResults();
+
+ rowLabel.setText(Integer.toString(rowNum));
+
+ //Set initial field visibility. Defaults to [operator : resultTag : answerTag]
+ AnswerTagTextField.setVisible(true);
+ ResultTag2ComboBox.setVisible(false);
+ ParameterComboBox.setVisible(false);
+ ArithmeticResultTagTextField.setVisible(false);
+ BooleanTextField.setVisible(false);
+ ExecutableFileTextField.setVisible(false);
+ Goal1TextField.setVisible(false);
+ Goal2TextField.setVisible(false);
+ ResultTagComboBox.setVisible(false);
+ SubgoalTextField.setVisible(false);
+ ValueTextField.setVisible(false);
+ BooleanResultTagsComboBox.setVisible(false);
+ PreviousMatchanyComboBox.setVisible(false);
+
+
+ //Load ComboBox Items
+ setComboItems(GoalTypeComboBox, GoalType_ITEMS);
+ setComboItems(OperatorComboBox, Operator_ITEMS);
+
+
+
+ ResultTagComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(resultTags.toArray(new String[resultTags.size()])));
+ AnswerTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(answerTypes));
+ if(parameterIDs.isEmpty()){
+ AnswerTypeComboBox.removeItem(answerTypes[2]);
+ AnswerTypeComboBox.removeItem(answerTypes[3]);
+ }
+ else
+ ParameterComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(parameterIDs.toArray(new String[parameterIDs.size()])));
+
+ ResultTag2ComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(resultTags.toArray(new String[resultTags.size()])));
+ BooleanResultTagsComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(booleanResultTags.toArray(new String[booleanResultTags.size()])));
+ }
+
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ ArtifactPanel = new javax.swing.JPanel();
+ GoalIDTextField = new javax.swing.JTextField();
+ GoalTypeComboBox = new javax.swing.JComboBox<>();
+ OperatorComboBox = new javax.swing.JComboBox<>();
+ AnswerTagTextField = new javax.swing.JTextField();
+ BooleanTextField = new javax.swing.JTextField();
+ Goal1TextField = new javax.swing.JTextField();
+ Goal2TextField = new javax.swing.JTextField();
+ ValueTextField = new javax.swing.JTextField();
+ SubgoalTextField = new javax.swing.JTextField();
+ ResultTagComboBox = new javax.swing.JComboBox<>();
+ ExecutableFileTextField = new javax.swing.JTextField();
+ ArithmeticResultTagTextField = new javax.swing.JTextField();
+ AnswerTypeComboBox = new javax.swing.JComboBox<>();
+ ResultTag2ComboBox = new javax.swing.JComboBox<>();
+ ParameterComboBox = new javax.swing.JComboBox<>();
+ BooleanResultTagsComboBox = new javax.swing.JComboBox<>();
+ PreviousMatchanyComboBox = new javax.swing.JComboBox<>();
+ DeleteButton = new javax.swing.JButton();
+ rowLabel = new javax.swing.JLabel();
+ UpButton = new javax.swing.JButton();
+ DownButton = new javax.swing.JButton();
+
+ setPreferredSize(new java.awt.Dimension(1110, 69));
+
+ ArtifactPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
+ ArtifactPanel.setMinimumSize(new java.awt.Dimension(1400, 0));
+ ArtifactPanel.setPreferredSize(new java.awt.Dimension(1300, 34));
+
+ GoalTypeComboBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ goalTypeItemChanged(evt);
+ }
+ });
+
+ OperatorComboBox.setToolTipText("Identifies how the line is to be identified");
+ OperatorComboBox.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Operator"));
+
+ AnswerTagTextField.setToolTipText("Parameter based on Line Type");
+ AnswerTagTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "AnswerTag"));
+
+ BooleanTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Boolean"));
+
+ Goal1TextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Goal 1"));
+
+ Goal2TextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Goal 2"));
+
+ ValueTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Value"));
+
+ SubgoalTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Subgoal List"));
+
+ ResultTagComboBox.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Result Tag"));
+
+ ExecutableFileTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Executable File"));
+
+ ArithmeticResultTagTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Arithmetic Result Tag"));
+
+ AnswerTypeComboBox.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Answer Type"));
+ AnswerTypeComboBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ AnswerTypeComboBoxItemStateChanged(evt);
+ }
+ });
+
+ BooleanResultTagsComboBox.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Boolean Result Tags"));
+
+ javax.swing.GroupLayout ArtifactPanelLayout = new javax.swing.GroupLayout(ArtifactPanel);
+ ArtifactPanel.setLayout(ArtifactPanelLayout);
+ ArtifactPanelLayout.setHorizontalGroup(
+ ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(ArtifactPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(GoalIDTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(GoalTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(OperatorComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 139, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ExecutableFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ResultTagComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(2, 2, 2)
+ .addComponent(ArithmeticResultTagTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(AnswerTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(AnswerTagTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ResultTag2ComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ParameterComboBox, 0, 150, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(BooleanTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 404, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ValueTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(SubgoalTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 643, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(Goal1TextField, javax.swing.GroupLayout.PREFERRED_SIZE, 185, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(Goal2TextField, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(BooleanResultTagsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(PreviousMatchanyComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ ArtifactPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {Goal1TextField, Goal2TextField});
+
+ ArtifactPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {ParameterComboBox, ResultTag2ComboBox});
+
+ ArtifactPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {BooleanResultTagsComboBox, PreviousMatchanyComboBox});
+
+ ArtifactPanelLayout.setVerticalGroup(
+ ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, ArtifactPanelLayout.createSequentialGroup()
+ .addGap(14, 14, 14)
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(ValueTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(SubgoalTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(Goal2TextField, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(GoalIDTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(GoalTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(BooleanTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(Goal1TextField, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(OperatorComboBox)
+ .addComponent(ExecutableFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(ResultTagComboBox)
+ .addComponent(ArithmeticResultTagTextField)
+ .addComponent(AnswerTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(AnswerTagTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(ResultTag2ComboBox, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(ParameterComboBox, javax.swing.GroupLayout.Alignment.TRAILING))
+ .addComponent(BooleanResultTagsComboBox)
+ .addComponent(PreviousMatchanyComboBox))
+ .addGap(83, 83, 83))
+ );
+
+ ArtifactPanelLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {Goal1TextField, Goal2TextField, SubgoalTextField, ValueTextField});
+
+ ArtifactPanelLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {AnswerTagTextField, AnswerTypeComboBox, ArithmeticResultTagTextField, BooleanTextField, ExecutableFileTextField, OperatorComboBox, ParameterComboBox, ResultTag2ComboBox, ResultTagComboBox});
+
+ DeleteButton.setText("Delete");
+ DeleteButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ DeleteButtonActionPerformed(evt);
+ }
+ });
+
+ rowLabel.setFont(new java.awt.Font("Arial", 1, 24)); // NOI18N
+ rowLabel.setText("10");
+
+ UpButton.setText("^");
+ UpButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ UpButtonActionPerformed(evt);
+ }
+ });
+
+ DownButton.setText("v");
+ DownButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ DownButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(rowLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(ArtifactPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 1390, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(UpButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(DownButton, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(DeleteButton)
+ .addGap(73, 73, 73))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(ArtifactPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(UpButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(DownButton))
+ .addComponent(DeleteButton, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(rowLabel)))
+ );
+ }// //GEN-END:initComponents
+
+ private void DeleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DeleteButtonActionPerformed
+ deleteButton();
+ }//GEN-LAST:event_DeleteButtonActionPerformed
+
+ private void deleteButton(){
+ JPanel container = (JPanel)this.getParent();
+ container.remove(this);
+ goalsUI.dataUI.decreaseRowCount();
+ goalsUI.refresh();
+ }
+
+ private void UpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_UpButtonActionPerformed
+ swapUpdate("UP", rowNum-1); //Subtract rowNum by one to get the proper index number
+ }//GEN-LAST:event_UpButtonActionPerformed
+
+ private void DownButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DownButtonActionPerformed
+ swapUpdate("DOWN", rowNum-1); //Subtract rowNum by one to get the proper index number
+ }//GEN-LAST:event_DownButtonActionPerformed
+
+ private void goalTypeItemChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_goalTypeItemChanged
+ goalTypeListener();
+ }//GEN-LAST:event_goalTypeItemChanged
+
+ private void AnswerTypeComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_AnswerTypeComboBoxItemStateChanged
+ answerTypeListener();
+ }//GEN-LAST:event_AnswerTypeComboBoxItemStateChanged
+
+ private void goalTypeListener(){
+ String goalType = ((ToolTipWrapper)GoalTypeComboBox.getSelectedItem()).getItem();
+
+ if(opInput.contains(goalType))
+ visibilityHandler("op");
+ else if(goalInput.contains(goalType))
+ visibilityHandler("goal");
+ else if(resultTagInput.contains(goalType))
+ visibilityHandler("rT");
+ else if("boolean".equals(goalType))
+ visibilityHandler("boolean");
+ else if("count_greater".equals(goalType))
+ visibilityHandler("countg");
+ else if("execute".equals(goalType))
+ visibilityHandler("exe");
+ else if("matchExpression".equals(goalType))
+ visibilityHandler("matche");
+ else
+ System.out.println("Goal Type Listener could not find this type: " + goalType);
+ }
+
+ private void visibilityHandler(String type){
+ OperatorComboBox.setVisible(false);
+ if(((DefaultComboBoxModel)OperatorComboBox.getModel()).getIndexOf(Operator_ITEMS[4]) == -1)
+ OperatorComboBox.insertItemAt(Operator_ITEMS[4], 0);
+ if(((DefaultComboBoxModel)OperatorComboBox.getModel()).getIndexOf(Operator_ITEMS[2]) == -1)
+ OperatorComboBox.insertItemAt(Operator_ITEMS[3], 0);
+ if(((DefaultComboBoxModel)OperatorComboBox.getModel()).getIndexOf(Operator_ITEMS[2]) == -1)
+ OperatorComboBox.insertItemAt(Operator_ITEMS[2], 0);
+ if(((DefaultComboBoxModel)OperatorComboBox.getModel()).getIndexOf(Operator_ITEMS[1]) == -1)
+ OperatorComboBox.insertItemAt(Operator_ITEMS[1], 0);
+ if(((DefaultComboBoxModel)OperatorComboBox.getModel()).getIndexOf(Operator_ITEMS[0]) == -1)
+ OperatorComboBox.insertItemAt(Operator_ITEMS[0], 0);
+
+ OperatorComboBox.setSelectedItem(Operator_ITEMS[0]);
+
+
+
+ ExecutableFileTextField.setVisible(false);
+ ExecutableFileTextField.setText("");
+
+ ResultTagComboBox.setVisible(false);
+ if(resultTags != null && !resultTags.isEmpty())
+ ResultTagComboBox.setSelectedItem(resultTags.get(0));
+
+ ArithmeticResultTagTextField.setVisible(false);
+ ArithmeticResultTagTextField.setText("");
+
+ AnswerTypeComboBox.setVisible(false);
+ AnswerTypeComboBox.setSelectedItem(answerTypes[0]);
+ //"Result Tag" may have been removed by the execute goaltype so readd it to the combo box to reset it back to default
+ if(((DefaultComboBoxModel)AnswerTypeComboBox.getModel()).getIndexOf("Result Tag") == -1)
+ AnswerTypeComboBox.addItem("Result Tag");
+ AnswerTagTextField.setVisible(false);
+ AnswerTagTextField.setText("");
+
+ ResultTag2ComboBox.setVisible(false);
+ if(resultTags != null && !resultTags.isEmpty())
+ ResultTag2ComboBox.setSelectedItem(resultTags.get(0));
+
+ ParameterComboBox.setVisible(false);
+ if(parameterIDs != null && !parameterIDs.isEmpty())
+ ParameterComboBox.setSelectedItem(parameterIDs.get(0));
+
+ BooleanTextField.setVisible(false);
+ BooleanTextField.setText("");
+
+ Goal1TextField.setVisible(false);
+ Goal1TextField.setText("");
+
+ Goal2TextField.setVisible(false);
+ Goal2TextField.setText("");
+
+ SubgoalTextField.setVisible(false);
+ SubgoalTextField.setText("");
+
+ ValueTextField.setVisible(false);
+ ValueTextField.setText("");
+
+ BooleanResultTagsComboBox.setVisible(false);
+ if(booleanResultTags != null && !booleanResultTags.isEmpty())
+ BooleanResultTagsComboBox.setSelectedItem(booleanResultTags.get(0));
+
+ PreviousMatchanyComboBox.setVisible(false);
+ //if(prevMatchany != null && !prevMatchany.isEmpty())
+ // PreviousMatchanyComboBox.setSelectedItem(prevMatchany.get(0));
+
+ switch(type){
+ case "op":
+ OperatorComboBox.setVisible(true);
+ ResultTagComboBox.setVisible(true);
+ AnswerTypeComboBox.setVisible(true);
+ AnswerTagTextField.setVisible(true);
+ break;
+ case "goal":
+ Goal1TextField.setVisible(true);
+ Goal2TextField.setVisible(true);
+ BooleanResultTagsComboBox.setVisible(true);
+ //PreviousMatchanyComboBox.setVisible(true);
+ break;
+ case "rT":
+ ResultTagComboBox.setVisible(true);
+ break;
+ case "boolean":
+ BooleanTextField.setVisible(true);
+ BooleanResultTagsComboBox.setVisible(true);
+ break;
+ case "countg":
+ SubgoalTextField.setVisible(true);
+ ValueTextField.setVisible(true);
+ BooleanResultTagsComboBox.setVisible(true);
+ break;
+ case "exe":
+ ExecutableFileTextField.setVisible(true);
+ ResultTagComboBox.setVisible(true);
+ AnswerTypeComboBox.setVisible(true);
+ //Answertag is expected to be a literal value or a symbolic name from parameters.config (pg. 26 in labtainers manual)
+ AnswerTypeComboBox.removeItem("Result Tag");
+ AnswerTagTextField.setVisible(true);
+ break;
+ case "matche":
+ OperatorComboBox.setVisible(true);
+ OperatorComboBox.removeItem(Operator_ITEMS[0]);
+ OperatorComboBox.removeItem(Operator_ITEMS[1]);
+ OperatorComboBox.removeItem(Operator_ITEMS[2]);
+ OperatorComboBox.removeItem(Operator_ITEMS[3]);
+ OperatorComboBox.removeItem(Operator_ITEMS[4]);
+ ArithmeticResultTagTextField.setVisible(true);
+ AnswerTypeComboBox.setVisible(true);
+ AnswerTagTextField.setVisible(true);
+ break;
+ default:
+ System.out.println("No type match");
+ }
+
+ this.revalidate();
+ this.repaint();
+ }
+
+ private void answerTypeListener(){
+ String answerType = (String)(AnswerTypeComboBox.getSelectedItem());
+
+ if(answerType.equals(answerTypes[0])){ //Literal
+ AnswerTagTextField.setVisible(true);
+
+ ResultTag2ComboBox.setVisible(false);
+ if(resultTags != null && !resultTags.isEmpty())
+ ResultTag2ComboBox.setSelectedItem(resultTags.get(0));
+
+ ParameterComboBox.setVisible(false);
+ if(parameterIDs != null && !parameterIDs.isEmpty())
+ ParameterComboBox.setSelectedItem(parameterIDs.get(0));
+ }
+ else if(answerType.equals(answerTypes[1])){ //Result Tag
+ AnswerTagTextField.setVisible(false);
+ AnswerTagTextField.setText("");
+
+ ResultTag2ComboBox.setVisible(true);
+
+ ParameterComboBox.setVisible(false);
+ if(parameterIDs != null && !parameterIDs.isEmpty())
+ ParameterComboBox.setSelectedItem(parameterIDs.get(0));
+ }
+ else if(answerType.equals(answerTypes[2]) || answerType.equals(answerTypes[3])){
+ AnswerTagTextField.setVisible(false);
+ AnswerTagTextField.setText("");
+
+ ResultTag2ComboBox.setVisible(false);
+ if(resultTags != null && !resultTags.isEmpty())
+ ResultTag2ComboBox.setSelectedItem(resultTags.get(0));
+
+ ParameterComboBox.setVisible(true);
+ }
+
+ this.revalidate();
+ this.repaint();
+ }
+
+ //Swaps goal order in the list of goals and then redraws them
+ protected void swapUpdate(String type, int rowIndex){
+ goalsUI.dataUI.updateListofGoals(goalsUI.getPanelofGoals());
+ goalsUI.dataUI.swapGoals(type, rowIndex);
+ goalsUI.goalsPanelRedraw();
+ }
+
+
+ //Field Getters
+ public JTextField getGoalIDTextField(){
+ return GoalIDTextField;
+ }
+
+ public JComboBox getGoalTypeComboBox(){
+ return GoalTypeComboBox;
+ }
+
+ public JComboBox getOperatorComboBox(){
+ return OperatorComboBox;
+ }
+
+ public JTextField getExecutableFileTextField(){
+ return ExecutableFileTextField;
+ }
+
+ public JComboBox getResultTagComboBox(){
+ return ResultTagComboBox;
+ }
+
+ public JTextField getArithmeticResultTagTextField(){
+ return ArithmeticResultTagTextField;
+ }
+
+ public JComboBox getAnswerTypeComboBox(){
+ return AnswerTypeComboBox;
+ }
+
+ public JTextField getAnswerTagTextField(){
+ return AnswerTagTextField;
+ }
+
+ public JComboBox getResultTag2ComboBox(){
+ return ResultTag2ComboBox;
+ }
+
+ public JComboBox getParameterComboBox(){
+ return ParameterComboBox;
+ }
+
+ public JTextField getBooleanTextField(){
+ return BooleanTextField;
+ }
+
+ public JTextField getGoal1TextField(){
+ return Goal1TextField;
+ }
+
+ public JTextField getGoal2TextField(){
+ return Goal2TextField;
+ }
+
+ public JTextField getValueTextField(){
+ return ValueTextField;
+ }
+
+ public JTextField getSubgoalTextField(){
+ return SubgoalTextField;
+ }
+
+
+
+ //Field SETTERS
+ private void setGoalIDTextField(String v){
+ GoalIDTextField.setText(v);
+ }
+
+ private void setGoalTypeComboBox(ToolTipWrapper v){
+ GoalTypeComboBox.setSelectedItem(v);
+ }
+
+ private void setOperatorComboBox(ToolTipWrapper v){
+ OperatorComboBox.setSelectedItem(v);
+ }
+
+ private void setExecutableFileTextField(String v){
+ ExecutableFileTextField.setText(v);
+ }
+
+ private void setResultTagComboBox(String v){
+ ResultTagComboBox.setSelectedItem(v);
+ }
+
+ private void setArithmeticResultTagTextField(String v){
+ ArithmeticResultTagTextField.setText(v);
+ }
+
+ private void setAnswerTypeComboBox(String v){
+ AnswerTypeComboBox.setSelectedItem(v);
+ }
+
+ private void setAnswerTagTextField(String v){
+ AnswerTagTextField.setText(v);
+ }
+
+ private void setResultTag2ComboBox(String v){
+ ResultTag2ComboBox.setSelectedItem(v);
+ }
+
+ private void setParameterComboBox(String v){
+ ParameterComboBox.setSelectedItem(v);
+ }
+
+ private void setBooleanTextField(String v){
+ BooleanTextField.setText(v);
+ }
+
+ private void setGoal1TextField(String v){
+ Goal1TextField.setText(v);
+ }
+
+ private void setGoal2TextField(String v){
+ Goal2TextField.setText(v);
+ }
+
+ private void setValueTextField(String v){
+ ValueTextField.setText(v);
+ }
+
+ private void setSubgoalTextField(String v){
+ SubgoalTextField.setText(v);
+ }
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextField AnswerTagTextField;
+ private javax.swing.JComboBox AnswerTypeComboBox;
+ private javax.swing.JTextField ArithmeticResultTagTextField;
+ private javax.swing.JPanel ArtifactPanel;
+ private javax.swing.JComboBox BooleanResultTagsComboBox;
+ private javax.swing.JTextField BooleanTextField;
+ private javax.swing.JButton DeleteButton;
+ private javax.swing.JButton DownButton;
+ private javax.swing.JTextField ExecutableFileTextField;
+ private javax.swing.JTextField Goal1TextField;
+ private javax.swing.JTextField Goal2TextField;
+ private javax.swing.JTextField GoalIDTextField;
+ private javax.swing.JComboBox GoalTypeComboBox;
+ private javax.swing.JComboBox OperatorComboBox;
+ private javax.swing.JComboBox ParameterComboBox;
+ private javax.swing.JComboBox PreviousMatchanyComboBox;
+ private javax.swing.JComboBox ResultTag2ComboBox;
+ private javax.swing.JComboBox ResultTagComboBox;
+ private javax.swing.JTextField SubgoalTextField;
+ private javax.swing.JButton UpButton;
+ private javax.swing.JTextField ValueTextField;
+ private javax.swing.JLabel rowLabel;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalValues.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalValues.java
new file mode 100644
index 000000000..18286fa8c
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalValues.java
@@ -0,0 +1,158 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package GoalsUI;
+
+import static GoalsUI.ParamReferenceStorage.GoalType_ITEMS;
+import static GoalsUI.ParamReferenceStorage.Operator_ITEMS;
+import static GoalsUI.ParamReferenceStorage.answerTypes;
+import static GoalsUI.ParamReferenceStorage.goalInput;
+import static GoalsUI.ParamReferenceStorage.opInput;
+import static GoalsUI.ParamReferenceStorage.resultTagInput;
+import java.util.List;
+
+
+/**
+ *
+ * @author Dan
+ */
+
+//****The param parsing in this class is limited to where the param value's corresponding index is on the goal line.
+ //If at any point this alignment is modified with less or more params, this code will need to be revised
+public class GoalValues {
+ //Values to be obtained
+ String goalID, resultTag, answerTag, answerType, booleanExp, goal1, goal2, value, subgoalList, executableFile;
+
+ ToolTipHandlers.ToolTipWrapper goalType, operator;
+
+ //Constructor for loading goals into the UI
+ GoalValues(String goalLine, List resultTags){
+ goalID = resultTag = answerType = answerTag = booleanExp = goal1 = goal2 = value = subgoalList = executableFile = "";
+ goalType = null;
+ operator = Operator_ITEMS[0];
+ //by default set the result tag to the first result tag in the resultTags list (Warning: an error will occur if there is nothing the results tags list)
+ resultTag = resultTags.get(0);
+ answerType = answerTypes[0];
+
+ String[] paramParsedLine = goalLine.split(" : ");
+
+ //Get goal ID
+ goalID = paramParsedLine[0].split(" = ")[0].trim();
+
+ //System.out.println(paramParsedLine[0].split(" = ")[1]);
+
+
+
+ //Get goal type
+ if(paramParsedLine[0].split(" = ")[1].trim().equals("count")){
+ if(paramParsedLine.length > 2)
+ goalType = GoalType_ITEMS[10]; //count_matches
+ else
+ goalType = GoalType_ITEMS[9]; //count_value
+ }
+ else
+ goalType = itemFinder(GoalType_ITEMS, paramParsedLine[0].split(" = ")[1].trim());
+
+ if(opInput.contains(goalType.getItem())){
+ operator = itemFinder(Operator_ITEMS, paramParsedLine[1]);
+ resultTag = paramParsedLine[2];
+
+ //Overwrite the goaltype to "matchExpression" if the result tag has a parenthesis (this indicates an arithmetic expression)
+ if(resultTag.contains("(")){
+ goalType = GoalType_ITEMS[12];
+ //take out outer parens in resultTag
+ if(resultTag.startsWith("(") && resultTag.endsWith(")"))
+ resultTag = resultTag.substring(1, resultTag.length() -1);
+ }
+
+ answerTagModifier(paramParsedLine[3], resultTags);
+ }
+ else if(goalInput.contains(goalType.getItem())){
+ goal1 = paramParsedLine[1].trim();
+ goal2 = paramParsedLine[2].trim();
+ }
+ else if(resultTagInput.contains(goalType.getItem())){
+ resultTag = paramParsedLine[1].trim();
+ }
+ else if("boolean".equals(goalType.getItem())){
+ booleanExp = paramParsedLine[1];
+ }
+ else if("count_greater".equals(goalType.getItem())){
+ value = paramParsedLine[1].trim();
+ subgoalList = paramParsedLine[2].trim();
+ //Chop off the surrounding parens since this will be readded when written
+ if(subgoalList.startsWith("(") && subgoalList.endsWith(")"))
+ subgoalList = subgoalList.substring(1, subgoalList.length() -1);
+ }
+ else if("execute".equals(goalType.getItem())){
+ executableFile = paramParsedLine[1];
+ resultTag = paramParsedLine[2];
+ answerTagModifier(paramParsedLine[3], resultTags);
+ }
+ else
+ System.out.println("Goal Type doesn't match any");
+ }
+
+ //Constructor for temporarily storing values of artifacts in the UI
+ GoalValues(String goalID, ToolTipHandlers.ToolTipWrapper goalType, ToolTipHandlers.ToolTipWrapper operator, String resultTag, String answerType, String answerTag, String booleanExp, String goal1, String goal2, String value, String subgoalList, String executableFile){
+ this.goalID = goalID;
+ this.goalType = goalType;
+ this.operator = operator;
+ this.resultTag = resultTag;
+ this.answerType = answerType;
+ this.answerTag = answerTag;
+ this.booleanExp = booleanExp;
+ this.goal1 = goal1;
+ this.goal2 = goal2;
+ this.value = value;
+ this.subgoalList = subgoalList;
+ this.executableFile = executableFile;
+ }
+
+ //set the answertype & answertag to be displayed on the gui based on the config's answer tag
+ private void answerTagModifier(String aT, List resultTags){
+ if(aT.contains("answer=")){
+ answerTag = aT.split("answer=")[1];
+ }
+ else if(resultTags.contains(aT)){
+ answerTag = aT;
+ answerType = answerTypes[1]; //Result Tags
+ }
+ else if(aT.contains("result.")){
+ answerTag = aT.split("result.")[1];
+ answerType = answerTypes[1]; //Result Tags
+ }
+ else if(aT.contains("parameter.")){
+ answerTag = aT.split("parameter.")[1];
+ answerType = answerTypes[2]; //Parameter
+ }
+ else if(aT.contains("parameter_ascii.")){
+ answerTag = aT.split("parameter_ascii.")[1];
+ answerType = answerTypes[3]; //Parameter_ASCII
+ }
+ }
+
+
+ private ToolTipHandlers.ToolTipWrapper itemFinder(ToolTipHandlers.ToolTipWrapper[] list,String desired){
+ for(ToolTipHandlers.ToolTipWrapper item : list){
+ if(item.getItem().equals(desired)){
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private boolean isInteger(String s){
+ try{
+ Integer.parseInt(s);
+
+ return true;
+ }
+ catch(NumberFormatException ex){
+ return false;
+ }
+ }
+
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsData.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsData.java
new file mode 100644
index 000000000..dfcbe7fe5
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsData.java
@@ -0,0 +1,1249 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package GoalsUI;
+
+import static GoalsUI.ParamReferenceStorage.GoalType_ITEMS;
+import static GoalsUI.ParamReferenceStorage.answerTypes;
+import static GoalsUI.ParamReferenceStorage.booleanResultTypes;
+import static GoalsUI.ParamReferenceStorage.goalInput;
+import static GoalsUI.ParamReferenceStorage.opInput;
+import static GoalsUI.ParamReferenceStorage.resultTagInput;
+import GoalsUI.ToolTipHandlers.ToolTipWrapper;
+import java.awt.Component;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+/**
+ *
+ * @author Dan
+ */
+public class GoalsData {
+ private List listofGoals;
+ final private List resultTagList;
+ final private List parameters;
+ final private List booleanResults;
+ private boolean labloaded;
+ final private String labname;
+ private int rowCount;
+
+ GoalsData(){
+ listofGoals = new ArrayList<>();
+ resultTagList = new ArrayList<>();
+ parameters = new ArrayList<>();
+ booleanResults = new ArrayList<>();
+ labloaded = false;
+ labname = "";
+ rowCount = 0;
+ }
+
+ GoalsData(String labname){
+ listofGoals = new ArrayList<>();
+ resultTagList = new ArrayList<>();
+ parameters = new ArrayList<>();
+ booleanResults = new ArrayList<>();
+ labloaded = false;
+ this.labname = labname;
+ rowCount = 0;
+
+ getData();
+ }
+
+
+//LOADING~~~~~~~~~~~~~~~~~~~~~~~~
+
+ //Checks if the lab exists and will load lab's goals.config if it does
+ private void getData(){
+ //Check if the Folder exists
+ String userHomeFolder = System.getProperty("user.home");
+ File lab = new File(userHomeFolder + File.separator + "labtainer" + File.separator + "trunk" + File.separator + "labs" + File.separator+ labname);
+
+ if(lab.isDirectory()){
+ if(getResultTags(lab) && getGoals()){
+ labloaded = true;
+ getParameters(lab);
+ getBooleanResults(lab);
+ }
+ }
+ else
+ System.out.println("Lab does not exist!");
+ }
+
+ //Updates the resultTagList (all goal panels refer to this list to fill in the resultTag combobox)
+ private boolean getResultTags(File lab){
+ File resultsConfig = new File(lab + File.separator + "instr_config" + File.separator + "results.config");
+ try {
+ if(resultsConfig.exists()){
+ try (FileReader fileReader = new FileReader(resultsConfig)) {
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ String line = bufferedReader.readLine();
+ while (line != null) {
+ if(!line.isEmpty() && line.charAt(0) != '#' && !Character.isWhitespace(line.charAt(0)))
+ resultTagList.add(line.split(" = ")[0]);
+ line = bufferedReader.readLine();
+ }
+ }
+ return true;
+ }
+ else{
+ System.out.println("results.config is missing");
+ return false;
+ }
+ }
+ catch (FileNotFoundException ex) {
+ Logger.getLogger(GoalsUI.class.getName()).log(Level.SEVERE, null, ex);
+ return false;
+ }
+ catch (IOException ex) {
+ Logger.getLogger(GoalsUI.class.getName()).log(Level.SEVERE, null, ex);
+ return false;
+ }
+ }
+
+ //Parses the goals.config to obtain all the relevant goal lines,
+ //extracts the values of each goal line and stores them into a list of "goals"(Goal Values)
+ private boolean getGoals(){
+ //Attempt to set the listofGoals, if it ends up being null then there was an issue accessing the goal lines, which would be paresd into Goal Values
+ listofGoals = getGoalValuesOfConfigFile();
+ if(listofGoals != null){
+ rowCount=listofGoals.size();
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //Get the parameter.config IDs
+ private void getParameters(File lab){
+ File parameterConfig = new File(lab + File.separator + "config" + File.separator + "parameter.config");
+ try {
+ if(parameterConfig.exists()){
+ try (FileReader fileReader = new FileReader(parameterConfig)) {
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ String line = bufferedReader.readLine();
+ while (line != null) {
+ if(!line.isEmpty() && line.charAt(0) != '#' && !Character.isWhitespace(line.charAt(0)))
+ parameters.add(line.split(" : ")[0]);
+ line = bufferedReader.readLine();
+ }
+ }
+ }
+ else
+ System.out.println("parameter.config is missing");
+ }
+ catch (FileNotFoundException ex) {
+ Logger.getLogger(GoalsUI.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ catch (IOException ex) {
+ Logger.getLogger(GoalsUI.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ //Get the result tags that are boolean result types
+ private void getBooleanResults(File lab){
+ File resultsConfig = new File(lab + File.separator + "instr_config" + File.separator + "results.config");
+ try {
+ if(resultsConfig.exists()){
+ try (FileReader fileReader = new FileReader(resultsConfig)) {
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ String line = bufferedReader.readLine();
+ while (line != null) {
+ if(!line.isEmpty() && line.charAt(0) != '#' && !Character.isWhitespace(line.charAt(0)))
+ if(booleanResultTypes.contains(line.split(" : ")[1]))
+ booleanResults.add(line.split(" = ")[0]);
+
+ line = bufferedReader.readLine();
+ }
+ }
+ }
+ else
+ System.out.println("results.config is missing");
+ }
+ catch (FileNotFoundException ex) {
+ Logger.getLogger(GoalsUI.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ catch (IOException ex) {
+ Logger.getLogger(GoalsUI.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+//WRITING~~~~~~~~~~~~~~~~~~~~~~~~
+
+ //Update the results.config file with the user's input
+ protected void writeGoalsConfig(JPanel PanelofGoals){
+ try {
+ Component[] goals = PanelofGoals.getComponents(); //Access the list of goals
+ String goalID,
+ goalType,
+
+ operator,
+ resultTag,
+ answerType,
+
+ booleanExp,
+
+ goal1,
+ goal2,
+
+ value,
+ subgoalList,
+
+ executableFile;
+ String goalsConfigText = "";
+ ErrorHandler error = new ErrorHandler();
+ List goalIDs = new ArrayList(); //Used for goal ID duplication check
+
+ //Iterate through each goal
+ for(int i=0;i < goals.length;i++){
+ error.checkReset(); //Reset the error statuses for a new goal line
+
+ String goalConfigLine = "";
+
+ //Goal ID
+ goalID = ((GoalPanels)goals[i]).getGoalIDTextField().getText();
+ goalIDs.add(goalID);
+ //Checks if goal ID is valid or inputted
+ if(error.checkGoalID(goalID))
+ goalConfigLine += (goalID + " = "); //add to goal ID Config line
+
+ //Goal Type
+ ToolTipHandlers.ToolTipWrapper goalTypeTTW = (ToolTipHandlers.ToolTipWrapper)(((GoalPanels)goals[i]).getGoalTypeComboBox().getSelectedItem());
+ goalType = goalTypeTTW.getItem();
+
+ switch (goalType) {
+ case "matchExpression":
+ goalConfigLine += "matchany : ";
+ break;
+ case "count_value":
+ case "count_matches":
+ goalConfigLine += "count : ";
+ break;
+ default:
+ goalConfigLine += goalType+" : ";
+ break;
+ }
+
+ if(opInput.contains(goalType)){
+ ToolTipHandlers.ToolTipWrapper operatorTTW = (ToolTipHandlers.ToolTipWrapper)(((GoalPanels)goals[i]).getOperatorComboBox().getSelectedItem());
+ operator = operatorTTW.getItem();
+ resultTag = (String)((GoalPanels)goals[i]).getResultTagComboBox().getSelectedItem();
+ answerType = (String)((GoalPanels)goals[i]).getAnswerTypeComboBox().getSelectedItem();
+
+ goalConfigLine += operator+" : ";
+ goalConfigLine += resultTag+" : ";
+ goalConfigLine += answerHandler(answerType, (GoalPanels)goals[i]);
+ }
+
+ else if(goalInput.contains(goalType)){
+ goal1 = ((GoalPanels)goals[i]).getGoal1TextField().getText();
+ goal2 = ((GoalPanels)goals[i]).getGoal2TextField().getText();
+
+ ArrayList listOfAboveGoals = getAboveGoals("GOAL1&2", i, goals);
+ if(error.checkGoal1(goal1, listOfAboveGoals))
+ goalConfigLine += goal1+" : ";
+ if(error.checkGoal2(goal2, listOfAboveGoals))
+ goalConfigLine += goal2;
+ }
+
+ else if(resultTagInput.contains(goalType)){
+ resultTag = (String)((GoalPanels)goals[i]).getResultTagComboBox().getSelectedItem();
+ goalConfigLine += resultTag;
+ }
+
+ else if("boolean".equals(goalType)){
+ booleanExp = ((GoalPanels)goals[i]).getBooleanTextField().getText();
+
+ if(error.checkBooleanExp(booleanExp, getAboveGoals("BOOLEAN", i, goals), booleanResults)){
+ goalConfigLine += booleanExp;
+ }
+ }
+
+ else if("count_greater".equals(goalType)){
+ value = ((GoalPanels)goals[i]).getValueTextField().getText();
+ subgoalList = ((GoalPanels)goals[i]).getSubgoalTextField().getText();
+
+ if(error.checkValueAndSubgoals(value, subgoalList, getAboveGoals("ALL", i, goals), booleanResults)){
+ goalConfigLine += value+" : ";
+ goalConfigLine += "(";
+ goalConfigLine += subgoalList;
+ goalConfigLine += ")";
+ }
+
+
+
+ }
+ else if("execute".equals(goalType)){
+ executableFile = ((GoalPanels)goals[i]).getExecutableFileTextField().getText();
+ resultTag = (String)((GoalPanels)goals[i]).getResultTagComboBox().getSelectedItem();
+ answerType = (String)((GoalPanels)goals[i]).getAnswerTypeComboBox().getSelectedItem();
+
+ goalConfigLine += executableFile+" : ";
+ goalConfigLine += resultTag+" : ";
+ goalConfigLine += answerHandler(answerType, (GoalPanels)goals[i]);
+ }
+ else if("matchExpression".equals(goalType)){
+ ToolTipHandlers.ToolTipWrapper operatorTTW = (ToolTipHandlers.ToolTipWrapper)(((GoalPanels)goals[i]).getOperatorComboBox().getSelectedItem());
+ operator = operatorTTW.getItem();
+
+ //May need modification /validation
+ String rt = (String)((GoalPanels)goals[i]).getArithmeticResultTagTextField().getText();
+ resultTag="";
+ if(error.checkArithRT(rt)){ //NOTE: the checkArithRT is incomplete and simply returns 'true'
+ resultTag += "(";
+ resultTag += rt;
+ resultTag += ")";
+ }
+
+ answerType = (String)((GoalPanels)goals[i]).getAnswerTypeComboBox().getSelectedItem();
+
+ goalConfigLine += operator+" : ";
+ goalConfigLine += resultTag+" : ";
+ goalConfigLine += answerHandler(answerType, (GoalPanels)goals[i]);
+ }
+
+
+ //If there's no error, put the goalConfigLine in the resultsConfigText string,
+ //Otherwise the overallPass of the user input is false
+ if(error.userInputCheck(i+1)){
+ if(i < goals.length-1)
+ goalConfigLine+= System.lineSeparator();
+ //Add the goal config line to the Results Config text
+ goalsConfigText += goalConfigLine;
+ }
+ else
+ error.fail();
+ }
+
+ //Check for duplicate goal IDs
+ error.checkDuplicateGoalIDs(goalIDs, booleanResults);
+
+
+ if(error.passStatus()){
+ //Resets the results.config file
+ File goalsConfigFile = initializeGoalsConfig();
+
+ try ( //Write the resultsConfigText to the results.config
+ BufferedWriter writer = new BufferedWriter(new FileWriter(goalsConfigFile, true))) {
+ writer.write(goalsConfigText);
+ }
+ }
+ else
+ JOptionPane.showMessageDialog(null, error.toString(), "INPUT ERROR", JOptionPane.ERROR_MESSAGE);
+ }
+ catch (IOException ex) {
+ Logger.getLogger(GoalsUI.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ //Builds the string bit to be added in the goals.config that describes the answer for a goal
+ private String answerHandler(String answerType, GoalPanels goal){
+ String answer = "";
+
+ if(answerType.equals(answerTypes[0])){ //Literal
+ answer += "answer=";
+ answer += goal.getAnswerTagTextField().getText();
+ }
+ else if(answerType.equals(answerTypes[1])){ //Result Tag
+ answer += "result.";
+ answer += (String)(goal.getResultTag2ComboBox().getSelectedItem());
+ }
+ else if(answerType.equals(answerTypes[2])){ //Parameter
+ answer += "parameter.";
+ answer += (String)(goal.getParameterComboBox().getSelectedItem());
+ }
+ else if(answerType.equals(answerTypes[3])){ //Parameter ASCII
+ answer += "parameter_ascii.";
+ answer += (String)(goal.getParameterComboBox().getSelectedItem());
+ }
+ else
+ System.out.println("Issue writing answer in the goals.config");
+
+ return answer;
+ }
+
+ //Checks if the goals.config file exists and prepares the goals.config file for the lab
+ private File initializeGoalsConfig() throws IOException{
+ //Get the filepath for the lab's goals.config
+ String userHomeFolder = System.getProperty("user.home");
+ File goalsConfigFile = new File(userHomeFolder + File.separator + "labtainer" + File.separator + "trunk" + File.separator + "labs" + File.separator + labname + File.separator + "instr_config" + File.separator + "goals.config");
+
+ //May not be necessary, subject to remove the base text, perhaps there is an option for the user to add their own comments
+ String baseText =
+ "# goals.config" + System.lineSeparator()
+ + "#" + System.lineSeparator()
+ + "# Please see the Labtainer Lab Designer User Guide" + System.lineSeparator();
+
+ if(goalsConfigFile.exists()){
+ //Overwrite goals.config file if it already exists
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(goalsConfigFile, false))) {
+ writer.write(baseText);
+ }
+ return goalsConfigFile;
+ }
+ else if(goalsConfigFile.createNewFile()){
+ //Create new goals.config file otherwise(if it does not already exist)
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(goalsConfigFile))) {
+ writer.write(baseText);
+ }
+ return goalsConfigFile;
+ }
+ else{ //File could not be created so return error message
+ System.out.println("Goals Config File couldn't be initialzed.");
+ return null;
+ }
+ }
+
+ //Handles all the error data and error checking before writing the goals.config
+ protected class ErrorHandler{
+ private boolean overallPass;
+ private String errorMsg;
+ boolean
+ goalError,
+ goalIDMissing,
+
+ goal1Error,
+ goal1Missing,
+ goal2Error,
+ goal2Missing,
+
+ booleanExpCharError,
+ booleanExpTagError,
+ booleanExpNotError,
+ booleanExpStartError,
+ booleanExpEndError,
+ booleanParensError,
+ booleanAlternateError,
+ booleanMissing,
+
+ arithRTCharError,
+ arithRTMissing,
+
+ valueError,
+ valueMissing,
+ subgoalError,
+ subgoalMissing;
+
+ ErrorHandler(){
+ overallPass = true;
+ errorMsg = "";
+ checkReset();
+ }
+
+ void fail(){
+ overallPass = false;
+ }
+
+ //Rests the error status(used right before looking at new goal line)
+ private void checkReset(){
+ goalError = false;
+ goalIDMissing = false;
+
+ goal1Error = false;
+ goal1Missing = false;
+ goal2Error = false;
+ goal2Missing = false;
+
+ booleanExpCharError = false;
+ booleanExpTagError = false;
+ booleanExpNotError = false;
+ booleanExpStartError = false;
+ booleanExpEndError = false;
+ booleanParensError = false;
+ booleanAlternateError = false;
+ booleanMissing = false;
+
+ arithRTCharError = false;
+ arithRTMissing = false;
+
+ valueError = false;
+ valueMissing = false;
+ subgoalError = false;
+ subgoalMissing = false;
+ }
+
+
+
+ //Builds error message detailing the errors that appear in the user input
+ boolean userInputCheck(int goalIndex){
+ boolean rowPassed = true;
+ String infoMsg = "Goal Line: " + goalIndex + System.lineSeparator();
+
+ if(goalError){
+ rowPassed = false;
+ infoMsg+= "-Make sure your Goal ID has only alphanumeric characters or underscores." + System.lineSeparator();
+ }
+ if(goalIDMissing){
+ rowPassed = false;
+ infoMsg+= "-Goal ID input is missing." + System.lineSeparator();
+ }
+
+
+ if(goal1Error){
+ rowPassed = false;
+ infoMsg+= "-Make sure that Goal 1 is a 'matchany' goal above this line or a results boolean." + System.lineSeparator();
+ }
+ if(goal1Missing){
+ rowPassed = false;
+ infoMsg+= "-Goal 1 input is missing." + System.lineSeparator();
+ }
+ if(goal2Error){
+ rowPassed = false;
+ infoMsg+= "-Make sure that Goal 2 is a 'matchany' goal above this line or a results boolean." + System.lineSeparator();
+ }
+ if(goal2Missing){
+ rowPassed = false;
+ infoMsg+= "-Goal 2 input is missing." + System.lineSeparator();
+ }
+
+
+ if(booleanExpCharError || booleanExpTagError){
+ rowPassed = false;
+ infoMsg+= "-Make sure Boolean Expression contains only result booleans, non-matchacross goal IDs above this goal line," + System.lineSeparator() +
+ "parentheses, and boolean operators(and, or, and_not, or_not, not)." + System.lineSeparator();
+ }
+ if(booleanExpNotError){
+ rowPassed = false;
+ infoMsg+= "-The 'not' boolean operator can only appear at the beginning of a boolean expression." + System.lineSeparator();
+ }
+ if(booleanExpStartError || booleanExpEndError || booleanParensError || booleanAlternateError){
+ rowPassed = false;
+ infoMsg+= "-Make sure your expression is formatted correctly: Proper Parentheses and making sure an item precedes and follows " + System.lineSeparator()
+ + "a boolean operator." + System.lineSeparator();
+ }
+ if(booleanMissing){
+ rowPassed = false;
+ infoMsg+= "-Boolean input is missing." + System.lineSeparator();
+ }
+
+
+ if(arithRTCharError){
+ rowPassed = false;
+ infoMsg+= "-Make sure Arithmetic Result Tag is formatted correctly." + System.lineSeparator();
+ }
+ if(arithRTMissing){
+ rowPassed = false;
+ infoMsg+= "-Arithmetic Result Tag input is missing." + System.lineSeparator();
+ }
+
+
+ if(valueError){
+ rowPassed = false;
+ infoMsg+= "-Value can only be a positive number(includes zero) less than the number of subgoal items." + System.lineSeparator();
+ }
+ if(valueMissing){
+ rowPassed = false;
+ infoMsg+= "-Value input is missing." + System.lineSeparator();
+ }
+ if(subgoalError){
+ rowPassed = false;
+ infoMsg+= "-Make sure your Subgoal list is seperated by commas(', ') and only contains goals from above this goal line" + System.lineSeparator()
+ + "and/or result booleans." + System.lineSeparator();
+ }
+ if(subgoalMissing){
+ rowPassed = false;
+ infoMsg+= "-Subgoal List input is missing." + System.lineSeparator();
+ }
+
+ if(!rowPassed)
+ errorMsg += (infoMsg + System.lineSeparator());
+
+ return rowPassed;
+ }
+
+ //Checks is goal ID is missing or has invalid characters(valid: alphanumeric, and underscores)
+ boolean checkGoalID(String goalID){
+ if(goalID.isEmpty() || goalID.equals("")){
+ goalIDMissing = true;
+ return false;
+ }
+ else if(!goalID.matches("^[a-zA-Z0-9_-]+$")){
+ goalError = true;
+ return false;
+ }
+ else
+ return true;
+ }
+
+
+ //Checks if goal 1 is either an above goal or a boolean results
+ boolean checkGoal1(String goal1, List listOfAboveGoals){
+ if(goal1.isEmpty() || goal1.equals("")){
+ goal1Missing = true;
+ return false;
+ }
+ else if(!listOfAboveGoals.contains(goal1) && !booleanResults.contains(goal1)){
+ goal1Error = true;
+ return false;
+ }
+ else
+ return true;
+ }
+
+ //Checks if goal 2 is either an above goal or a boolean results
+ boolean checkGoal2(String goal2, List listOfAboveGoals){
+ if(goal2.isEmpty() || goal2.equals("")){
+ goal2Missing = true;
+ return false;
+ }
+ else if(!listOfAboveGoals.contains(goal2) && !booleanResults.contains(goal2)){
+ goal2Error = true;
+ return false;
+ }
+ else
+ return true;
+ }
+
+ //Checks if boolean expression is valid: (The checking may have some overlap thta may need to be recoded)
+ boolean checkBooleanExp(String booleanExp, List nonMAAGoals, List booleanResults) {
+ String[] booleanOperators = {"and", "or", "and_not", "or_not"};
+
+ if(booleanExp.isEmpty() || booleanExp.equals("")){
+ booleanMissing = true;
+ return false;
+ }
+
+ //Does the boolean exp contain invalid chars (char not: alphnumeric, undescore, hyphen, whitespace, parenthesis)
+ if(!booleanExp.matches("^[a-zA-Z0-9_() -]+$")){
+ booleanExpCharError = true;
+ return false;
+ }
+
+ //Reformat the boolean expression string to identitfy things that shouldn't be there
+ //Replace all " not" with %
+ booleanExp = " "+booleanExp;
+ //The line above is necessary because when 'not' is used in the beginning there may or may not be a space before it.
+ //Adding the space includes the non-space-preceeded case.
+ booleanExp = booleanExp.replaceAll(" not ", "%");
+
+ booleanExp = booleanExp.trim();
+
+ //System.out.println("OG: "+booleanExp);
+ //System.out.println();
+ //System.out.println("GOALS:");
+
+ //Replace all non Matchacross Goals with an asterisk symbol
+ for(String toReplace : nonMAAGoals){
+ booleanExp = symbolReplace(booleanExp, toReplace, "*");
+ }
+
+ //System.out.println();
+ //System.out.println("RESULT BOOLEANS:");
+ //Replace all non boolean results with an asterisk symbol
+ for(String toReplace : booleanResults){
+ booleanExp = symbolReplace(booleanExp, toReplace, "*");
+ }
+
+ //System.out.println();
+ //System.out.println("BOOLEAN OPERATORS:");
+ //Replace all boolean operators with a pound symbol
+ for(String toReplace : booleanOperators){
+ booleanExp = symbolReplace(booleanExp, toReplace, "#");
+ }
+
+ //System.out.println(booleanExp);
+
+ booleanExp = booleanExp.replaceAll("\\s+","");//removes white space
+
+ //If the boolean expression had a "not " in it, did it not occur at the beginning and/or more than once
+ if(booleanExp.contains("%") && (!booleanExp.startsWith("%") || (booleanExp.indexOf("%") != booleanExp.lastIndexOf("%")))){
+ booleanExpNotError = true;
+ return false;
+ }
+ //Does the reformatted Boolean Expression string pick up alphnumeric(with underscore) substring that doesn't belong in either nonMAAGoals or booleanResults
+ if(!booleanExp.matches("^[%*#()]+$")){
+
+ booleanExpTagError = true;
+ return false;
+ }
+ //Does it start with an operator or a close parens
+ else if(booleanExp.startsWith("#") || booleanExp.startsWith(")")){
+ booleanExpStartError = true;
+ return false;
+ }
+ //Does it end with an operator or an open parens
+ else if(booleanExp.endsWith("#") || booleanExp.endsWith("(")){
+ booleanExpEndError = true;
+ return false;
+ }
+ //Does the boolean expression have bad parens
+ else if(parensHandler(booleanExp)){
+ booleanParensError = true;
+ return false;
+ }
+ //Does it at least have one operator not preceeded and not followed by a nonMAA goal/boolean result
+ else if(alternatationCheck(booleanExp)){
+ booleanAlternateError = true;
+ return false;
+ }
+
+ return true;
+ }
+
+ //Replaces the a substring in the a string with another string
+ String symbolReplace(String booleanExp, String toReplace, String replaceWith){
+ int tRIndex = booleanExp.indexOf(toReplace);
+ while(tRIndex != -1){
+ int indexAfterWord = tRIndex+toReplace.length();
+ int indexBeforeWord = tRIndex-1;
+ //System.out.println(toReplace+": ");
+ //System.out.println("tRIndex: "+tRIndex);
+ //System.out.println("indexAfterWord: "+indexAfterWord);
+
+
+ //IF the word to replace is at the beginning: "toReplace and_not other" -> "* and_not other"
+ if(tRIndex == 0 && booleanExp.charAt(indexAfterWord) == ' '){
+ booleanExp = booleanExp.substring(0, indexAfterWord).replaceFirst(toReplace, replaceWith)+
+ booleanExp.substring(indexAfterWord, booleanExp.length());
+ }
+ //IF the word to replace is at the end: "other and_not toRepalce" -> "other and_not *"
+ else if(tRIndex == booleanExp.length()-toReplace.length() &&
+ booleanExp.charAt(booleanExp.length()-toReplace.length()-1) == ' '){
+ booleanExp = booleanExp.substring(0, tRIndex) +
+ booleanExp.substring(tRIndex, booleanExp.length()).replaceFirst(toReplace, replaceWith);
+ }
+ /*
+ IF the word to replace is in the middle: "other and toReplace and another" -> "other and * and another"
+ "(other and toReplace) and another" -> "(other and *) and another"
+ "(toReplace and other) and another" -> "(* and other) and another"
+ "(toReplace) and another" -> "(*) and another"
+ */
+ else if((booleanExp.charAt(indexBeforeWord) == ' ' || booleanExp.charAt(indexBeforeWord) == '(') &&
+ (booleanExp.charAt(indexAfterWord) == ' ' || booleanExp.charAt(indexAfterWord) == ')')){
+ booleanExp = booleanExp.substring(0, tRIndex)+
+ booleanExp.substring(tRIndex, indexAfterWord).replaceFirst(toReplace, replaceWith)+
+ booleanExp.substring(indexAfterWord, booleanExp.length());
+ }
+
+ //System.out.println(booleanExp);
+ //System.out.println();
+
+ indexAfterWord = tRIndex+replaceWith.length(); //The indexAfterWord is shifted since the word has been deleted and replaced
+ if(indexAfterWord aboveGoals, List booleanResults){
+ boolean pass = true;
+
+ if(subgoalList.isEmpty() || subgoalList.equals("")){
+ subgoalMissing = true;
+ pass = false;
+ }
+ if(value.isEmpty() || value.equals("")){
+ valueMissing = true;
+ pass = false;
+ }
+
+ if(!subgoalMissing && !valueMissing){
+ String[] subgoals = subgoalList.split(", ");
+ for(String subgoal : subgoals){
+ subgoal = subgoal.replaceAll("\\s+", "");
+ if(!aboveGoals.contains(subgoal) && !booleanResults.contains(subgoal)){
+ subgoalError = true;
+ pass = false;
+ }
+ }
+
+ if(!value.matches("^[0-9]+$") || subgoals.length <= Integer.parseInt(value)){
+ valueError = true;
+ pass = false;
+ }
+
+
+ }
+ return pass;
+ }
+
+ //Checks if the result tag has any arithmetic errors (NEEDS REVISION) ***Incomplete
+ boolean checkArithRT(String arithRT){
+ if(arithRT.isEmpty() || arithRT.equals("")){
+ arithRTMissing = true;
+ return false;
+ }
+// for(String rt : resultTagList)
+// arithRT.replaceAll(rt, "0");
+// arithRT.replaceAll("\\s+","");//removes white space
+//
+// if(!arithRT.matches("^[-+0*/&0-9()]+$")){
+// arithRTCharError = true;
+// return false;
+// }
+
+ return true;
+ }
+
+
+
+
+
+ //Check if there are goalID duplicates (this includes checking duplicates with boolean results)
+ void checkDuplicateGoalIDs(List goalIDs, List booleanResults){
+ ArrayList goalIDSet = new ArrayList<>();
+
+ //Store all the indices for each unique goal ID
+ for(int i=0;i 1){
+ duplicateErrorMsg+= "Duplicate Goal ID: \"" + goal.goalID + "\" on rows ";
+
+ for(int i=0;i indices;
+
+ GoalIDIndices(String goalID, int index){
+ this.goalID = goalID;
+ indices = new ArrayList<>();
+ indices.add(index);
+ isResultTagBoolean = false;
+ }
+
+ void addIndex(int index){
+ indices.add(index);
+ }
+ }
+
+ //Is the goal ID already in the duplicate list?
+ boolean isDuplicate(List goalIDSet, String goalID){
+ for(GoalIDIndices goalIndices : goalIDSet){
+ if(goalIndices.goalID.equals(goalID))
+ return true;
+ }
+ return false;
+ }
+
+ //Get the duplicate object based on the duplicate string
+ GoalIDIndices getDuplicate(List goalIDSet, String goalID){
+ for(GoalIDIndices goalIndices : goalIDSet){
+ if(goalIndices.goalID.equals(goalID))
+ return goalIndices;
+ }
+ return null;
+ }
+
+ @Override
+ public String toString(){
+ return errorMsg;
+ }
+
+ boolean passStatus(){
+ return overallPass;
+ }
+
+
+ }
+
+
+//GENERAL~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ //Gets a list of GoalValues from the the current state of the goals.config file
+ protected ArrayList getGoalValuesOfConfigFile(){
+ ArrayList officialListofGoals = new ArrayList<>();
+
+ ArrayList goalLines = getGoalLines();
+ if(goalLines != null){
+ for(String goalLine : goalLines){
+ GoalValues values = new GoalValues(goalLine, resultTagList);
+ officialListofGoals.add(values);
+ }
+ return officialListofGoals;
+ }
+ else
+ return null;
+ }
+
+ //Get the list of goal lines from the goals.config that need to be parsed
+ private ArrayList getGoalLines(){
+ ArrayList goals = new ArrayList<>();
+
+ try {
+ String userHomeFolder = System.getProperty("user.home");
+ File lab = new File(userHomeFolder + File.separator + "labtainer" + File.separator + "trunk" + File.separator + "labs" + File.separator+ labname);
+ File goalsConfig = new File(lab+"/instr_config/goals.config");
+
+ //Get the artifact lines
+ if(goalsConfig.exists()){
+ try (FileReader fileReader = new FileReader(goalsConfig)) {
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ String line = bufferedReader.readLine();
+ while (line != null) {
+ //just checks if the first character is: not empty, not a hash, and not whitspace)
+ if(!line.isEmpty() && line.charAt(0) != '#' && !Character.isWhitespace(line.charAt(0)))
+ goals.add(line);
+
+ line = bufferedReader.readLine();
+ }
+ }
+ return goals;
+ }
+ else{
+ System.out.println("No goals.config file in the loaded lab!");
+ return null;
+ }
+ }
+ catch (IOException e) {
+ System.out.println("Issue with getting goals.config goals");
+ return null;
+ }
+ }
+
+
+ //Updates the list of goals
+ protected void updateListofGoals(JPanel PanelofGoals){
+ Component[] goals = PanelofGoals.getComponents(); //Access the list of goals
+
+ ArrayList listofGoalsTMP = new ArrayList<>();
+
+ //Iterate through each goal panel in the UI and add its values to the temp list of goal values
+ for (Component goal : goals) {
+ //Goal ID
+ String goalID = ((GoalPanels) goal).getGoalIDTextField().getText();
+ //GoalType
+ ToolTipWrapper goalType = (ToolTipWrapper)((GoalPanels) goal).getGoalTypeComboBox().getSelectedItem();
+
+
+ //Operator
+ ToolTipWrapper operator = (ToolTipWrapper)((GoalPanels) goal).getOperatorComboBox().getSelectedItem();
+ String resultTag = "";
+ if(goalType.equals(GoalType_ITEMS[12])){ //matchExpression
+ resultTag = ((GoalPanels) goal).getArithmeticResultTagTextField().getText();
+ }
+ else{
+ //Result Tag
+ resultTag = (String)((GoalPanels) goal).getResultTagComboBox().getSelectedItem();
+ }
+ //Answer Type
+ String answerType = (String)((GoalPanels) goal).getAnswerTypeComboBox().getSelectedItem();
+ //Answer Tag
+ String answerTag = "";
+ if(answerType.equals(answerTypes[0])) //Literal
+ answerTag = ((GoalPanels) goal).getAnswerTagTextField().getText();
+ else if(answerType.equals(answerTypes[1])) //Result Tag
+ answerTag = (String)(((GoalPanels) goal).getResultTag2ComboBox().getSelectedItem());
+ else if(answerType.equals(answerTypes[2]) || answerType.equals(answerTypes[3])) //Parameter and Parameter ASCII
+ answerTag = (String)(((GoalPanels) goal).getParameterComboBox().getSelectedItem());
+
+
+
+ //Boolean Expression
+ String booleanExp = ((GoalPanels) goal).getBooleanTextField().getText();
+
+
+ //Goal 1
+ String goal1 = ((GoalPanels) goal).getGoal1TextField().getText();
+ //Goal 2
+ String goal2 = ((GoalPanels) goal).getGoal2TextField().getText();
+
+
+ //Value
+ String value = ((GoalPanels) goal).getValueTextField().getText();
+ //Subgoal List
+ String subgoalList = ((GoalPanels) goal).getSubgoalTextField().getText();
+
+
+ //Executable File
+ String executableFile = ((GoalPanels) goal).getExecutableFileTextField().getText();
+
+ listofGoalsTMP.add(new GoalValues(goalID, goalType, operator, resultTag, answerType, answerTag, booleanExp, goal1, goal2, value, subgoalList, executableFile));
+ }
+ listofGoals = listofGoalsTMP; //overwrite the old listofGoals with the temp listofGoals
+ }
+
+ //Swaps goal order in the list of goals and then redraws them
+ protected void swapGoals(String type, int rowIndex){
+ switch(type){
+ case "UP":
+ if(rowIndex > 0){
+ //System.out.println("UP: "+listofGoals.get(rowIndex).resultTag+" Index: "+rowIndex);
+ Collections.swap(listofGoals, rowIndex, rowIndex-1);
+ }
+ break;
+ case "DOWN":
+ if(rowIndex < rowCount-1){
+ //System.out.println("DOWN: "+listofGoals.get(rowIndex).resultTag);
+ Collections.swap(listofGoals, rowIndex, rowIndex+1);
+ }
+ break;
+ default:
+ System.out.println("swap case not registered");
+ }
+ }
+
+
+ //Compares the data of two lists of ArtifactValues. If there is a difference then return 'true', 'false' otherwise
+ static boolean goalValuesDiffer(List list1, List list2){
+ if(list1 == null || list2 == null || list1.size() != list2.size())
+ return true;
+ else{
+ //This is a gross implemenation of copmaring each individual value between two sets of Goal Values (Maybe conisder implementing the GoalValues Class as a comparable)
+ for(int i=0;i getAboveGoals(String type, int rowIndex, Component[] goals){
+ ArrayList aboveGoals = new ArrayList<>();
+ for(int i=0;i();
+ rowCount = listofGoals.size();
+ }
+
+//RowCount setters
+ void increaseRowCount(){
+ rowCount++;
+ }
+
+ void decreaseRowCount(){
+ rowCount--;
+ }
+
+//Getters
+ boolean isLoaded(){
+ return labloaded;
+ }
+
+ int getRowCount(){
+ return rowCount;
+ }
+
+ List getListofGoals(){
+ return listofGoals;
+ }
+
+ List getResultTagList(){
+ return resultTagList;
+ }
+
+ List getParameters(){
+ return parameters;
+ }
+
+ List getBooleanResults(){
+ return booleanResults;
+ }
+
+//Debug
+ static private void goalValuesDifferDEBUG(List list1, List list2, int i){
+ System.out.println("GOAL: "+i);
+ System.out.println();
+ System.out.println("Goal ID");
+ System.out.println(list1.get(i).goalID + " : " + list2.get(i).goalID);
+ System.out.println();
+ System.out.println("Goal Type");
+ System.out.println(list1.get(i).goalType + " : " + list2.get(i).goalType);
+ System.out.println();
+ System.out.println("Opertor");
+ System.out.println(list1.get(i).operator + " : " + list2.get(i).operator);
+ System.out.println();
+ System.out.println("Result Tag");
+ System.out.println(list1.get(i).resultTag + " : " + list2.get(i).resultTag);
+ System.out.println();
+ System.out.println("Answer Tag");
+ System.out.println(list1.get(i).answerTag + " : " + list2.get(i).answerTag);
+ System.out.println();
+ System.out.println("Boolean Expression");
+ System.out.println(list1.get(i).booleanExp + " : " + list2.get(i).booleanExp);
+ System.out.println();
+ System.out.println("Goal 1");
+ System.out.println(list1.get(i).goal1 + " : " + list2.get(i).goal1);
+ System.out.println();
+ System.out.println("Goal 2");
+ System.out.println(list1.get(i).goal2 + " : " + list2.get(i).goal2);
+ System.out.println();
+ System.out.println("Value");
+ System.out.println(list1.get(i).value + " : " + list2.get(i).value);
+ System.out.println();
+ System.out.println("Subgoal List");
+ System.out.println(list1.get(i).subgoalList + " : " + list2.get(i).subgoalList);
+ System.out.println();
+ System.out.println("Goal ID");
+ System.out.println(list1.get(i).executableFile + " : " + list2.get(i).executableFile);
+ }
+
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsUI.form b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsUI.form
new file mode 100644
index 000000000..1b91e7dbc
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsUI.form
@@ -0,0 +1,186 @@
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsUI.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsUI.java
new file mode 100644
index 000000000..1530dbb3c
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/GoalsUI.java
@@ -0,0 +1,316 @@
+package GoalsUI;
+
+import java.awt.Component;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ *
+ * @author Daniel Liao
+ */
+public class GoalsUI extends javax.swing.JFrame {
+ GoalsData dataUI;
+
+ public GoalsUI() {
+ initComponents();
+ LabNotExist.setVisible(false);
+ dataUI = new GoalsData();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ ScrollPaneOfGoals = new javax.swing.JScrollPane();
+ PanelofGoals = new javax.swing.JPanel();
+ UpdateButton = new javax.swing.JButton();
+ RemoveAllButton = new javax.swing.JButton();
+ jLabel9 = new javax.swing.JLabel();
+ CreateButton = new javax.swing.JButton();
+ jLabel3 = new javax.swing.JLabel();
+ jLabel1 = new javax.swing.JLabel();
+ LabNameTextField = new javax.swing.JTextField();
+ LabNotExist = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ setBackground(new java.awt.Color(255, 255, 255));
+ setMinimumSize(new java.awt.Dimension(1590, 500));
+ setPreferredSize(new java.awt.Dimension(1110, 389));
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ formWindowClosing(evt);
+ }
+ });
+
+ ScrollPaneOfGoals.setAutoscrolls(true);
+ ScrollPaneOfGoals.setMaximumSize(new java.awt.Dimension(1300, 800));
+
+ PanelofGoals.setLayout(new javax.swing.BoxLayout(PanelofGoals, javax.swing.BoxLayout.PAGE_AXIS));
+ ScrollPaneOfGoals.setViewportView(PanelofGoals);
+
+ UpdateButton.setText("Update");
+ UpdateButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ UpdateButtonActionPerformed(evt);
+ }
+ });
+
+ RemoveAllButton.setFont(new java.awt.Font("Dialog", 1, 12)); // NOI18N
+ RemoveAllButton.setText("Remove All");
+ RemoveAllButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ RemoveAllButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel9.setFont(new java.awt.Font("Arial Black", 0, 12)); // NOI18N
+ jLabel9.setText("Lab Name: ");
+
+ CreateButton.setFont(new java.awt.Font("Dialog", 1, 12)); // NOI18N
+ CreateButton.setText("Create");
+ CreateButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ CreateButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel3.setFont(new java.awt.Font("Arial", 1, 12)); // NOI18N
+ jLabel3.setText("Goal Type");
+ jLabel3.setToolTipText("The mode in which a value is found.");
+
+ jLabel1.setFont(new java.awt.Font("Arial", 1, 12)); // NOI18N
+ jLabel1.setText("Goal ID");
+ jLabel1.setToolTipText("The symbolic name of the result, which will be referenced in the goals configuration file. \n\n(It must be alphanumeric, underscores permitted) ");
+
+ LabNameTextField.setPreferredSize(new java.awt.Dimension(6, 25));
+ LabNameTextField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ LabNameTextFieldActionPerformed(evt);
+ }
+ });
+
+ LabNotExist.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
+ LabNotExist.setText("Lab does not exist!");
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(ScrollPaneOfGoals, javax.swing.GroupLayout.DEFAULT_SIZE, 1300, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(CreateButton)
+ .addGap(10, 10, 10)
+ .addComponent(RemoveAllButton)
+ .addGap(98, 98, 98)
+ .addComponent(jLabel9)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(LabNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 378, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addComponent(LabNotExist)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 344, Short.MAX_VALUE)
+ .addComponent(UpdateButton))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(50, 50, 50)
+ .addComponent(jLabel1)
+ .addGap(89, 89, 89)
+ .addComponent(jLabel3)
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(CreateButton)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(RemoveAllButton)
+ .addComponent(jLabel9)
+ .addComponent(LabNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(UpdateButton)
+ .addComponent(LabNotExist)))
+ .addGap(14, 14, 14)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel1)
+ .addComponent(jLabel3))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ScrollPaneOfGoals, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void UpdateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_UpdateButtonActionPerformed
+ update();
+ }//GEN-LAST:event_UpdateButtonActionPerformed
+ private void update(){
+ if(dataUI.isLoaded())
+ dataUI.writeGoalsConfig(PanelofGoals);
+ }
+
+ private void LabNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_LabNameTextFieldActionPerformed
+ loadLab();
+ }//GEN-LAST:event_LabNameTextFieldActionPerformed
+ //Checks if the lab exists and will load lab's goals config if it does
+ private void loadLab(){
+ dataUI = new GoalsData(getLabName());
+
+ if(dataUI.isLoaded()){
+ LabNotExist.setVisible(false);
+ goalsPanelRedraw();
+ }
+ else
+ LabNotExist.setVisible(true);
+ }
+
+ private void CreateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CreateButtonActionPerformed
+ createFreshGoal();
+ }//GEN-LAST:event_CreateButtonActionPerformed
+ //Creates and loads a new goal row *Note: creating a new row does not automatically save the new row into the GoalsData(acti)
+ private void createFreshGoal(){
+ if(dataUI.isLoaded()){
+ dataUI.increaseRowCount();
+ GoalPanels newGoal = new GoalPanels(this, dataUI);
+ PanelofGoals.add(newGoal);
+ PanelofGoals.revalidate();
+ PanelofGoals.repaint();
+ }
+ }
+
+ private void RemoveAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RemoveAllButtonActionPerformed
+ removeAllButton();
+ }//GEN-LAST:event_RemoveAllButtonActionPerformed
+ private void removeAllButton(){
+ if(dataUI.isLoaded()){
+ if(JOptionPane.showConfirmDialog(null, "Are you sure you want to remove all?") == JOptionPane.YES_OPTION){
+ removeAllGoals();
+ dataUI.resetData();
+ }
+ }
+ }
+
+ private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
+ checkUnsavedChangesMade();
+ }//GEN-LAST:event_formWindowClosing
+ //Check if the the current state of the UI matches with what's saved in the goals.config
+ void checkUnsavedChangesMade(){
+ if(dataUI.isLoaded()){
+ dataUI.updateListofGoals(PanelofGoals);
+
+ if(GoalsData.goalValuesDiffer(dataUI.getListofGoals(), dataUI.getGoalValuesOfConfigFile())){
+ int confirmed = JOptionPane.showConfirmDialog(null,
+ "There are Unsaved Changes. Are you sure you want to exit the program?", "Unsaved Changes",
+ JOptionPane.YES_NO_OPTION);
+
+ if (confirmed == JOptionPane.YES_OPTION)
+ dispose();
+ else
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ }
+ else
+ dispose();
+ }
+ }
+
+//General Methods
+ //Updates the list of goals and redraws them on screen
+ void refresh(){
+ dataUI.updateListofGoals(PanelofGoals);
+ goalsPanelRedraw();
+ }
+
+ //Redraws the goals Panel
+ void goalsPanelRedraw(){
+ removeAllGoals();
+ for(int i=0; i < dataUI.getListofGoals().size(); i++)
+ loadGoal(dataUI.getListofGoals().get(i), i+1);
+ }
+
+ //Removes all the goal lines for the lab *note: this doesn't update results.config until the user hits the update button
+ private void removeAllGoals(){
+ Component[] componentList = PanelofGoals.getComponents();
+ for(Component c: componentList)
+ PanelofGoals.remove(c);
+ PanelofGoals.revalidate();
+ PanelofGoals.repaint();
+ }
+
+ //Load's the goals into GUI
+ private void loadGoal(GoalValues goalVal, int rowNum){
+ GoalPanels newGoal = new GoalPanels(this, dataUI, goalVal, rowNum);
+ PanelofGoals.add(newGoal);
+ PanelofGoals.revalidate();
+ PanelofGoals.repaint();
+ }
+
+
+
+ //Gets the labname
+ private String getLabName(){
+ return LabNameTextField.getText();
+ }
+
+ //Gets the panel holding the goals
+ protected JPanel getPanelofGoals(){
+ return PanelofGoals;
+ }
+
+
+ public static void main(String args[]) {
+ /* Set the Nimbus look and feel */
+ //
+ /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ */
+ try {
+ for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ javax.swing.UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(GoalsUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ }
+ //
+ //
+
+ //
+
+ /* Create and display the form */
+ java.awt.EventQueue.invokeLater(() -> {
+ GoalsUI newGoalsUI = new GoalsUI();
+ newGoalsUI.setSize(1000, 1000);
+ newGoalsUI.setVisible(true);
+ });
+ }
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton CreateButton;
+ private javax.swing.JTextField LabNameTextField;
+ private javax.swing.JLabel LabNotExist;
+ private javax.swing.JPanel PanelofGoals;
+ private javax.swing.JButton RemoveAllButton;
+ private javax.swing.JScrollPane ScrollPaneOfGoals;
+ private javax.swing.JButton UpdateButton;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel9;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/ParamReferenceStorage.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/ParamReferenceStorage.java
new file mode 100644
index 000000000..445057a98
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/ParamReferenceStorage.java
@@ -0,0 +1,190 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package GoalsUI;
+
+import GoalsUI.ToolTipHandlers.ToolTipWrapper;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+
+/**
+ *
+ * @author Dan
+ */
+public class ParamReferenceStorage {
+
+ public static final ToolTipWrapper[] GoalType_ITEMS = new ToolTipWrapper[] {
+ //0
+ new ToolTipWrapper("matchany", "Results from all timestamped sets are evaluated. " +
+ "If the answertag names a result, then both that " +
+ "result and the resulttag must occur in the same " +
+ "timestamped set. The ’matchany’ goals are treated " +
+ "as a set of values, each timestamped based on the " +
+ "timestamp of the reference resulttag."),
+ // 1
+ new ToolTipWrapper("matchlast", "only results from the latest timestamped set are " +
+ "evaluated."),
+ // 2
+ new ToolTipWrapper("matchacross", "The resulttag and answertag name results. The " +
+ "operator is applied against values in different " +
+ "timestamped sets. For example, a \"string_diff\" " +
+ "operator would require the named results to have " +
+ "at least two distinct values in different " +
+ "timestamped sets."),
+ // 3
+ new ToolTipWrapper("boolean", "The goal value is computed from a boolean expression " +
+ "consisting of goal_id’s and boolean operators, (\"and\", " +
+ "\"or\", \"and_not\", \"or_not\", and \"not\"), and parenthisis " +
+ "for precedence. The goal_id’s must be from goals defined " +
+ "earlier in the goals.config file, or boolean results " +
+ "from results.config. The goal evalutes to " +
+ "TRUE if the boolen expression evaluates to TRUE for any " +
+ "of the timestamped sets of goal_ids, (see the ’matchany’ " +
+ "discussion above). The goal_id’s cannot include any " +
+ "\"matchacross\" goals. NOTE: evaluation is within " +
+ "timestamped sets. If you want to evaluate across " +
+ "timestamps, use the count_greater_operator below."),
+ // 4
+ new ToolTipWrapper("count_greater", "The goal is TRUE if the count of TRUE subgoals in the " +
+ "list exceeds the given value. The subgoals are " +
+ "summed across all timestamps. The subgoal list is " +
+ "comma-separated within parenthesis."),
+ // 5
+ new ToolTipWrapper("time_before", "Both goal1 and goal2 must be goal_ids from previous " +
+ "matchany, or boolean values from results.config " +
+ "A timestamped goal is created for each goal2 " +
+ "timestamped instance whose timestamp is proceeded " +
+ "by a goal1 timestamped instance. The goal for that " +
+ "timestamp will be TRUE if the goal2 " +
+ "instance is TRUE, and at least one of the goal1 " +
+ "instances is TRUE. These timestamped goals can " +
+ "then be evaluated within boolean goals."),
+ // 6
+ new ToolTipWrapper("time_during", "Both goal1 and goal2 must be goal_ids from previous " +
+ "matchany goal types, or boolean values from " +
+ "results.config. Timestamps include a start and end " +
+ "time, reflecting when the program starts and when it " +
+ "terminates. A timestamped goal is created for each " +
+ "goal2 range that encompasses a goal1 timestamp. " +
+ "The goal for that timestamp will be TRUE if the " +
+ "goal2 instance is TRUE, and at least one goal1 instance " +
+ "is TRUE. These timestamped goals can then be " +
+ "evaluated within boolean goals."),
+ // 7
+ new ToolTipWrapper("time_not_during", "Similar to time_during, but timestamped goals are " +
+ "always created for each goal2. Each such goal is True " +
+ "unless one or more goal1 times occur within a True goal2 " +
+ "range."),
+ // 8
+ new ToolTipWrapper("execute", "The is treated as a file name of a script to " +
+ "execute, with the resulttag and answertag passed to the " +
+ "script as arguments. The resulttag is expected to be " +
+ "one of the symbolic names defined in the results.config " +
+ "file, while the answertag is expected to be a literal " +
+ "value or the symbolic name in the parameters.config file " +
+ "Note: the answertag cannot be a symbolic name from " +
+ "results.config"),
+ // 9
+ new ToolTipWrapper("count_value", "If the remainder of the line only includes a resulttag, " +
+ "then the goal value is assigned the quanity of " +
+ "timestamped files containing the given resulttag. " +
+ "Otherwise the goal value is assigned the " +
+ "quantity of timestamped files having results " +
+ "that satisfy the given operator and arguments."),
+ // 10
+ new ToolTipWrapper("count_matches", "If the remainder of the line only includes a resulttag, " +
+ "then the goal value is assigned the quanity of " +
+ "timestamped files containing the given resulttag. " +
+ "Otherwise the goal value is assigned the " +
+ "quantity of timestamped files having results " +
+ "that satisfy the given operator and arguments."),
+ // 11
+ new ToolTipWrapper("value", "The goal value is assigned the given resulttag value from " +
+ "the most recent timestamped file that contains the resulttag."),
+
+ // 12
+ new ToolTipWrapper("matchExpression", "The resultTag is an arithmetic expression")};
+
+
+ public static final ToolTipWrapper[] Operator_ITEMS = new ToolTipWrapper[] {
+ // 0
+ new ToolTipWrapper("string_equal", "The strings derived from answertag and resulttag " +
+ "are equal."),
+ // 1
+ new ToolTipWrapper("string_diff", "The line_id is an integer line number " +
+ "(starting at one). Use of this to identify " +
+ "lines is discouraged since minor lab changes " +
+ "might alter the count."),
+ // 2
+ new ToolTipWrapper("string_start", "the line_id is a string. This names the " +
+ "first occurrence of a line that starts with " +
+ "this string." ),
+ // 3
+ new ToolTipWrapper("string_end", "The line_id is a string. This names the " +
+ "first occurrence of a line that contains the " +
+ "string." ),
+ // 4
+ new ToolTipWrapper("string_contains", "The line_id is a regular expression. This names the " +
+ "first occurrence of a line that matches the regular " +
+ "expression. Also see the \"GROUP\" field_type." ),
+
+ // 5
+ new ToolTipWrapper("integer_equal", "The line_id is a regular expression. This names the " +
+ "first occurrence of a line that matches the regular " +
+ "expression. Also see the \"GROUP\" field_type." ),
+
+ // 6
+ new ToolTipWrapper("integer_greater", "The line_id is a regular expression. This names the " +
+ "first occurrence of a line that matches the regular " +
+ "expression. Also see the \"GROUP\" field_type." ),
+
+ // 7
+ new ToolTipWrapper("integer_lessthan", "The line_id is a regular expression. This names the " +
+ "first occurrence of a line that matches the regular " +
+ "expression. Also see the \"GROUP\" field_type." )};
+
+
+ //Answer Types
+ public static final String[] answerTypes = new String[] {
+ "Literal",
+ "Result Tag",
+ "Parameter",
+ "Parameter ASCII"
+ };
+
+ //Boolean Result Types
+ public static final ArrayList booleanResultTypes = new ArrayList(Arrays.asList(
+ "CONTAINS",
+ "FILE_REGEX",
+ "LOG_TS",
+ "FILE_REGEX_TS",
+ "LOG_RANGE",
+ "TIME_DELIM"
+ ));
+
+ //Input format 1: [operator : resultTag : answerTag]
+ public static final ArrayList opInput = new ArrayList(Arrays.asList(
+ "matchany",
+ "matchlast",
+ "matchacross",
+ "count_matches"
+ ));
+
+ //Input format 2: [goal1 : goal2]
+ public static final ArrayList goalInput = new ArrayList(Arrays.asList(
+ "time_before",
+ "time_during",
+ "time_not_during"
+ ));
+
+ //Input format 2: [resultTag]
+ public static final ArrayList resultTagInput = new ArrayList(Arrays.asList(
+ "count_value",
+ "value"
+ ));
+
+
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/ToolTipHandlers.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/ToolTipHandlers.java
new file mode 100644
index 000000000..a94b57ec1
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Goals/src/GoalsUI/ToolTipHandlers.java
@@ -0,0 +1,75 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package GoalsUI;
+
+import java.awt.Component;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JList;
+
+/**
+ *
+ * @author Daniel Liao
+ */
+public class ToolTipHandlers {
+ public static interface ToolTipProvider{
+ public String getToolTip();
+ }
+
+ //Stores an item and its correspoinding tool tip. (Items put into a combobox)
+ public static class ToolTipWrapper implements ToolTipProvider{
+ final String item;
+ final String toolTip;
+
+ public ToolTipWrapper(String item, String toolTip){
+ this.item = item;
+ this.toolTip = toolTip;
+ }
+
+ @Override
+ public String getToolTip(){
+ return toolTip;
+ }
+
+ @Override
+ public String toString(){
+ return item;
+ }
+
+ public String getItem(){
+ return item;
+ }
+ }
+
+ //custom combobox renderer to handle ToolTipWrapper objects that contain an string item and string tool tip
+ public static class ComboBoxRenderer extends DefaultListCellRenderer {
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ JComponent component = (JComponent) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ String tip = null;
+ if (value instanceof ToolTipProvider) {
+ ToolTipProvider ttp = (ToolTipProvider) value;
+ tip = ttp.getToolTip();
+ }
+ list.setToolTipText(tip);
+ return component;
+ }
+ }
+
+ //Sets the combo items with associated tool tips (called in the constructors)
+ public static void setComboItems(JComboBox combobox, ToolTipWrapper[] items){
+ ComboBoxRenderer renderer = new ComboBoxRenderer();
+ combobox.setRenderer(renderer);
+
+ for (ToolTipWrapper item : items) {
+ if(((DefaultComboBoxModel)combobox.getModel()).getIndexOf(item) == -1)
+ combobox.addItem(item);
+ }
+ }
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/build.xml b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/build.xml
new file mode 100644
index 000000000..33706d5f7
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/build.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+ Builds, tests, and runs the project ResultsUIAug30.
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/manifest.mf b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/manifest.mf
new file mode 100644
index 000000000..1574df4a2
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/build-impl.xml b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/build-impl.xml
new file mode 100644
index 000000000..89fe3d83d
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/build-impl.xml
@@ -0,0 +1,1420 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set test.src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No tests executed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set JVM to use for profiling in profiler.info.jvm
+ Must set profiler agent JVM arguments in profiler.info.jvmargs.agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set profile.class
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+
+
+
+
+ This target only works when run from inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+ Must select some files in the IDE or set test.class
+ Must select some method in the IDE or set test.method
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+ Must select one file in the IDE or set test.class
+ Must select some method in the IDE or set test.method
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/genfiles.properties b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/genfiles.properties
new file mode 100644
index 000000000..3236f5d57
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=06f40a7b
+build.xml.script.CRC32=dc6ed3ed
+build.xml.stylesheet.CRC32=8064a381@1.80.1.48
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=06f40a7b
+nbproject/build-impl.xml.script.CRC32=486037cd
+nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/private/private.properties b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/private/private.properties
new file mode 100644
index 000000000..9436b19f6
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/private/private.properties
@@ -0,0 +1,2 @@
+compile.on.save=true
+user.properties.file=C:\\Users\\Dan\\AppData\\Roaming\\NetBeans\\8.2\\build.properties
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/project.properties b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/project.properties
new file mode 100644
index 000000000..a6e77a4fd
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/project.properties
@@ -0,0 +1,75 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processor.options=
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# Files in build.classes.dir which should be excluded from distribution jar
+dist.archive.excludes=
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/ResultsUIAug30.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=\
+ ${libs.absolutelayout.classpath}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.external.vm=true
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.8
+javac.target=1.8
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=ResultsUI.ResultsUI
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/project.xml b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/project.xml
new file mode 100644
index 000000000..1f8e85a84
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/nbproject/project.xml
@@ -0,0 +1,15 @@
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+ ResultsUIAug30
+
+
+
+
+
+
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactPanels.form b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactPanels.form
new file mode 100644
index 000000000..f2c6f5439
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactPanels.form
@@ -0,0 +1,283 @@
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactPanels.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactPanels.java
new file mode 100644
index 000000000..10d417cca
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactPanels.java
@@ -0,0 +1,461 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package ResultsUI;
+
+import static ResultsUI.ParamReferenceStorage.FieldType_ITEMS;
+import static ResultsUI.ParamReferenceStorage.LOG_ACCESIBLE_FieldType;
+import static ResultsUI.ParamReferenceStorage.LOG_TS_ACCESSIBLE_LineType;
+import static ResultsUI.ParamReferenceStorage.LineType_ITEMS;
+import static ResultsUI.ParamReferenceStorage.SpecialTimeStampType;
+import static ResultsUI.ParamReferenceStorage.TimestampType_ITEMS;
+import static ResultsUI.ParamReferenceStorage.justFieldType;
+import static ResultsUI.ParamReferenceStorage.lineParamAccessible;
+import static ResultsUI.ParamReferenceStorage.timeStampDelimiterAccessible;
+import ResultsUI.ToolTipHandlers.ToolTipWrapper;
+import static ResultsUI.ToolTipHandlers.setComboItems;
+import java.awt.Dimension;
+import java.util.ArrayList;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+/**
+ *
+ * @author Dan
+ */
+public class ArtifactPanels extends javax.swing.JPanel {
+
+ static Dimension dim = new Dimension(975, 100);
+ ResultsUI uiResult;
+ ResultsData dataUI;
+ int rowNum;
+
+ //Creating fresh artifact line
+ public ArtifactPanels(ResultsUI ui, ArrayList containers, int rowNum) {
+ initComponents();
+ this.uiResult = ui;
+ this.dataUI = ui.dataUI;
+ this.rowNum = rowNum;
+ rowLabel.setText(Integer.toString(rowNum));
+ TimeDelimiterTextField.setVisible(false);
+
+ //Load ComboBox Items
+ ContainerComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(containers.toArray(new String[containers.size()])));
+ setComboItems(FieldTypeComboBox, FieldType_ITEMS);
+ setComboItems(LineTypeComboBox, LineType_ITEMS);
+ setComboItems(TimeStampComboBox, TimestampType_ITEMS);
+
+ this.revalidate();
+ this.repaint();
+ }
+
+ //Loading artifact line
+ public ArtifactPanels(ResultsUI ui, ArrayList containers, int rowNum, String resultTag, String container, String fileID, ToolTipWrapper fieldType, String fieldID, ToolTipWrapper lineType, String lineID, ToolTipWrapper timeStampType, String timeStampDelimiter) {
+ initComponents();
+ this.uiResult = ui;
+ this.dataUI = ui.dataUI;
+ this.rowNum = rowNum;
+ rowLabel.setText(Integer.toString(rowNum));
+ if(!timeStampDelimiterAccessible.contains(timeStampType.getItem()))
+ TimeDelimiterTextField.setVisible(false);
+
+ //Load ComboBox Items
+ ContainerComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(containers.toArray(new String[containers.size()])));
+ setComboItems(FieldTypeComboBox, FieldType_ITEMS);
+ setComboItems(LineTypeComboBox, LineType_ITEMS);
+ setComboItems(TimeStampComboBox, TimestampType_ITEMS);
+
+ //Set Values
+ setContainerComboBox(container);
+ setFieldIDTextField(fieldID);
+ setTagTextField(resultTag);
+ setFileTextField(fileID);
+ setFieldTypeComboBox(fieldType);
+ setLineIDTextField(lineID);
+ setLineTypeComboBox(lineType);
+ setTimeStampComboBox(timeStampType);
+ setTimeDelimiterTextField(timeStampDelimiter);
+
+ this.revalidate();
+ this.repaint();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ ArtifactPanel = new javax.swing.JPanel();
+ TagTextField = new javax.swing.JTextField();
+ ContainerComboBox = new javax.swing.JComboBox<>();
+ FileTextField = new javax.swing.JTextField();
+ FieldTypeComboBox = new javax.swing.JComboBox<>();
+ LineTypeComboBox = new javax.swing.JComboBox<>();
+ FieldIDTextField = new javax.swing.JTextField();
+ LineIDTextField = new javax.swing.JTextField();
+ TimeStampComboBox = new javax.swing.JComboBox<>();
+ TimeDelimiterTextField = new javax.swing.JTextField();
+ DeleteButton = new javax.swing.JButton();
+ rowLabel = new javax.swing.JLabel();
+ UpButton = new javax.swing.JButton();
+ DownButton = new javax.swing.JButton();
+
+ setPreferredSize(new java.awt.Dimension(1110, 69));
+
+ ArtifactPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
+ ArtifactPanel.setMinimumSize(new java.awt.Dimension(1400, 0));
+ ArtifactPanel.setPreferredSize(new java.awt.Dimension(1300, 34));
+
+ FieldTypeComboBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ FieldTypeComboBoxItemStateChanged(evt);
+ }
+ });
+
+ LineTypeComboBox.setToolTipText("Identifies how the line is to be identified");
+ LineTypeComboBox.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Line Type"));
+ LineTypeComboBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ LineTypeComboBoxItemStateChanged(evt);
+ }
+ });
+
+ FieldIDTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Field ID"));
+
+ LineIDTextField.setToolTipText("Parameter based on Line Type");
+ LineIDTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Line ID"));
+
+ TimeStampComboBox.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Timestamp Type"));
+ TimeStampComboBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ TimeStampComboBoxItemStateChanged(evt);
+ }
+ });
+
+ TimeDelimiterTextField.setHorizontalAlignment(javax.swing.JTextField.LEFT);
+ TimeDelimiterTextField.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Time Delimiter"));
+ TimeDelimiterTextField.setMinimumSize(new java.awt.Dimension(20, 100));
+
+ javax.swing.GroupLayout ArtifactPanelLayout = new javax.swing.GroupLayout(ArtifactPanel);
+ ArtifactPanel.setLayout(ArtifactPanelLayout);
+ ArtifactPanelLayout.setHorizontalGroup(
+ ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(ArtifactPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(TagTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ContainerComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 116, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(6, 6, 6)
+ .addComponent(FileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(FieldTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(FieldIDTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 188, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(14, 14, 14)
+ .addComponent(LineTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 165, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(LineIDTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 135, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(TimeStampComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 137, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(TimeDelimiterTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ ArtifactPanelLayout.setVerticalGroup(
+ ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(ArtifactPanelLayout.createSequentialGroup()
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(ArtifactPanelLayout.createSequentialGroup()
+ .addGap(12, 12, 12)
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(TagTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(ContainerComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(FileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(FieldTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addGroup(ArtifactPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(ArtifactPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE, false)
+ .addComponent(LineTypeComboBox)
+ .addComponent(LineIDTextField)
+ .addComponent(TimeStampComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(FieldIDTextField)
+ .addComponent(TimeDelimiterTextField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
+ .addContainerGap(12, Short.MAX_VALUE))
+ );
+
+ ArtifactPanelLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {TimeDelimiterTextField, TimeStampComboBox});
+
+ DeleteButton.setText("Delete");
+ DeleteButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ DeleteButtonActionPerformed(evt);
+ }
+ });
+
+ rowLabel.setFont(new java.awt.Font("Arial", 1, 24)); // NOI18N
+ rowLabel.setText("10");
+
+ UpButton.setText("^");
+ UpButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ UpButtonActionPerformed(evt);
+ }
+ });
+
+ DownButton.setText("v");
+ DownButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ DownButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(rowLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(ArtifactPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 1390, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(UpButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(DownButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(DeleteButton)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(ArtifactPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(rowLabel)
+ .addGap(19, 19, 19))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(UpButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(DownButton))
+ .addComponent(DeleteButton, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE))
+ );
+ }// //GEN-END:initComponents
+
+ private void DeleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DeleteButtonActionPerformed
+ JPanel container = (JPanel)this.getParent();
+ container.remove(this);
+ uiResult.dataUI.rowCount--;
+ uiResult.refresh();
+ }//GEN-LAST:event_DeleteButtonActionPerformed
+
+ private void TimeStampComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_TimeStampComboBoxItemStateChanged
+ timeStampListener();
+ }//GEN-LAST:event_TimeStampComboBoxItemStateChanged
+
+ private void LineTypeComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_LineTypeComboBoxItemStateChanged
+ lineTypeListener();
+ }//GEN-LAST:event_LineTypeComboBoxItemStateChanged
+
+ private void FieldTypeComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_FieldTypeComboBoxItemStateChanged
+ fieldTypeListener();
+ }//GEN-LAST:event_FieldTypeComboBoxItemStateChanged
+
+ private void UpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_UpButtonActionPerformed
+ swapUpdate("UP", rowNum-1); //Subtract rowNum by one to get the proper index number
+ }//GEN-LAST:event_UpButtonActionPerformed
+
+ private void DownButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DownButtonActionPerformed
+ swapUpdate("DOWN", rowNum-1); //Subtract rowNum by one to get the proper index number
+ }//GEN-LAST:event_DownButtonActionPerformed
+
+ //The listeners sees what values are present in their respective fields and then changes the interface based on that(remove or adding other fields)
+ private void lineTypeListener(){
+ ToolTipWrapper lineType = (ToolTipWrapper)LineTypeComboBox.getSelectedItem();
+
+ if(lineType.getItem().equals("NONE")){
+ LineIDTextField.setVisible(false);
+ }
+ else
+ LineIDTextField.setVisible(true);
+
+
+ //Does the line type allow for LOG_TS option in the TimeStampComboBox?
+ if(LOG_TS_ACCESSIBLE_LineType.contains(lineType.getItem())){
+ //Add "LOG_TS" to the timestampComboBox if it's not already
+ if(((DefaultComboBoxModel)TimeStampComboBox.getModel()).getIndexOf(SpecialTimeStampType[0]) == -1)
+ TimeStampComboBox.addItem(SpecialTimeStampType[0]);
+ }
+ else{
+ ToolTipWrapper fieldTypeTTW = (ToolTipWrapper)FieldTypeComboBox.getSelectedItem();
+ //Remove "LOG_TS" from the timestampComboBox if it's not already
+ if(((DefaultComboBoxModel)TimeStampComboBox.getModel()).getIndexOf(SpecialTimeStampType[0]) != -1 && !LOG_ACCESIBLE_FieldType.contains(fieldTypeTTW.getItem()))
+ TimeStampComboBox.removeItem(SpecialTimeStampType[0]);
+ }
+
+ this.revalidate();
+ this.repaint();
+ }
+
+ private void fieldTypeListener(){
+ ToolTipWrapper fieldType = (ToolTipWrapper)FieldTypeComboBox.getSelectedItem();
+
+ //Does the fieldType allow for certain user inputs
+ if(!justFieldType.contains(fieldType.getItem())){
+ FieldIDTextField.setVisible(true);
+ if(lineParamAccessible.contains(fieldType.getItem())){
+ LineTypeComboBox.setVisible(true);
+ LineIDTextField.setVisible(true);
+ }
+ else{
+ setLineTypeComboBox(LineType_ITEMS[0]);
+ LineTypeComboBox.setVisible(false);
+ setLineIDTextField("");
+ LineIDTextField.setVisible(false);
+ }
+ }
+ else{
+ setFieldIDTextField("");
+ FieldIDTextField.setVisible(false);
+ setLineTypeComboBox(LineType_ITEMS[0]);
+ LineTypeComboBox.setVisible(false);
+ setLineIDTextField("");
+ LineIDTextField.setVisible(false);
+ }
+
+ /*
+ If the selected Field Type allows for the "LOG_TS" and "LOG_RANGE" in the timeStampComboBox,
+ then make sure to add them if they aren't there already
+ */
+ if(LOG_ACCESIBLE_FieldType.contains(fieldType.getItem())){
+ //Add "LOG_TS" to the timestampComboBox if it's not already
+ if(((DefaultComboBoxModel)TimeStampComboBox.getModel()).getIndexOf(SpecialTimeStampType[0]) == -1)
+ TimeStampComboBox.addItem(SpecialTimeStampType[0]);
+ //Add "LOG_RANGE" to the timestampComboBox if it's not already
+ if(((DefaultComboBoxModel)TimeStampComboBox.getModel()).getIndexOf(SpecialTimeStampType[1]) == -1)
+ TimeStampComboBox.addItem(SpecialTimeStampType[1]);
+ }
+ /*
+ If the selcted Field Type doesn't allow for "LOG_TS" and "LOG_RANGE" in the timeStampComboBox,
+ then make sure to remove them if they're still in the box
+ */
+ else{
+ ToolTipWrapper lineType = (ToolTipWrapper)LineTypeComboBox.getSelectedItem();
+ //Remove "LOG_TS" from the timestampComboBox if it's not already
+ if(((DefaultComboBoxModel)TimeStampComboBox.getModel()).getIndexOf(SpecialTimeStampType[0]) != -1 && !LOG_TS_ACCESSIBLE_LineType.contains(lineType.getItem()))
+ TimeStampComboBox.removeItem(SpecialTimeStampType[0]);
+ //Remove "LOG_RANGE" from the timestampComboBox if it's there
+ if(((DefaultComboBoxModel)TimeStampComboBox.getModel()).getIndexOf(SpecialTimeStampType[1]) != -1)
+ TimeStampComboBox.removeItem(SpecialTimeStampType[1]);
+ }
+
+ ArtifactPanel.revalidate();
+ ArtifactPanel.repaint();
+ }
+
+ private void timeStampListener(){
+ ToolTipWrapper timestamptype = (ToolTipWrapper)TimeStampComboBox.getSelectedItem();
+ //Does the timestamp Type allow for Time Delimiter input
+ if(timeStampDelimiterAccessible.contains(timestamptype.getItem()))
+ TimeDelimiterTextField.setVisible(true);
+ else{
+ setTimeDelimiterTextField("");
+ TimeDelimiterTextField.setVisible(false);
+ }
+ ArtifactPanel.revalidate();
+ ArtifactPanel.repaint();
+ }
+
+ //Swaps artifact order in the list of artifacts and then redraws them
+ void swapUpdate(String type, int rowIndex){
+ //System.out.println("RowCOUNT(swap): " +dataUI.rowCount);
+ dataUI.updateListofArtifacts(uiResult.getPanelofArtifacts());
+ dataUI.swapArtifacts(type, rowIndex);
+ uiResult.artifactsPanelRedraw();
+ }
+
+
+ //Field Getters
+ public JComboBox getContainerComboBox(){
+ return ContainerComboBox;
+ }
+ public JTextField getFieldIDTextField(){
+ return FieldIDTextField;
+ }
+ public JTextField getTagTextField(){
+ return TagTextField;
+ }
+ public JTextField getFileTextField(){
+ return FileTextField;
+ }
+ public JComboBox getFieldTypeComboBox(){
+ return FieldTypeComboBox;
+ }
+ public JTextField getLineIDTextField(){
+ return LineIDTextField;
+ }
+ public JComboBox getLineTypeComboBox(){
+ return LineTypeComboBox;
+ }
+ public JComboBox getTimeStampComboBox(){
+ return TimeStampComboBox;
+ }
+ public JTextField getTimeStampTextField(){
+ return TimeDelimiterTextField;
+ }
+
+ //Field SETTERS
+ private void setContainerComboBox(String v){
+ ContainerComboBox.setSelectedItem(v);
+ }
+ private void setFieldIDTextField(String v){
+ FieldIDTextField.setText(v);
+ }
+ private void setTagTextField(String v){
+ TagTextField.setText(v);
+ }
+ private void setFileTextField(String v){
+ FileTextField.setText(v);
+ }
+ private void setFieldTypeComboBox(ToolTipWrapper v){
+ FieldTypeComboBox.setSelectedItem(v);
+ }
+ private void setLineIDTextField(String v){
+ LineIDTextField.setText(v);
+ }
+ private void setLineTypeComboBox(ToolTipWrapper v){
+ LineTypeComboBox.setSelectedItem(v);
+ }
+ private void setTimeStampComboBox(ToolTipWrapper v){
+ TimeStampComboBox.setSelectedItem(v);
+ }
+ private void setTimeDelimiterTextField(String v){
+ TimeDelimiterTextField.setText(v);
+}
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JPanel ArtifactPanel;
+ private javax.swing.JComboBox ContainerComboBox;
+ private javax.swing.JButton DeleteButton;
+ private javax.swing.JButton DownButton;
+ private javax.swing.JTextField FieldIDTextField;
+ private javax.swing.JComboBox FieldTypeComboBox;
+ private javax.swing.JTextField FileTextField;
+ private javax.swing.JTextField LineIDTextField;
+ private javax.swing.JComboBox LineTypeComboBox;
+ private javax.swing.JTextField TagTextField;
+ private javax.swing.JTextField TimeDelimiterTextField;
+ private javax.swing.JComboBox TimeStampComboBox;
+ private javax.swing.JButton UpButton;
+ private javax.swing.JLabel rowLabel;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactValues.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactValues.java
new file mode 100644
index 000000000..ad1ed3521
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ArtifactValues.java
@@ -0,0 +1,269 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package ResultsUI;
+
+import static ResultsUI.ParamReferenceStorage.FieldType_ITEMS;
+import static ResultsUI.ParamReferenceStorage.LineType_ITEMS;
+import static ResultsUI.ParamReferenceStorage.SpecialTimeStampType;
+import static ResultsUI.ParamReferenceStorage.TimestampType_ITEMS;
+import static ResultsUI.ParamReferenceStorage.justFieldType;
+import static ResultsUI.ParamReferenceStorage.lineParamAccessible;
+
+/**
+ *
+ * @author Dan
+ */
+
+/*
+Errors that need to be fixed/Notes to consider:
+****The param parsing in this class is critically dependent to where the param value's corresponding index is on the artifact line.
+ If at any point this alignment is modified with less or more params, this code will need to be revised
+
+****If the Line ID or the Field ID input contains a " : " in it, then the code will add everything after the " : " to the "line ID, or field ID".
+ For the Field ID, it adds all the " : " parsed values after the field type, until it hits a Line Type(excludes the line type value)
+
+****Currently this code will allow/read weird inputs like "CONTAINS : LINE : STUFF" in field ID or Line ID (which breaks the parsing)
+*/
+public class ArtifactValues {
+ //Values to be obtained
+ String resultTag, container, fileID, fieldID, lineID, timeStampDelimiter;
+
+ ToolTipHandlers.ToolTipWrapper fieldType, lineType, timeStampType;
+
+ //Stores the values of an arifactline fed into it (NO real value validation happening here)
+ ArtifactValues(String artifactLine){
+ resultTag = container = fileID = fieldID = lineID = timeStampDelimiter = "";
+
+ fieldType = lineType = timeStampType = null;
+
+ //Parsing the artifactline
+ String[] paramParsedLine = artifactLine.split(" : ");
+
+ //Get the resultTag
+ resultTag = paramParsedLine[0].split(" = ")[0];
+
+ //Get the container, fieldID, timeStampType, and timeStampDelimiter
+ handleFileRef(paramParsedLine[0].split(" = ")[1]);
+
+ //Get Field Type and Field ID (and the lineType and lineID depending on if the field type allows it):
+
+ //Case where "TOKEN" field Type is not explicitly stated and the paramParsedLine index is off by 1 for fieldID, lineType, lineID
+ if(paramParsedLine[1].equals("ALL") || paramParsedLine[1].equals("LAST") || isInteger(paramParsedLine[1])){
+ fieldType = FieldType_ITEMS[0]; //TOKEN
+ fieldID = paramParsedLine[1];
+
+ /*
+ If the paramParsedLine isn't just the fileID and the fieldID (note fieldType is assumed to be "Token"),
+ then that means we need to consider the other parms which are certainly* line type and line ID.
+ *if the user enters a bad config file this may cause an error.
+ */
+ if(paramParsedLine.length > 2){
+ lineType = itemFinder(LineType_ITEMS, paramParsedLine[2]);
+ lineID = paramParsedLine[3];
+ }
+ else{
+ lineType = LineType_ITEMS[0]; //NONE
+ lineID ="";
+ }
+ }
+
+ //Case where the field type IS EXPLICITY stated
+ else{
+ fieldType = itemFinder(FieldType_ITEMS, paramParsedLine[1]);
+ //If the field type is null after looking through the field type items, then it may be under the SpecialTimeStampType array
+ if(fieldType == null)
+ fieldType = itemFinder(SpecialTimeStampType, paramParsedLine[1]);
+
+ //Does the field type consider other fields, if so then continue parsing for these values
+ if(!justFieldType.contains(fieldType.getItem())){
+ //If the field Type doesn't bother with line Params then execute these details
+ if(!lineParamAccessible.contains(fieldType.getItem())){
+ //Everything after the field type is considered the field ID (this ensures that the fieldID potentially split by " : " will all be captured and stored)
+ fieldID = artifactLine.split(fieldType + " : ")[1];
+
+ //If the fieldType is equal "FILE_REGEX_TS", then overwrite the fieldType to be "FILE_REGEX" and make the timeStampType to be "LOG_TS"
+ //If the fieldType is equal "LOG_TS", then overwrite the fieldType to be "CONTAINS" and make the timeStampType to be "LOG_TS"
+ //If the fieldType is equal "LOG_RANGE", then overwrite the fieldType to be "CONTAINS" and make the timeStampType to be "LOG_RANGE"
+ switch (fieldType.getItem()) {
+ case "FILE_REGEX_TS":
+ fieldType = FieldType_ITEMS[7]; //FILE REGEX
+ timeStampType = SpecialTimeStampType[0]; //LOG_TS
+ break;
+ case "LOG_TS":
+ fieldType = FieldType_ITEMS[6]; //CONTAINS
+ timeStampType = SpecialTimeStampType[0]; // LOG_TS
+ break;
+ case "LOG_RANGE":
+ fieldType = FieldType_ITEMS[6]; //CONTAINS
+ timeStampType = SpecialTimeStampType[1]; //LOG_RANGE
+ break;
+ default:
+ break;
+ }
+
+ lineType = LineType_ITEMS[0]; //NONE
+ lineID = "";
+ }
+ //If the field Type does bother with line Params then execute these details
+ else{
+ int properLineTypeIndex = 3; //This value may be changed if user's field ID includes " : ", offsetting the parsing indexes
+
+ /*The Field ID may include " : ". But since the line parsing breaks the line up based on " : ",
+ the for block below makes sure to the include the pieces that were broken up
+ */
+ for(int i=2; i.[stdin | stdout | prgout] or file_path
+ if(!fileRef.contains(":")){
+ container = "ALL";
+ fileID = fileRef;
+ timeStampType = TimestampType_ITEMS[0]; //File
+ }
+ //Case 2: [container_name:].[stdin | stdout | prguot]
+ else if(fileRef.contains(":") && !fileRef.contains("/")){
+ container = fileRef.split(":")[0];
+ fileID = fileRef.split(":")[1];
+ timeStampType = TimestampType_ITEMS[0]; //File
+ }
+ else{
+ String[] parsedFileRef = fileRef.split(":");
+
+ if(parsedFileRef.length == 2){
+ //Case 3: [container_name:]file_path
+ if(fileRef.indexOf(":") < fileRef.indexOf('/')){
+ container = parsedFileRef[0];
+ fileID = parsedFileRef[1];
+ timeStampType = TimestampType_ITEMS[0]; //File
+ }
+ //Case 4: file_path[:time_delimiter]
+ else{
+ fileID = parsedFileRef[0];
+ //Set the timeStamp Type either to be "Service" or "Program"
+ if(parsedFileRef[1].contains(".service")){
+ timeStampType = TimestampType_ITEMS[1]; //Service
+ timeStampDelimiter = parsedFileRef[1].replace(".service", "");
+ }
+ else{
+ timeStampType = TimestampType_ITEMS[2]; //Program
+ timeStampDelimiter = parsedFileRef[1];
+ }
+ }
+ }
+ //Case 5: [container_name:]file_path[:time_delimiter]
+ else {
+ container = parsedFileRef[0];
+ fileID = parsedFileRef[1];
+ if(parsedFileRef[2].contains(".service")){
+ timeStampType = TimestampType_ITEMS[1]; //Serivce
+ timeStampDelimiter = parsedFileRef[2].replace(".service", "");
+ }
+ else{
+ timeStampType = TimestampType_ITEMS[2]; //Program
+ timeStampDelimiter = parsedFileRef[2];
+ }
+ }
+ }
+ }
+
+ private ToolTipHandlers.ToolTipWrapper itemFinder(ToolTipHandlers.ToolTipWrapper[] list,String desired){
+ for(ToolTipHandlers.ToolTipWrapper item : list){
+ if(item.getItem().equals(desired)){
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private boolean itemExistCheck(ToolTipHandlers.ToolTipWrapper[] list,String desired){
+ for(ToolTipHandlers.ToolTipWrapper item : list){
+ if(item.getItem().equals(desired)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isInteger(String s){
+ try{
+ Integer.parseInt(s);
+
+ return true;
+ }
+ catch(NumberFormatException ex){
+ return false;
+ }
+ }
+
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ParamReferenceStorage.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ParamReferenceStorage.java
new file mode 100644
index 000000000..5fe6a6281
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ParamReferenceStorage.java
@@ -0,0 +1,144 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package ResultsUI;
+
+import ResultsUI.ToolTipHandlers.ToolTipWrapper;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author Dan
+ */
+public class ParamReferenceStorage {
+
+ public static final ToolTipWrapper[] FieldType_ITEMS = new ToolTipWrapper[] {
+ //0
+ new ToolTipWrapper("TOKEN", "Treat the line as space-delimited tokens."),
+ // 1
+ new ToolTipWrapper("PARENS", "The desired value is contained in parenthesis."),
+ // 2
+ new ToolTipWrapper("QUOTES", "The desired value is contained in quotes."),
+ // 3
+ new ToolTipWrapper("SLASH", "The desired value is contained within slashes " +
+ "e.g., /foo/"),
+ // 4
+ new ToolTipWrapper("LINE_COUNT", "The quantity of lines in the file. Remaining fields " +
+ "are ignored."),
+ // 5
+ new ToolTipWrapper("CHECKSUM", "The result value is set to the md5 checksum " +
+ "of the file."),
+ // 6
+ new ToolTipWrapper("CONTAINS", "The result value is set to TRUE if the file " +
+ "contains the string represented in field_id."),
+ // 7
+ new ToolTipWrapper("FILE_REGEX", "The result value is set to TRUE if the file " +
+ "contains the regular expression represented in field_id. " +
+ "The python findall function is used on the entire file. " +
+ "See the acl lab for an example of multi-line expressions."),
+ // 8
+ new ToolTipWrapper("STRING_COUNT", "The result value is set to the quantity of " +
+ "occurances of the string represented in field_id."),
+ // 9
+ new ToolTipWrapper("COMMAND_COUNT", "Intended for use with bash_history files, counts " +
+ "the occurances of the command given in the field_id. "),
+ // 10
+ new ToolTipWrapper("PARAM", "The result value is set to nth parameter " +
+ "(0 is the program name), provided in the " +
+ "program invocation."),
+ // 11
+ new ToolTipWrapper("SEARCH", "The result is assigned the value of the search " +
+ "defined by the given field_id, which is treated as an " +
+ "expression having the syntax of pythons parse.search " +
+ "function. E.g., \"frame.number=={:d}\" would " +
+ "yield the frame number."),
+ // 12
+ new ToolTipWrapper("GROUP", "Intended for use with \"REGEX\" line types, the " +
+ "result is set to the value of the regex group " +
+ "number named by the field_id. Regular expressions " +
+ "and their groups are processed using the python " +
+ "re.search semantics." ),
+ // 13
+ new ToolTipWrapper("TIME_DELIM", "" )};
+
+
+ public static final ToolTipWrapper[] LineType_ITEMS = new ToolTipWrapper[] {
+ // 0
+ new ToolTipWrapper("NONE", ""),
+ // 1
+ new ToolTipWrapper("LINE", "The line_id is an integer line number " +
+ "(starting at one). Use of this to identify " +
+ "lines is discouraged since minor lab changes " +
+ "might alter the count."),
+ // 2
+ new ToolTipWrapper("STARTSWITH", "the line_id is a string. This names the " +
+ "first occurrence of a line that starts with " +
+ "this string." ),
+ // 3
+ new ToolTipWrapper("HAVESTRING", "The line_id is a string. This names the " +
+ "first occurrence of a line that contains the " +
+ "string." ),
+ // 4
+ new ToolTipWrapper("REGEX", "The line_id is a regular expression. This names the " +
+ "first occurrence of a line that matches the regular " +
+ "expression. Also see the \"GROUP\" field_type." ),
+ // 5
+ new ToolTipWrapper("NEXT_STARTSWITH", "the line_id is a string. This names the " +
+ "line preceeding the first occurrence of a line " +
+ "that starts with this string.")};
+
+
+ public static final ToolTipWrapper[] TimestampType_ITEMS = new ToolTipWrapper[] {
+ // 0
+ new ToolTipWrapper("File", ""),
+ // 1
+ new ToolTipWrapper("Service", ""),
+ // 2
+ new ToolTipWrapper("Program", "")} ;
+
+
+ //****These items may need to be stored differently for better organization)
+ public static final ToolTipWrapper[] SpecialTimeStampType = new ToolTipWrapper[] {
+ //FIELDTYPES
+ // 0
+ new ToolTipWrapper("LOG_TS", "Used with timestamped log files, this results in a " +
+ "timestamped set of boolean results with a value " +
+ "of TRUE for each log line that contains the string " +
+ "represented in the field_id."),
+ // 1
+ new ToolTipWrapper("LOG_RANGE", "Similar to LOG_TS, except the timestamped entries " +
+ "are ranges delimited by the matching log entries."),
+ // 2 ***These items below do not appear in the comboboxes, they're here merely for reference
+ new ToolTipWrapper("FILE_REGEX_TS", ""),
+ //LINETYPES
+ new ToolTipWrapper("HAVESTRING_TS", ""),
+
+ new ToolTipWrapper("REGEX_TS", "")};
+
+
+ public static final Set LOG_ACCESIBLE_FieldType = new HashSet(Arrays.asList(
+ new String[] {"CONTAINS", "FILE_REGEX", "SEARCH"}
+ ));
+
+ public static final Set LOG_TS_ACCESSIBLE_LineType = new HashSet(Arrays.asList(
+ new String[] {"HAVESTRING", "REGEX"}
+ ));
+
+ public static final Set lineParamAccessible = new HashSet(Arrays.asList(
+ new String[] {"TOKEN", "PARENS", "QUOTES", "SLASH", "GROUP", "SEARCH"}
+ ));
+
+
+ public static final Set justFieldType = new HashSet(Arrays.asList(
+ new String[] {"LINE_COUNT", "CHECKSUM", "TIME_DELIM"}
+ ));
+
+
+ public static final Set timeStampDelimiterAccessible = new HashSet(Arrays.asList(
+ new String[] {"Service", "Program"}
+ ));
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsData.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsData.java
new file mode 100644
index 000000000..5e0a325a2
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsData.java
@@ -0,0 +1,745 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package ResultsUI;
+
+import static ResultsUI.ParamReferenceStorage.justFieldType;
+import static ResultsUI.ParamReferenceStorage.lineParamAccessible;
+import static ResultsUI.ParamReferenceStorage.timeStampDelimiterAccessible;
+import ResultsUI.ToolTipHandlers.ToolTipWrapper;
+import java.awt.Component;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+/**
+ *
+ * @author Dan
+ */
+public class ResultsData {
+ List listofArtifacts;
+ ArrayList containerList;
+ boolean labloaded;
+ String labname;
+ int rowCount;
+
+ ResultsData(){
+ listofArtifacts = new ArrayList<>();
+ containerList = new ArrayList<>();
+ labloaded = false;
+ labname = "";
+ rowCount = 0;
+ }
+
+ ResultsData(String labname){
+ listofArtifacts = new ArrayList<>();
+ containerList = new ArrayList<>();
+ labloaded = false;
+ this.labname = labname;
+ rowCount = 0;
+
+ getData();
+ }
+
+//LOADING~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ //Checks if the lab exists and will get lab's result config data if it does
+ private void getData(){
+ //Check if the Folder exists
+ String userHomeFolder = System.getProperty("user.home");
+ File lab = new File(userHomeFolder + File.separator + "labtainer" + File.separator + "trunk" + File.separator + "labs" + File.separator+ labname);
+
+ if(lab.isDirectory()){
+ if(getContainers(lab) && getArtifacts())
+ labloaded = true;
+ }
+ else
+ System.out.println("Lab does not exist!");
+ }
+
+ //Updates the containerlist (all artifct panels refer to this list to fill in the container combobox)
+ private boolean getContainers(File lab){
+ File startConfig = new File(lab+"/config/start.config");
+
+ try {
+ if(startConfig.exists()){
+ try (FileReader fileReader = new FileReader(startConfig)) {
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ String line = bufferedReader.readLine();
+ while (line != null) {
+ if(line.startsWith("CONTAINER")){
+ containerList.add(line.split("\\s+")[1]);
+ }
+ line = bufferedReader.readLine();
+ }
+ }
+
+ //Every list of containers should include "ALL" to signify when the container_name is not specified in the file ID
+ if(containerList.size() > 1)
+ containerList.add("ALL");
+
+ return true;
+ }
+ else{
+ System.out.println("start.config is missing");
+ return false;
+ }
+ }
+ catch (FileNotFoundException ex) {
+ Logger.getLogger(ResultsUI.class.getName()).log(Level.SEVERE, null, ex);
+ System.out.println("Issue with getting containers");
+ return false;
+ } catch (IOException ex) {
+ Logger.getLogger(ResultsUI.class.getName()).log(Level.SEVERE, null, ex);
+ System.out.println("Issue with getting containers");
+ return false;
+ }
+
+ }
+
+ //Parses the results.config to obtain all the relevant artifact lines,
+ //extracts the values of each artifact line
+ //and then loads each artifact line's value into the list of Artifacts
+ private boolean getArtifacts(){
+ ArrayList artifacts = getArtifactLines();
+
+ if(artifacts != null){
+ //Fill the list of artifacts
+ for(String artifactLine : artifacts){
+ ArtifactValues values = new ArtifactValues(artifactLine);
+ listofArtifacts.add(values);
+ rowCount++;
+ }
+ return true;
+ }
+ else
+ return false;
+
+ }
+
+
+//WRITING~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ //Update the results.config file with the user's input
+ protected void writeResultsConfig(JPanel PanelofArtifacts){
+ try {
+ updateListofArtifacts(PanelofArtifacts);
+ String resultTag,
+ container,
+ file,
+ fieldType,
+ fieldID,
+ lineType,
+ lineID,
+ timeStampType,
+ timeStampDelimiter;
+ String resultsConfigText = "";
+
+ ErrorHandler error = new ErrorHandler();
+ ArrayList resultTagList = new ArrayList<>(); //Used for duplication checking
+
+
+ //Iterate through each artifact
+ for(int i=0;i < listofArtifacts.size();i++){
+ error.checkReset(); //Reset the error statuses for a new artifact line
+
+ String artifactConfigLine = "";
+
+ //RESULTS TAG
+ resultTag = listofArtifacts.get(i).resultTag;
+ resultTagList.add(resultTag);
+
+ //Checks if resultTag is valid or inputted
+ if(resultTag.matches("^[a-zA-Z0-9_]+$"))
+ artifactConfigLine += (resultTag + " = "); //add to artifact Config line
+ else if(resultTag.isEmpty() || resultTag.equals(""))
+ error.resultTagMissing = true;
+ else
+ error.resultError = true;
+
+ //FILEID CONFIG
+ file = listofArtifacts.get(i).fileID;
+ container = listofArtifacts.get(i).container;
+ ToolTipWrapper timeStampTypeTTW = listofArtifacts.get(i).timeStampType;
+ timeStampType = timeStampTypeTTW.getItem();
+ timeStampDelimiter = listofArtifacts.get(i).timeStampDelimiter;
+
+ if(file.isEmpty() || file.equals("")){
+ error.fileIDMissing = true;
+ }
+ //Checks if non-file-path file input has .stdin | .stdout | .prgout dottag
+ //Note: most OS, but Windows use backslashes as a File seperator
+ else if(!file.contains("/")){
+ if(!file.contains("."))
+ error.fileError = true;
+ else{
+ String dotTag = file.substring(file.indexOf("."),file.length());
+ if(!(dotTag.equals(".stdin") || dotTag.equals(".stdout") || dotTag.equals(".prgout")))
+ error.fileError = true;
+ }
+ }
+
+ //CONTAINER (if a specific container is selected)
+ if(containerList.size() > 1 && !container.equals("ALL")){
+ artifactConfigLine += (container);
+ artifactConfigLine += ":";
+ }
+
+ //TIMESTAMP DELIMITER (if Serivce or Program was selected in the Timestamp combobox)
+ if(timeStampDelimiterAccessible.contains(timeStampType)){
+ //Checks if the file is a file path when a user inputs a time delimiter
+ if(file.contains("/") && !(timeStampDelimiter.isEmpty() || timeStampDelimiter.equals(""))){
+ artifactConfigLine += (file+ ":" + timeStampDelimiter);
+
+ if((timeStampType).equals("Service"))
+ artifactConfigLine += ".service";
+ }
+ else{
+ if(!file.contains("/"))
+ error.timeDelimiterError = true;
+ else
+ error.timeDelimiterMissing = true;
+ }
+ }
+ else
+ artifactConfigLine += file; //could be a .[stdin | stdout | prgout], file_path
+
+
+ //FIELD TYPE
+ /*
+ If the timeStampType is "LOG_TS" and the fieldType is "CONTAINS", then the fieldType will be "LOG_TS"
+ If the timeStampType is "LOG_TS" and the fieldType is "FILE_REGEX", then the fieldType will be "FILE_REGEX_TS"
+ If the timeStampType is "LOG_RANGE" and the fieldType is "CONTAINS", then the fieldType will be "LOG_RANGE"
+ */
+ ToolTipWrapper fieldTypeTTW = listofArtifacts.get(i).fieldType;
+ fieldType = fieldTypeTTW.getItem();
+
+ if(timeStampType.equals("LOG_TS")){
+ if(fieldType.equals("CONTAINS"))
+ fieldType = "LOG_TS";
+ else if(fieldType.equals("FILE_REGEX"))
+ fieldType = "FILE_REGEX_TS";
+ }
+ if(timeStampType.equals("LOG_RANGE")){
+ if(fieldType.equals("CONTAINS"))
+ fieldType = "LOG_RANGE";
+ }
+ artifactConfigLine += (" : " + fieldType);
+
+ //FIELD ID
+ //if field type is "LINE_COUNT or CHECKSUM" then don't look into the Field TYPE and Line ID and Line Type
+ if(!justFieldType.contains(fieldType)){
+ fieldID = listofArtifacts.get(i).fieldID;
+
+ //If the field type is TOKEN, check if the field ID is a number 1-9 or ALL or LAST
+ if(fieldType.equals("TOKEN") && (fieldID.equals("0") || !(fieldID.matches("^[0-9]+$") || fieldID.equals("ALL") || fieldID.equals("LAST"))))
+ error.fieldTypeTokenError = true;
+
+ //If the field type is PARAM, check if the value is a postive number or zero
+ else if(fieldType.equals("PARAM") && !(fieldID.matches("^[0-9]+$")))
+ error.fieldTypeParamError = true;
+
+ //Check if the user didn't inputted anthing in the Field ID
+ else if(fieldID.isEmpty() || fieldID.equals(""))
+ error.fieldIDMissing = true;
+
+ //If all is good with the above checks, then concatenate the fieldID to the artifactLine
+ else
+ artifactConfigLine += (" : " + fieldID);
+
+ //LINE_TYPE and LINE ID
+ //Is LineType and Line ID relevant based on field type? if so, then...
+ if(lineParamAccessible.contains(fieldType)){
+ ToolTipWrapper lineTypeTTW = listofArtifacts.get(i).lineType;
+ lineType = lineTypeTTW.getItem();
+ lineID = listofArtifacts.get(i).lineID;
+
+ if(!lineType.equals("NONE")){
+ //Check if there is a line ID input if the user has a line type
+ if(lineID.isEmpty() || lineID.equals(""))
+ error.lineIDMissing = true;
+ else if(lineType.equals("LINE") && (lineID.equals("0") || !(lineID.matches("^[0-9]+$")))){
+ error.lineIDError = true;
+ }
+ else if(timeStampType.equals("LOG_TS") && lineType.equals("HAVESTRING"))
+ artifactConfigLine += (" : " + "HAVESTRING_TS" + " : " + lineID);
+ else if(timeStampType.equals("LOG_TS") && lineType.equals("REGEX"))
+ artifactConfigLine += (" : " + "REGEX_TS" + " : " + lineID);
+ else
+ artifactConfigLine += (" : " + lineType + " : " + lineID);
+ }
+ }
+ }
+
+ //If there's no error, put the artifactConfigLine in the resultsConfigText string,
+ //Otherwise the overallPass of the user input is false
+ if(error.userInputCheck(i+1)){
+ if(i < listofArtifacts.size()-1)
+ artifactConfigLine+= System.lineSeparator();
+ //Add the artifact config line to the Results Config text
+ resultsConfigText += artifactConfigLine;
+ }
+ else
+ error.fail();
+ }
+
+ //Check for duplicate result tags
+ error.checkDuplicateResultTags(resultTagList);
+ /*
+ for(String rt : resultTagList)
+ System.out.println(rt);
+ */
+
+ if(error.passStatus()){
+ //Resets the results.config file
+ File resultsConfigFile = initializeResultConfig();
+
+ try ( //Write the resultsConfigText to the results.config
+ BufferedWriter writer = new BufferedWriter(new FileWriter(resultsConfigFile, true))) {
+ writer.write(resultsConfigText);
+ }
+ }
+ else
+ JOptionPane.showMessageDialog(null, error.toString(), "INPUT ERROR", JOptionPane.ERROR_MESSAGE);
+ }
+ catch (IOException ex) {
+ Logger.getLogger(ResultsUI.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ //Checks if the results.config file exists and prepares the result.config file for the lab
+ private File initializeResultConfig() throws IOException{
+ //Get the filepath for the lab's results.config
+ String userHomeFolder = System.getProperty("user.home");
+ File resultsConfigFile = new File(userHomeFolder + File.separator + "labtainer" + File.separator + "trunk" + File.separator + "labs" + File.separator + labname + File.separator + "instr_config" + File.separator + "results.config");
+
+ //May not be necessary, subject to remove the base text, perhaps there is an option for the user to add their own comments
+ String baseText =
+ "# results.config" + System.lineSeparator()
+ + "#" + System.lineSeparator()
+ + "# Please see the Labtainer Lab Designer User Guide" + System.lineSeparator();
+
+ if(resultsConfigFile.exists()){
+ //Overwrite results.config file if it already exists
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultsConfigFile, false))) {
+ writer.write(baseText);
+ }
+ return resultsConfigFile;
+ }
+ else if(resultsConfigFile.createNewFile()){
+ //Create new results.config file otherwise(if it does not already exist)
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultsConfigFile))) {
+ writer.write(baseText);
+ }
+ return resultsConfigFile;
+ }
+ else{ //File could not be created so return error message
+ System.out.println("Results Config File couldn't be initialzed.");
+ return null;
+ }
+ }
+
+ //Handles all the error data and error checking before writing the results.config
+ private class ErrorHandler{
+ private boolean overallPass;
+ private String errorMsg;
+ private boolean
+ resultError,
+ fileError,
+ timeDelimiterError,
+ fieldTypeTokenError,
+ fieldTypeParamError,
+ lineIDError,
+
+ resultTagMissing,
+ fileIDMissing,
+ timeDelimiterMissing,
+ fieldIDMissing,
+ lineIDMissing;
+
+
+ ErrorHandler(){
+ overallPass = true;
+ errorMsg = "";
+ checkReset();
+ }
+
+ void fail(){
+ overallPass = false;
+ }
+
+ //Resets the error status(used right before looking at new artifact line)
+ private void checkReset(){
+ resultError = false;
+ fileError = false;
+ timeDelimiterError = false;
+ fieldTypeTokenError = false;
+ fieldTypeParamError = false;
+ lineIDError = false;
+
+ resultTagMissing = false;
+ fileIDMissing = false;
+ timeDelimiterMissing = false;
+ fieldIDMissing = false;
+ lineIDMissing = false;
+
+ }
+
+ //Builds error message detailing the errors that appear in the user input
+ boolean userInputCheck(int artifactIndex){
+ boolean rowPassed = true;
+ String infoMsg = "Artifact Line: " + artifactIndex + System.lineSeparator();
+
+ if(resultTagMissing){
+ rowPassed = false;
+ infoMsg+= "-Result Tag input is missing." + System.lineSeparator();
+ }
+ if(fileIDMissing){
+ rowPassed = false;
+ infoMsg+= "-File ID input is missing." + System.lineSeparator();
+ }
+ if(timeDelimiterMissing){
+ rowPassed = false;
+ infoMsg+= "-Time Delimiter input is missing." + System.lineSeparator();
+ }
+ if(fieldIDMissing){
+ rowPassed = false;
+ infoMsg+= "-Field ID input is missing." + System.lineSeparator();
+ }
+ if(lineIDMissing){
+ rowPassed = false;
+ infoMsg+= "-Line ID input is missing)." + System.lineSeparator();
+ }
+ if(resultError){
+ rowPassed = false;
+ infoMsg+= "-Make sure your Results Tag has only alphanumeric characters or underscores." + System.lineSeparator();
+ }
+ if(fileError){
+ rowPassed = false;
+ infoMsg+= "-Make sure your File ID file's extentsion ends in \".stdin\", \".stdout\", or \".prgout\"." + System.lineSeparator() + " Or is a file path." + System.lineSeparator();
+ }
+ if(timeDelimiterError){
+ rowPassed = false;
+ infoMsg+= "-Timestamp Delimiter Option is only available if your File ID is a file path." + System.lineSeparator();
+ }
+ if(fieldTypeTokenError){
+ rowPassed = false;
+ infoMsg+= "-If your Field Type is TOKEN then make sure your Field ID is a positve number(zero exclusive), \"ALL\", or \"LAST\"." + System.lineSeparator();
+ }
+ if(fieldTypeParamError){
+ rowPassed = false;
+ infoMsg+= "-If your Field Type is PARAM then make sure your Field ID is a positve number(zero inclusive)." + System.lineSeparator();
+ }
+ if(lineIDError){
+ rowPassed = false;
+ infoMsg+= "-If your Line Type is LINE then make sure your Line ID is a positve number(zero exclusive)." + System.lineSeparator();
+ }
+
+
+ if(!rowPassed)
+ errorMsg += (infoMsg + System.lineSeparator());
+
+ return rowPassed;
+ }
+
+ //Check for duplicate results Taga
+ void checkDuplicateResultTags(ArrayList resultTags){
+ ArrayList markedResultTags = new ArrayList<>();
+
+ //Store all the indices for each unique result tag
+ for(int i=0;i 1){
+ duplicateErrorMsg+= "Duplicate Result Tag: \"" + rt.resultTag + "\" on rows ";
+
+ for(int i=0;i indices;
+
+ ResultTagIndices(String resultTag, int index){
+ this.resultTag = resultTag;
+ indices = new ArrayList<>();
+ indices.add(index);
+ }
+
+ void addIndex(int index){
+ indices.add(index);
+ }
+ }
+
+ //Is the result tag already in the duplicate list?
+ boolean isDuplicate(ArrayList markedResultTags, String resultTag){
+ for(ResultTagIndices rtIndices : markedResultTags){
+ if(rtIndices.resultTag.equals(resultTag))
+ return true;
+ }
+ return false;
+ }
+
+ //Get the duplicate object based on the duplicate string
+ ResultTagIndices getDuplicate(ArrayList markedResultTags, String resultTag){
+ for(ResultTagIndices rtIndices : markedResultTags){
+ if(rtIndices.resultTag.equals(resultTag))
+ return rtIndices;
+ }
+ return null;
+ }
+
+
+ @Override
+ public String toString(){
+ return errorMsg;
+ }
+
+ boolean passStatus(){
+ return overallPass;
+ }
+ }
+
+
+//GENERAL~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ //Gets the artifact lines in the goals.config
+ protected ArrayList getArtifactLines(){
+ ArrayList artifacts = new ArrayList<>();
+
+ try {
+ String userHomeFolder = System.getProperty("user.home");
+ File lab = new File(userHomeFolder + File.separator + "labtainer" + File.separator + "trunk" + File.separator + "labs" + File.separator+ labname);
+ File resultsConfig = new File(lab+"/instr_config/results.config");
+
+ //Get the artifact lines
+ if(resultsConfig.exists()){
+ try (FileReader fileReader = new FileReader(resultsConfig)) {
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+ String line = bufferedReader.readLine();
+
+ while (line != null) {
+ //just checks if the first character is: not empty, not a hash, and not whitspace)
+ if(!line.isEmpty() && line.charAt(0) != '#' && !Character.isWhitespace(line.charAt(0)))
+ artifacts.add(line);
+
+ line = bufferedReader.readLine();
+ }
+ }
+ return artifacts;
+ }
+ else{
+ System.out.println("No results.config file in the loaded lab!");
+ return null;
+ }
+ }
+ catch (IOException e) {
+ System.out.println("Issue with getting result.config artifacts");
+ return null;
+ }
+ }
+
+ //Updates the list of artifacts
+ protected void updateListofArtifacts(JPanel PanelofArtifacts){
+ Component[] artifacts = PanelofArtifacts.getComponents(); //Access the list of artifacts
+
+ List listofArtifactsTMP = new ArrayList<>();
+
+ //Iterate through each artifact and add it to the temp list of artifact values
+ for (Component artifact : artifacts) {
+ //RESULTS TAG
+ String resultTag = ((ArtifactPanels) artifact).getTagTextField().getText();
+ //FILEID CONFIG
+ String file = ((ArtifactPanels) artifact).getFileTextField().getText();
+ String container = (String) (((ArtifactPanels) artifact).getContainerComboBox().getSelectedItem());
+ ToolTipHandlers.ToolTipWrapper timeStampType = (ToolTipHandlers.ToolTipWrapper) (((ArtifactPanels) artifact).getTimeStampComboBox().getSelectedItem());
+ String timeStampDelimiter = ((ArtifactPanels) artifact).getTimeStampTextField().getText();
+ //FieldType
+ ToolTipHandlers.ToolTipWrapper fieldType = (ToolTipHandlers.ToolTipWrapper) (((ArtifactPanels) artifact).getFieldTypeComboBox().getSelectedItem());
+ String fieldID = ((ArtifactPanels) artifact).getFieldIDTextField().getText();
+ //LINE_TYPE and LINE ID
+ ToolTipHandlers.ToolTipWrapper lineType = (ToolTipHandlers.ToolTipWrapper) (((ArtifactPanels) artifact).getLineTypeComboBox().getSelectedItem());
+ String lineID = ((ArtifactPanels) artifact).getLineIDTextField().getText();
+
+ listofArtifactsTMP.add(new ArtifactValues(resultTag, container, file, fieldType, fieldID, lineType, lineID, timeStampType, timeStampDelimiter));
+ }
+
+ listofArtifacts = listofArtifactsTMP; //overwrite the old listofArtifacts with the temp listofArtifacts
+ }
+
+ //Swaps the position of artifacts in a list
+ protected void swapArtifacts(String type, int rowIndex){
+
+ switch(type){
+ case "UP":
+ if(rowIndex > 0){
+ //System.out.println("UP: "+listofArtifacts.get(rowIndex).resultTag+" Index: "+rowIndex);
+ Collections.swap(listofArtifacts, rowIndex, rowIndex-1);
+ }
+ break;
+ case "DOWN":
+ //System.out.println(rowCount);
+ //System.out.println("RowINdex: " + rowIndex + " RowCount-1: "+ (rowCount-1));
+ if(rowIndex < rowCount-1){
+ //System.out.println("DOWN: "+listofArtifacts.get(rowIndex).resultTag);
+ Collections.swap(listofArtifacts, rowIndex, rowIndex+1);
+ }
+ break;
+ default:
+ System.out.println("swap case no register");
+ }
+ }
+
+ //Gets a list of ArtifactValues from the the current state of the results.config file
+ protected List getArtifactValuesOfConfigFile(){
+ List officialListofArtifacts = new ArrayList<>();
+
+ ArrayList artifactLines = getArtifactLines();
+
+ if(artifactLines != null){
+
+ for(String artifactLine : artifactLines){
+ ArtifactValues values = new ArtifactValues(artifactLine);
+ officialListofArtifacts.add(values);
+ }
+ return officialListofArtifacts;
+ }
+ else
+ return null;
+ }
+
+ //Compares the data of two lists of ArtifactValues. If there is a difference then return 'true', 'false' otherwise
+ static boolean artifactValuesDiffer(List list1, List list2){
+ if(list1.size() != list2.size()){
+ return true;
+ }
+ else{
+ //This is a gross implemenation of comparing each individual value between two sets of Artifact Values (Maybe conisder implementing the ArtifactValues Class as a comparable)
+ for(int i=0;i list1, List list2) method
+ static private void printlistValues(List list1, List list2, int i){
+ System.out.println("Result Tag: ");
+ System.out.println("UI: "+list1.get(i).resultTag);
+ System.out.println("Config: "+list2.get(i).resultTag);
+ System.out.println();
+
+ System.out.println("File ID: ");
+ System.out.println("UI: "+list1.get(i).fileID);
+ System.out.println("Config: "+list2.get(i).fileID);
+ System.out.println();
+
+ System.out.println("Field Type: ");
+ System.out.println("UI: "+list1.get(i).fieldType);
+ System.out.println("Config: "+list2.get(i).fieldType);
+ System.out.println();
+
+ System.out.println("Field ID: ");
+ System.out.println("UI: "+list1.get(i).fieldID);
+ System.out.println("Config: "+list2.get(i).fieldID);
+ System.out.println();
+
+ System.out.println("Line Type: ");
+ System.out.println("UI: "+list1.get(i).lineType);
+ System.out.println("Config: "+list2.get(i).lineType);
+ System.out.println();
+
+ System.out.println("Line ID: ");
+ System.out.println("UI: "+list1.get(i).lineID);
+ System.out.println("Config: "+list2.get(i).lineID);
+ System.out.println();
+
+ System.out.println("TimeStamp Type: ");
+ System.out.println("UI: "+list1.get(i).timeStampType);
+ System.out.println("Config: "+list2.get(i).timeStampType);
+ System.out.println();
+
+ System.out.println("TimeStamp Delim: ");
+ System.out.println("UI: "+list1.get(i).timeStampDelimiter);
+ System.out.println("Config: "+list2.get(i).timeStampDelimiter);
+ System.out.println();
+
+ System.out.println("CONTAINER: ");
+ System.out.println("UI: "+list1.get(i).container);
+ System.out.println("Config: "+list2.get(i).container);
+ System.out.println();
+
+
+
+
+
+
+ }
+
+//GETTERS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ protected List getListofArtifacts(){
+ return listofArtifacts;
+ }
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsUI.form b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsUI.form
new file mode 100644
index 000000000..8fa23d5a7
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsUI.form
@@ -0,0 +1,210 @@
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsUI.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsUI.java
new file mode 100644
index 000000000..e121ba1e7
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ResultsUI.java
@@ -0,0 +1,355 @@
+package ResultsUI;
+
+
+import static ResultsUI.ResultsData.artifactValuesDiffer;
+import java.awt.Component;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ *
+ * @author Dan
+ */
+public class ResultsUI extends javax.swing.JFrame {
+ ResultsData dataUI;
+
+ public ResultsUI() {
+ initComponents();
+ LabNotExist.setVisible(false);
+
+ dataUI = new ResultsData();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ ScrollPaneOfArtifacts = new javax.swing.JScrollPane();
+ PanelofArtifacts = new javax.swing.JPanel();
+ UpdateButton = new javax.swing.JButton();
+ jLabel2 = new javax.swing.JLabel();
+ RemoveAllButton = new javax.swing.JButton();
+ jLabel9 = new javax.swing.JLabel();
+ CreateButton = new javax.swing.JButton();
+ jLabel3 = new javax.swing.JLabel();
+ jLabel5 = new javax.swing.JLabel();
+ jLabel1 = new javax.swing.JLabel();
+ LabNameTextField = new javax.swing.JTextField();
+ LabNotExist = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ setBackground(new java.awt.Color(255, 255, 255));
+ setMinimumSize(new java.awt.Dimension(1590, 500));
+ setPreferredSize(new java.awt.Dimension(1585, 389));
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ formWindowClosing(evt);
+ }
+ });
+
+ ScrollPaneOfArtifacts.setAutoscrolls(true);
+ ScrollPaneOfArtifacts.setMaximumSize(new java.awt.Dimension(1300, 800));
+
+ PanelofArtifacts.setLayout(new javax.swing.BoxLayout(PanelofArtifacts, javax.swing.BoxLayout.PAGE_AXIS));
+ ScrollPaneOfArtifacts.setViewportView(PanelofArtifacts);
+
+ UpdateButton.setText("Update");
+ UpdateButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ UpdateButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel2.setFont(new java.awt.Font("Arial", 1, 12)); // NOI18N
+ jLabel2.setText("Container");
+ jLabel2.setToolTipText("Identifies the container hosting the file. \nIf \"ALL\" is selected, then the file is across all the containers.");
+
+ RemoveAllButton.setFont(new java.awt.Font("Dialog", 1, 12)); // NOI18N
+ RemoveAllButton.setText("Remove All");
+ RemoveAllButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ RemoveAllButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel9.setFont(new java.awt.Font("Arial Black", 0, 12)); // NOI18N
+ jLabel9.setText("Lab Name: ");
+
+ CreateButton.setFont(new java.awt.Font("Dialog", 1, 12)); // NOI18N
+ CreateButton.setText("Create");
+ CreateButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ CreateButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel3.setFont(new java.awt.Font("Arial", 1, 12)); // NOI18N
+ jLabel3.setText("Field Type");
+ jLabel3.setToolTipText("The mode in which a value is found.");
+
+ jLabel5.setFont(new java.awt.Font("Arial", 1, 12)); // NOI18N
+ jLabel5.setText("File");
+ jLabel5.setToolTipText("File should either be a file path or a program/utility name with the \".stdin\", \".stdout\", or \".prgout\" extension.\n\n Ex. \"test.stdin\", \".local/result/sniff.txt\" ");
+
+ jLabel1.setFont(new java.awt.Font("Arial", 1, 12)); // NOI18N
+ jLabel1.setText("Result Tag");
+ jLabel1.setToolTipText("The symbolic name of the result, which will be referenced in the goals configuration file. \n\n(It must be alphanumeric, underscores permitted) ");
+
+ LabNameTextField.setPreferredSize(new java.awt.Dimension(6, 25));
+ LabNameTextField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ LabNameTextFieldActionPerformed(evt);
+ }
+ });
+
+ LabNotExist.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
+ LabNotExist.setText("Lab does not exist!");
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(CreateButton)
+ .addGap(10, 10, 10)
+ .addComponent(RemoveAllButton)
+ .addGap(98, 98, 98)
+ .addComponent(jLabel9)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(LabNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 378, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addComponent(LabNotExist)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 344, Short.MAX_VALUE)
+ .addComponent(UpdateButton))
+ .addComponent(ScrollPaneOfArtifacts, javax.swing.GroupLayout.DEFAULT_SIZE, 1300, Short.MAX_VALUE))
+ .addContainerGap())
+ .addGroup(layout.createSequentialGroup()
+ .addGap(60, 60, 60)
+ .addComponent(jLabel1)
+ .addGap(74, 74, 74)
+ .addComponent(jLabel2)
+ .addGap(66, 66, 66)
+ .addComponent(jLabel5)
+ .addGap(131, 131, 131)
+ .addComponent(jLabel3)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(CreateButton)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(RemoveAllButton)
+ .addComponent(jLabel9)
+ .addComponent(LabNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(UpdateButton)
+ .addComponent(LabNotExist)))
+ .addGap(14, 14, 14)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel1)
+ .addComponent(jLabel2)
+ .addComponent(jLabel5)
+ .addComponent(jLabel3))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ScrollPaneOfArtifacts, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void UpdateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_UpdateButtonActionPerformed
+ update();
+ }//GEN-LAST:event_UpdateButtonActionPerformed
+
+ private void update(){
+ if(dataUI.labloaded)
+ dataUI.writeResultsConfig(PanelofArtifacts);
+ }
+
+ private void LabNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_LabNameTextFieldActionPerformed
+ loadLab();
+ }//GEN-LAST:event_LabNameTextFieldActionPerformed
+
+ //Checks if the lab exists and will load lab's result config if it does
+ private void loadLab(){
+ dataUI = new ResultsData(getLabName());
+ //System.out.println("RowCount(Load): " + dataUI.rowCount);
+
+ if(dataUI.labloaded){
+ LabNotExist.setVisible(false);
+ artifactsPanelRedraw();
+ }
+ else
+ LabNotExist.setVisible(true);
+ }
+
+ private void CreateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CreateButtonActionPerformed
+ createFreshArtifact();
+ }//GEN-LAST:event_CreateButtonActionPerformed
+
+ //Creates and loads a new artifact row
+ private void createFreshArtifact(){
+ if(dataUI.labloaded){
+ dataUI.rowCount++;
+ ArtifactPanels newArtifact = new ArtifactPanels(this, dataUI.containerList, dataUI.rowCount);
+ PanelofArtifacts.add(newArtifact);
+ PanelofArtifacts.revalidate();
+ PanelofArtifacts.repaint();
+ }
+ }
+
+ private void RemoveAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RemoveAllButtonActionPerformed
+ removeAllButton();
+ }//GEN-LAST:event_RemoveAllButtonActionPerformed
+
+ private void removeAllButton(){
+ if(dataUI.labloaded){
+ if(JOptionPane.showConfirmDialog(null, "Are you sure you want to remove all?") == JOptionPane.YES_OPTION){
+ removeAllArtifacts();
+ dataUI.rowCount = 0;
+
+ }
+ }
+ }
+
+ private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
+ checkUnsavedChangesMade();
+ }//GEN-LAST:event_formWindowClosing
+
+ //Check if the the current state of the UI matches with what's saved in the goals.config
+ void checkUnsavedChangesMade(){
+ if(dataUI.labloaded){
+ dataUI.updateListofArtifacts(PanelofArtifacts);
+
+ if(artifactValuesDiffer(dataUI.listofArtifacts, dataUI.getArtifactValuesOfConfigFile())){
+ int confirmed = JOptionPane.showConfirmDialog(null,
+ "There are Unsaved Changes. Are you sure you want to exit the program?", "Unsaved Changes",
+ JOptionPane.YES_NO_OPTION);
+
+ if (confirmed == JOptionPane.YES_OPTION)
+ dispose();
+ else
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ }
+ else
+ dispose();
+ }
+ }
+
+//General Methods
+ //Updates the list of artifacts and redraws them on screen
+ void refresh(){
+ dataUI.updateListofArtifacts(PanelofArtifacts);
+ artifactsPanelRedraw();
+ }
+
+ //Redraws the artifacts Panel
+ void artifactsPanelRedraw(){
+ removeAllArtifacts();
+ //redraw the artifacts
+ for(int i=0; i < dataUI.listofArtifacts.size(); i++){
+ loadArtifact(dataUI.listofArtifacts.get(i), i+1);
+ }
+ }
+
+ //Removes all the artifact lines for the lab *note: this doesn't update results.config or the resultsData until the user hits the update button
+ private void removeAllArtifacts(){
+ Component[] componentList = PanelofArtifacts.getComponents();
+ for(Component c: componentList)
+ PanelofArtifacts.remove(c);
+
+ PanelofArtifacts.revalidate();
+ PanelofArtifacts.repaint();
+ }
+
+ //Load's the artifactlinePanel into GUI
+ private void loadArtifact(ArtifactValues artifactVal, int rowNum){
+ ArtifactPanels newArtifact = new ArtifactPanels(this, dataUI.containerList, rowNum,
+ artifactVal.resultTag,
+ artifactVal.container,
+ artifactVal.fileID,
+ artifactVal.fieldType,
+ artifactVal.fieldID,
+ artifactVal.lineType,
+ artifactVal.lineID,
+ artifactVal.timeStampType,
+ artifactVal.timeStampDelimiter);
+ PanelofArtifacts.add(newArtifact);
+ PanelofArtifacts.revalidate();
+ PanelofArtifacts.repaint();
+ }
+
+ //Gets the labname
+ private String getLabName(){
+ return LabNameTextField.getText();
+ }
+
+ //Gets the panel holding the artifacts
+ protected JPanel getPanelofArtifacts(){
+ return PanelofArtifacts;
+ }
+
+ public static void main(String args[]) {
+ /* Set the Nimbus look and feel */
+ //
+ /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ */
+ try {
+ for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ javax.swing.UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(ResultsUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ }
+ //
+ //
+ //
+ //
+
+ //
+
+ /* Create and display the form */
+ java.awt.EventQueue.invokeLater(() -> {
+ ResultsUI newResultsUI = new ResultsUI();
+ newResultsUI.setSize(1005, 1000);
+ newResultsUI.setVisible(true);
+ });
+ }
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton CreateButton;
+ private javax.swing.JTextField LabNameTextField;
+ private javax.swing.JLabel LabNotExist;
+ private javax.swing.JPanel PanelofArtifacts;
+ private javax.swing.JButton RemoveAllButton;
+ private javax.swing.JScrollPane ScrollPaneOfArtifacts;
+ private javax.swing.JButton UpdateButton;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel5;
+ private javax.swing.JLabel jLabel9;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ToolTipHandlers.java b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ToolTipHandlers.java
new file mode 100644
index 000000000..a7990d374
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/UI/Results/src/ResultsUI/ToolTipHandlers.java
@@ -0,0 +1,73 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package ResultsUI;
+
+import java.awt.Component;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JList;
+
+/**
+ *
+ * @author Dan
+ */
+public class ToolTipHandlers {
+ public static interface ToolTipProvider{
+ public String getToolTip();
+ }
+
+ //Stores an item and its correspoinding tool tip. (Items put into a combobox)
+ public static class ToolTipWrapper implements ToolTipProvider{
+ final String item;
+ final String toolTip;
+
+ public ToolTipWrapper(String item, String toolTip){
+ this.item = item;
+ this.toolTip = toolTip;
+ }
+
+ @Override
+ public String getToolTip(){
+ return toolTip;
+ }
+
+ @Override
+ public String toString(){
+ return item;
+ }
+
+ public String getItem(){
+ return item;
+ }
+ }
+
+ //custom combobox renderer to handle ToolTipWrapper objects that contain an string item and string tool tip
+ public static class ComboBoxRenderer extends DefaultListCellRenderer {
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ JComponent component = (JComponent) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ String tip = null;
+ if (value instanceof ToolTipProvider) {
+ ToolTipProvider ttp = (ToolTipProvider) value;
+ tip = ttp.getToolTip();
+ }
+ list.setToolTipText(tip);
+ return component;
+ }
+ }
+
+ //Sets the combo items with associated tool tips (called in the constructors)
+ public static void setComboItems(JComboBox combobox, ToolTipWrapper[] items){
+ ComboBoxRenderer renderer = new ComboBoxRenderer();
+ combobox.setRenderer(renderer);
+
+ for (ToolTipWrapper item : items) {
+ combobox.addItem(item);
+ }
+ }
+}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/config/labtainer.config b/modules/utilities/unix/labtainers/files/Labtainers-master/config/labtainer.config
new file mode 100644
index 000000000..0123f9535
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/config/labtainer.config
@@ -0,0 +1,40 @@
+# Filename : labtainer.config
+# Description:
+# This is a system wide configuration file
+#
+# WARNING: if you add relative paths to this file,
+# make sure that ParseLabtainerConfig.py converts them
+# to absolute paths.
+#
+GLOBAL_SETTINGS
+ # HOST_HOME_XFER - directory to transfer artifact to/from containers
+ # This directory will be set relative to the current user's home directory
+ # For example: if current user is joe and his home directory is /home/joe
+ # then the actual transfer directory is /home/joe/labtainer_xfer/
+ HOST_HOME_XFER labtainer_xfer/
+
+ # TESTSETS_ROOT - root directory for Regression Testing
+ # This directory is based on directory hierarchy (as checked out from svn)
+ # scripts that use is ran from ..../labtainer/trunk/scripts/labtainer-student/ or
+ # ..../labtainer/trunk/scripts/labtainer-instructor/
+ # Regression Testing directory is ..../labtainer/testsets/labs/
+ TESTSETS_ROOT ../../testsets/labs/
+
+ # WATERMARK_ROOT - root directory for Watermark Testing
+ # This directory is based on directory hierarchy (as checked out from svn)
+ # scripts that use is ran from ..../labtainer/trunk/scripts/labtainer-student/ or
+ # ..../labtainer/trunk/scripts/labtainer-instructor/
+ # Watermark Testing directory is ..../labtainer/testsets/watermark/
+ WATERMARK_ROOT ../../testsets/watermark/
+
+ # FILE_LOG_LEVEL and CONSOLE_LOG_LEVEL
+ # valid levels are: DEBUG, INFO, WARNING or ERROR
+ # specifies the log level to file and console respectively
+ # log to file logging.INFO and above
+ FILE_LOG_LEVEL DEBUG
+ # log to console logging.WARNING and above
+ CONSOLE_LOG_LEVEL WARNING
+ # An alternate apt/sources.list hostname. Default is archive.ubuntu.com
+ #APT_SOURCE mirror.picosecond.org
+ DEFAULT_REGISTRY mfthomps
+ TEST_REGISTRY testregistry:5000
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/check_tag.py b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/check_tag.py
new file mode 100755
index 000000000..84b8c9017
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/check_tag.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+import os
+import sys
+import argparse
+sys.path.append('../scripts/labtainer-student/bin')
+import InspectLocalReg
+import InspectRemoteReg
+import VersionInfo
+import labutils
+import subprocess
+import labutils
+'''
+Compare all labtainer image base labels with when would be expected based
+on the docker file. Fix the ones that are not consistent.
+'''
+
+def do_lab(lab_dir, lab, role, registry):
+ framework_version = labutils.framework_version
+ docker_dir = os.path.join(lab_dir, lab, 'dockerfiles')
+ if not os.path.isdir(docker_dir):
+ print('%s not a directory' % docker_dir)
+ return
+ print('LAB: %s' % lab)
+ df_list = [f for f in os.listdir(docker_dir) if os.path.isfile(os.path.join(docker_dir, f))]
+ for df in df_list:
+ if df.endswith('.swp'):
+ continue
+ dfile_path = os.path.join(docker_dir,df)
+ image_base = VersionInfo.getFrom(dfile_path, registry)
+ print('image base from %s is %s' % (dfile_path, image_base))
+ base_id = VersionInfo.getImageId(image_base)
+ try:
+ parts = df.split('.')
+ image = '%s.%s.%s' % (parts[1], parts[2], role)
+ except:
+ print('could not get image from %s' % df);
+ continue
+ print('image: %s expect base %s' % (image, image_base))
+ created, user, version, use_tag, base = InspectLocalReg.inspectLocal(image, registry, True)
+ print('created: %s user: %s version: %s tag %s base %s' % (created, user, version, use_tag, base))
+ if not base.startswith(image_base):
+ cmd = './relabel.sh %s %s %s %s %s' % (registry, framework_version , image, image_base, base_id)
+ print("MISMATCH")
+ print cmd
+ os.system(cmd)
+
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Build the images labs and publish to a registry')
+ parser.add_argument('-l', '--lab', action='store', help='retag just this lab')
+ parser.add_argument('-t', '--test_registry', action='store_true', default=False, help='build and publish with test registry')
+ parser.add_argument('-s', '--start', action='store', help='start with lab')
+ skip = []
+ with open('skip-labs') as fh:
+ for line in fh:
+ f = os.path.basename(line).strip()
+ #print('will skip [%s]' % f)
+ skip.append(f)
+
+ labdir = '../labs'
+ lab_list = os.listdir(labdir)
+ #
+ # test with a single lab. Then use loop below once it works.
+ #
+ args = parser.parse_args()
+ registry = 'mfthomps'
+ if args.test_registry:
+ registry = 'testregistry:5000'
+ if args.lab is not None:
+ print('retag lab %s' % args.lab)
+ do_lab(labdir, args.lab, 'student', registry)
+ do_lab(labdir, args.lab, 'instructor', registry)
+ else:
+ #print('commented out for now')
+ for lab in sorted(lab_list):
+ if lab not in skip:
+ if args.start is not None and lab < args.start:
+ continue
+ do_lab(labdir, lab, 'student', registry)
+ do_lab(labdir, lab, 'instructor', registry)
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/fix-git-dates.py b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/fix-git-dates.py
new file mode 100755
index 000000000..b01878c76
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/fix-git-dates.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+import subprocess, shlex
+import sys, os.path
+import logging as logger
+import argparse
+import time
+
+parser = argparse.ArgumentParser(
+ description='Use git archive and file times from the current repo to'
+ 'checkout a subset of a git repo with file dates taken from the'
+ 'repo.'
+ 'Current directory must be inside work tree')
+
+parser.add_argument('--verbose', '-v',
+ action="store_true",
+ help='print warnings and debug info for each processed file. ')
+
+parser.add_argument('pathspec',
+ help='path to subdirectory, relative to repo top')
+
+parser.add_argument('dist_path', help='directory of distribution tree')
+
+args = parser.parse_args()
+logger.basicConfig(level=logger.DEBUG if args.verbose else logger.ERROR,
+ format='%(levelname)s:\t%(message)s')
+
+# Find repo's top level.
+try:
+ workdir = os.path.abspath(subprocess.check_output(shlex.split(
+ 'git rev-parse --show-toplevel')).strip())
+except subprocess.CalledProcessError as e:
+ sys.exit(e.returncode)
+
+
+# List files matching user pathspec, relative to current directory
+# git commands always print paths relative to work tree root
+filelist = set()
+
+path = os.path.join(workdir, args.pathspec)
+# file or symlink (to file, to dir or broken - git handles the same way)
+if os.path.isfile(path) or os.path.islink(path):
+ filelist.add(os.path.relpath(path, workdir))
+
+# dir
+elif os.path.isdir(path):
+ for root, subdirs, files in os.walk(path):
+ if '.git' in subdirs:
+ subdirs.remove('.git')
+
+ for file in files:
+ filelist.add(os.path.relpath(os.path.join(root, file), workdir))
+
+
+def fixtimes(filelist, dist_path, pathspec, workdir):
+ for f in filelist:
+ source = os.path.join(workdir, f)
+ dest = os.path.join(dist_path, f)
+ if os.path.isfile(dest):
+ mtime = int(os.path.getmtime(source))
+ os.utime(dest, (mtime, mtime))
+
+if args.pathspec.strip() == './':
+ cmd = 'git archive master | tar -x -C %s' % (args.dist_path)
+else:
+ cmd = 'git archive master %s | tar -x -C %s' % (args.pathspec, args.dist_path)
+os.system(cmd)
+
+fixtimes(filelist, args.dist_path, args.pathspec, workdir)
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/git-restore-mtime.py b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/git-restore-mtime.py
new file mode 100755
index 000000000..0fa89e6b9
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/git-restore-mtime.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# git-restore-mtime - Change mtime of files based on commit date of last change
+#
+# Copyright (C) 2012 Rodrigo Silva (MestreLion)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. See
+#
+# Stripped-down version: no fancy options or statistics. Just the core!
+#
+# Only works from inside the work tree. Assumes git dir is "/.git"
+
+import subprocess, shlex
+import sys, os.path
+import logging as logger
+import argparse
+import time
+
+parser = argparse.ArgumentParser(
+ description='Restore original modification time of files based on '
+ 'the date of the most recent commit that modified them. '
+ 'Useful when generating release tarballs. '
+ 'Current directory must be inside work tree')
+
+parser.add_argument('--verbose', '-v',
+ action="store_true",
+ help='print warnings and debug info for each processed file. ')
+
+parser.add_argument('--merge', '-m',
+ action="store_true",
+ help='include merge commits.')
+
+parser.add_argument('pathspec',
+ nargs='*', default=[os.path.curdir],
+ help='only modify paths (dirs or files) matching PATHSPEC, '
+ 'absolute or relative to current directory. '
+ 'Default is current directory')
+
+args = parser.parse_args()
+logger.basicConfig(level=logger.DEBUG if args.verbose else logger.ERROR,
+ format='%(levelname)s:\t%(message)s')
+
+
+# Find repo's top level.
+try:
+ workdir = os.path.abspath(subprocess.check_output(shlex.split(
+ 'git rev-parse --show-toplevel')).strip())
+except subprocess.CalledProcessError as e:
+ sys.exit(e.returncode)
+
+
+# List files matching user pathspec, relative to current directory
+# git commands always print paths relative to work tree root
+filelist = set()
+for path in args.pathspec:
+
+ # file or symlink (to file, to dir or broken - git handles the same way)
+ if os.path.isfile(path) or os.path.islink(path):
+ filelist.add(os.path.relpath(path, workdir))
+
+ # dir
+ elif os.path.isdir(path):
+ for root, subdirs, files in os.walk(path):
+ if '.git' in subdirs:
+ subdirs.remove('.git')
+
+ for file in files:
+ filelist.add(os.path.relpath(os.path.join(root, file), workdir))
+
+
+# Process the log until all files are 'touched'
+def parselog(merge=False, filterlist=[]):
+ gitobj = subprocess.Popen(shlex.split('git whatchanged --pretty=%at') +
+ (['-m'] if merge else []) + filterlist,
+ stdout=subprocess.PIPE)
+ mtime = 0
+ for line in gitobj.stdout:
+ line = line.strip()
+
+ # Blank line between Date and list of files
+ if not line: continue
+
+ # File line
+ if line.startswith(':'):
+ file = os.path.normpath(line.split('\t')[-1])
+ if file in filelist:
+ logger.debug("%s\t%s", time.ctime(mtime), file)
+ filelist.remove(file)
+ try:
+ os.utime(os.path.join(workdir, file), (mtime, mtime))
+ except Exception as e:
+ logger.error("%s\n", e)
+
+ # Date line
+ else:
+ mtime = long(line)
+
+ # All files done?
+ if not filelist:
+ break
+
+parselog(args.merge)
+
+
+# Missing files
+if filelist and not args.merge:
+ filterlist = list(filelist)
+ for i in range(0, len(filterlist), 100):
+ parselog(merge=True, filterlist=filterlist[i:i+100])
+
+# Still missing some?
+for file in filelist:
+ logger.warn("not found in log: %s", file)
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mk-devel-dist.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mk-devel-dist.sh
new file mode 100755
index 000000000..046481d4d
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mk-devel-dist.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+#
+# Create a distribution for lab designers
+# Expects a directory at /media/sf_SEED into which it
+# will copy the distribution tar.
+#
+revision=`git describe --long`
+myshare=/media/sf_SEED/
+here=`pwd`
+cd ../
+rootdir=`pwd`
+git status -s | grep -E "^ M|^ D|^ A" | less
+ddir=/tmp/labtainer-distrib
+ldir=$ddir/labtainer
+ltrunk=$ldir/trunk
+scripts=$ltrunk/scripts
+labs=$ltrunk/labs
+rm -fr /$ddir
+mkdir $ddir
+mkdir $ldir
+mkdir $ltrunk
+mkdir $labs
+$here/fix-git-dates.py ./ $ltrunk
+cd $ltrunk
+sed -i "s/mm\/dd\/yyyy/$(date '+%m\/%d\/%Y %H:%M')/" README.md
+sed -i "s/^Revision:/Revision: $revision/" README.md
+cp setup_scripts/install-labtainer.sh .
+cp setup_scripts/update-labtainer.sh .
+cd $ldir/trunk/docs/labdesigner
+make
+cp labdesigner.pdf ../../../
+cp labdesigner.pdf $myshare
+
+cd $ldir/trunk/docs/student
+make
+cp labtainer-student.pdf ../../../
+cp labtainer-student.pdf $myshare
+
+cd $ldir/trunk/docs/instructor
+make
+cp labtainer-instructor.pdf ../../../
+cp labtainer-instructor.pdf $myshare
+$here/mkTars.sh $ldir/trunk/labs $here/skip-labs
+cd $ldir/trunk/labs
+mkdir -p /tmp/labtainer_pdf
+cd $rootdir
+distrib/mk-lab-pdf.sh $labs
+cd $ddir
+tar -cz -X $here/skip-labs -f $here/labtainer-developer.tar labtainer
+cd /tmp/
+zip -r $here/labtainer_pdf.zip labtainer_pdf
+cd $here
+cp labtainer-developer.tar $myshare
+cp labtainer_pdf.zip $myshare
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mk-lab-pdf.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mk-lab-pdf.sh
new file mode 100755
index 000000000..b3c59da7f
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mk-lab-pdf.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+labs=$1
+function contains() {
+ local n=$#
+ local value=${!n}
+ for ((i=1;i < $#;i++)) {
+ if [ "${!i}" == "${value}" ]; then
+ echo "y"
+ return 0
+ fi
+ }
+ echo "n"
+ return 1
+}
+rootdir=`pwd`
+mkdir -p /tmp/labtainer_pdf
+skip="distrib/skip-labs"
+skiplist=""
+lines=`cat $skip`
+for line in $lines; do
+ lab=$(basename $line)
+ skiplist+=($lab)
+done
+llist=$(git ls-files labs | cut -d '/' -f 2 | uniq)
+for lab in $llist; do
+ if [ $(contains "${skiplist[@]}" $lab) != "y" ]; then
+ echo "lab is $lab in dir `pwd`"
+ mkdir -p $labs/$lab
+ mkdir -p /tmp/labtainer_pdf/$lab
+ cd $labs/$lab
+ if [[ -d docs ]]; then
+ echo "lab is $lab"
+ cd docs
+ cp -p /tmp/labtainer_pdf/$lab/*.pdf .
+ if [[ -f Makefile ]]; then
+ make
+ else
+ doc=$lab.docx
+ if [[ -f $doc ]]; then
+ soffice --convert-to pdf $doc --headless
+ fi
+ fi
+ cp -p *pdf /tmp/labtainer_pdf/$lab/
+ else
+ cp */instructions.txt /tmp/labtainer_pdf/$lab/ 2>/dev/null
+ fi
+ cd $rootdir
+ fi
+done
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkTars.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkTars.sh
new file mode 100755
index 000000000..8d9931b99
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkTars.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+#
+# for each directory beneath the given one that ends in _tar
+# tar up its content into a file based on the name of the
+# subdirectory. WILL remove any existing tar files unless
+# the directory only contains one tar file.
+#
+containsElement () {
+ local e match="$1"
+ shift
+ for e; do [[ "$e" == "$match" ]] && return 0; done
+ return 1
+}
+if [[ -z "$1" ]]; then
+ echo need a path to top of tmp labs
+fi
+TOP_DIR=$1
+SKIP_LIST=$2
+while read skip; do
+ MY_SKIP="$MY_SKIP $(basename $skip)"
+done <$SKIP_LIST
+echo "my skip is $MY_SKIP"
+echo "lab dir is $LAB_DIR"
+skip_array=($MY_SKIP)
+here=`pwd`
+cd $TOP_DIR
+lab_list=$(ls)
+for lab in $lab_list; do
+ if [[ ! -d $lab ]]; then
+ continue
+ fi
+ containsElement $lab "${skip_array[@]}"
+ result=$?
+ if [[ $result == "0" ]]; then
+ continue
+ fi
+ LAB_DIR=$TOP_DIR/$lab
+ cd $LAB_DIR
+ CONTAINER_LIST=$(ls)
+ for CONTAINER_DIR in $CONTAINER_LIST; do
+ tar_list=$(ls $CONTAINER_DIR)
+ #echo $tar_list
+ for f in $tar_list; do
+ #echo check $f
+ full=$LAB_DIR/$f
+ if [[ -d $full ]]; then
+ if [[ $f == *_tar ]]; then
+ cd $full
+ echo "in $full"
+ tmp_name=${f::-4}
+ tar_name=$tmp_name.tar
+ echo "look for tar_name $tar_name"
+ if [[ ! -f $tar_name ]]; then
+ echo "no $tar_name, make one"
+ tar czf /tmp/$tar_name *
+ rm -fr *
+ mv /tmp/$tar_name .
+ else
+ # is a tar file
+ f_list=$(ls -lt)
+ f_array=($f_list)
+ len=${#f_array[@]}
+ if [[ $len -gt 1 ]] && [[ $tar_name -ot ${f_array[1]} ]] ; then
+ echo "replace tar"
+ rm $tar_name 2> /dev/null
+ tar czf /tmp/$tar_name *
+ rm -fr *
+ mv /tmp/$tar_name .
+ else
+ echo tar is newer, keep it
+ mv $tar_name /tmp/
+ rm -fr *
+ mv /tmp/$tar_name .
+ fi
+ fi
+ fi
+ fi
+ done # each _tar directory
+ done # each container
+done #each lab
+cd $here
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkdist.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkdist.sh
new file mode 100755
index 000000000..5b20d117f
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkdist.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+function contains() {
+ local n=$#
+ local value=${!n}
+ for ((i=1;i < $#;i++)) {
+ if [ "${!i}" == "${value}" ]; then
+ echo "y"
+ return 0
+ fi
+ }
+ echo "n"
+ return 1
+}
+revision=`git describe --long`
+skip="skip-labs"
+skiplist=""
+lines=`cat $skip`
+for line in $lines; do
+ lab=$(basename $line)
+ skiplist+=($lab)
+done
+mkdir -p /tmp/labtainer_pdf
+#myshare=/home/mike/sf_SEED/
+myshare=/media/sf_SEED/
+here=`pwd`
+cd ../
+rootdir=`pwd`
+git status -s | grep -E "^ M|^ D|^ A" | less
+ddir=/tmp/labtainer-distrib
+ldir=$ddir/labtainer
+ltrunk=$ldir/trunk
+scripts=$ltrunk/scripts
+labs=$ltrunk/labs
+rm -fr /$ddir
+mkdir $ddir
+mkdir $ldir
+mkdir $ltrunk
+git archive master README.md | tar -x -C $ltrunk
+sed -i "s/mm\/dd\/yyyy/$(date '+%m\/%d\/%Y %H:%M')/" $ltrunk/README.md
+sed -i "s/^Revision:/Revision: $revision/" $ltrunk/README.md
+#git archive master config | tar -x -C $ltrunk
+$here/fix-git-dates.py config $ltrunk
+$here/fix-git-dates.py setup_scripts $ltrunk
+$here/fix-git-dates.py docs $ltrunk
+$here/fix-git-dates.py tool-src $ltrunk
+$here/fix-git-dates.py distrib/skip-labs $ltrunk
+mkdir $scripts
+$here/fix-git-dates.py scripts/labtainer-student $ltrunk
+$here/fix-git-dates.py scripts/labtainer-instructor $ltrunk
+mkdir $labs
+llist=$(git ls-files labs | cut -d '/' -f 2 | uniq)
+for lab in $llist; do
+ if [ $(contains "${skiplist[@]}" $lab) != "y" ]; then
+ $here/fix-git-dates.py labs/$lab/config $ltrunk
+ $here/fix-git-dates.py labs/$lab/instr_config $ltrunk
+ if [[ -d labs/$lab/docs ]]; then
+ $here/fix-git-dates.py labs/$lab/docs $ltrunk
+ fi
+ if [[ -d labs/$lab/bin ]]; then
+ $here/fix-git-dates.py labs/$lab/bin $ltrunk
+ fi
+ fi
+done
+distrib/mk-lab-pdf.sh $labs
+result=$?
+echo "result of mk-lab-pdf is $result"
+if [ $result -ne 0 ]; then
+ echo "Trouble making lab manuals"
+ exit
+fi
+cd $ldir
+mv trunk/setup_scripts/install-labtainer.sh .
+ln -s trunk/setup_scripts/update-labtainer.sh .
+ln -s trunk/setup_scripts/update-designer.sh .
+
+cd $ldir/trunk/docs/student
+make
+cp labtainer-student.pdf ../../../
+cp labtainer-student.pdf $myshare
+
+cd $ldir/trunk/docs/instructor
+make
+cp labtainer-instructor.pdf ../../../
+cp labtainer-instructor.pdf $myshare
+
+cd $ldir/trunk/tool-src/capinout
+pwd
+./mkit.sh
+cd $ddir
+tar -cz -X $here/skip-labs -f $here/labtainer.tar labtainer
+cd /tmp/
+#tar -czf $here/labtainer_pdf.tar.gz labtainer_pdf
+zip -r $here/labtainer_pdf.zip labtainer_pdf
+cd $here
+cp labtainer.tar $myshare
+cp labtainer_pdf.zip $myshare
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mktest.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mktest.sh
new file mode 100755
index 000000000..92a992369
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mktest.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Create a distribution of the SimLab data files for
+# Labtainers regression testing.
+# NOTE: The files are in a separate, private repo, and
+# are not generally distributed.
+# Assumes the simlab files are in ../../Labtainers-simlab/simlab
+#
+tmp_dir=/tmp/labtainer_tests
+rm -fr $tmp_dir
+mkdir $tmp_dir
+trunk=$tmp_dir/trunk
+mkdir $trunk
+here=`pwd`
+cd ../
+$here/fix-git-dates.py distrib $trunk
+$here/fix-git-dates.py testsets $trunk
+cd ../Labtainers-simlab
+git status -s | grep -E "^ M|^ D|^ A" | less
+$here/fix-git-dates.py simlab $tmp_dir
+#git archive master simlab | tar -x -C $tmp_dir
+cd $tmp_dir
+tar czf /tmp/labtainer-tests.tar trunk simlab
+mv /tmp/labtainer-tests.tar /media/sf_SEED/
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish.py b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish.py
new file mode 100755
index 000000000..283ac2bdb
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+'''
+This software was created by United States Government employees at
+The Center for the Information Systems Studies and Research (CISR)
+at the Naval Postgraduate School NPS. Please note that within the
+United States, copyright protection is not available for any works
+created by United States Government employees, pursuant to Title 17
+United States Code Section 105. This software is in the public
+domain and is not subject to copyright.
+'''
+import sys
+import os
+import subprocess
+import shlex
+import argparse
+sys.path.append('../scripts/labtainer-student/bin')
+import LabtainerLogging
+import ParseLabtainerConfig
+import labutils
+import VersionInfo
+import removelab
+'''
+Build and publish labtainer images. Use -h option for help.
+'''
+def relabel(image, version, base_image, base_id, registry):
+ with open('./dfile', 'w') as fh:
+ fh.write('FROM %s\n' % image)
+ fh.write('ARG version\n')
+ fh.write('LABEL version=%s\n' % version)
+ fh.write('LABEL base=%s.%s' % (base_image, base_id))
+
+ cmd = 'docker build -f dfile -t %s.tmp .' % image
+ os.system(cmd)
+ cmd = 'docker tag %s.tmp %s/%s' % (image, registry, image)
+ print cmd
+ os.system(cmd)
+ cmd = 'docker push %s/%s' % (registry, image)
+ print cmd
+ os.system(cmd)
+ cmd = 'docker tag %s.tmp %s/%s:base_image%s' % (image, registry, image, base_id)
+ print cmd
+ os.system(cmd)
+ cmd = 'docker push %s/%s:base_image%s' % (registry, image, base_id)
+ print cmd
+ os.system(cmd)
+
+def rebuild(labname, labsdir, force, logger):
+ mycwd = os.getcwd()
+ path = '../scripts/labtainer-student'
+ os.chdir(path)
+ #print('now at %s' % os.getcwd())
+ lab_dir = os.path.join(labsdir, labname)
+ #print('cwd was %s now %s lab_dir is %s' % (mycwd, os.getcwd(), lab_dir))
+ retval = labutils.DoRebuildLab(lab_dir, force_build=force)
+ os.chdir(mycwd)
+ return retval
+
+def pushIt(lab, docker_dir, registry, logger):
+ '''
+ Set the label and tags on any newly built image and push it to the given registry.
+ '''
+ df_list = [f for f in os.listdir(docker_dir) if os.path.isfile(os.path.join(docker_dir, f))]
+ for df in df_list:
+ if df.endswith('.swp'):
+ continue
+ logger.DEBUG('tag and push %s' % df)
+ try:
+ parts = df.split('.')
+ image = '%s.%s.student' % (parts[1], parts[2])
+ except:
+ logger.ERROR('could not get image from %s' % df);
+ continue
+ image_exists, dumb, dumb1 = labutils.ImageExists(image, None)
+ if image_exists:
+ dfile_path = os.path.join(docker_dir,df)
+ image_base = VersionInfo.getFrom(dfile_path, registry)
+ base_id = VersionInfo.getImageId(image_base, True)
+ framework_version = labutils.framework_version
+ relabel(image, framework_version, image_base, base_id, registry)
+
+ else:
+ logger.DEBUG('Have not built %s, nothing to push' % image)
+ ''' Delete the lab images. Two reasons: 1) ensure we run authoritative copy,
+ which is from the dockerhub. 2) don't push on a rebuild if not rebuilt. '''
+ removelab.removeLab(lab)
+
+def DoLab(lab, labsdir, force, logger, do_login, test_registry, default_registry):
+ logger.DEBUG('DoLab for %s' % lab)
+ lab_dir = os.path.join(labsdir, lab)
+ registry_set = rebuild(lab, labsdir, force, logger)
+ if len(registry_set) > 1:
+ logger.ERROR('no current support for images from multiple registries')
+ exit(1)
+ else:
+ registry = list(registry_set)[0]
+ logger.DEBUG('back from rebuild with registry of %s' % registry)
+ ''' should we login? Never if test registry '''
+ if not test_registry:
+ if registry is not None and registry != default_registry:
+ print('registry %s not equal %s, login' % (registry, default_registry))
+ os.system('docker login -u %s' % registry)
+ else:
+ registry = default_registry
+ if do_login:
+ os.system('docker login -u %s' % registry)
+ docker_dir = os.path.join(labsdir, lab, 'dockerfiles')
+ pushIt(lab, docker_dir, registry, logger)
+
+def main():
+ parser = argparse.ArgumentParser(description='Build the images labs and publish to a registry')
+ parser.add_argument('-l', '--lab', action='store', help='build and publish just this lab')
+ parser.add_argument('-s', '--start', action='store', help='all labs starting with this one')
+ parser.add_argument('-t', '--test_registry', action='store_true', default=False, help='build and publish with test registry')
+ parser.add_argument('-f', '--force', action='store_true', default=False, help='force rebuild of all images')
+ args = parser.parse_args()
+ if args.test_registry:
+ if os.getenv('TEST_REGISTRY') is None:
+ print('use putenv to set it')
+ os.putenv("TEST_REGISTRY", "TRUE")
+ ''' why does putenv not set the value? '''
+ os.environ['TEST_REGISTRY'] = 'TRUE'
+ else:
+ print('exists, set it true')
+ os.environ['TEST_REGISTRY'] = 'TRUE'
+ print('set TEST REG to %s' % os.getenv('TEST_REGISTRY'))
+
+ src_path = '../'
+ labtainer_config_file = os.path.join(src_path, 'config', 'labtainer.config')
+ logger = LabtainerLogging.LabtainerLogging("labtainer-publish.log", 'publish', labtainer_config_file)
+ labutils.logger = logger
+
+
+ skip_labs = 'skip-labs'
+
+ skip = []
+ with open(skip_labs) as fh:
+ for line in fh:
+ f = os.path.basename(line).strip()
+ print('adding [%s]' % f)
+ skip.append(f)
+
+ labsdir = os.path.abspath(os.path.join(src_path, 'labs'))
+
+ labtainer_config = ParseLabtainerConfig.ParseLabtainerConfig(labtainer_config_file, logger)
+ default_registry = labtainer_config.default_registry
+
+ if args.lab is not None:
+ logger.DEBUG('Doing just one lab %s labsdir %s' % (args.lab, labsdir))
+ # Do login here and now so we don't wait for lab to build before prompt
+ if not args.test_registry:
+ os.system('docker login -u %s' % default_registry)
+ DoLab(args.lab, labsdir, args.force, logger, False, args.test_registry, default_registry)
+ else:
+ # do them all. warn of incomplete git
+ mycwd = os.getcwd()
+ os.chdir(labsdir)
+ command = 'git status -s'
+ ps = subprocess.Popen(shlex.split(command), True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+ grep_command = 'grep -E "^M|^D|^A"'
+ ps_grep = subprocess.Popen(shlex.split(grep_command), stdin=ps.stdout,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ ps.stdout.close()
+ output = ps_grep.communicate()
+ if len(output[0]) > 0:
+ for line in output[0].splitlines(True):
+ print line.strip()
+ dumb = raw_input("any key to continue")
+
+ if not args.test_registry:
+ os.system('docker login -u %s' % default_registry)
+ #cmd = 'svn ls https://tor.ern.nps.edu/svn/proj/labtainer/trunk/labs'
+ cmd = 'git ls-files ./ | cut -d/ -f1 | uniq'
+ child = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+ output = child.communicate()
+ lab_list = output[0].strip().splitlines(True)
+ for lab in sorted(lab_list):
+ #lab = lab[:len(lab)-1]
+ lab = lab.strip()
+ if args.start is not None and lab < args.start:
+ continue
+ if lab not in skip:
+ print('Lab: %s' % lab)
+ lab_dir = os.path.join(labsdir, lab)
+ os.chdir(lab_dir)
+ cmd = 'git checkout ./'
+ os.system(cmd)
+ os.chdir(mycwd)
+ DoLab(lab, labsdir, args.force, logger, False, args.test_registry, default_registry)
+
+if __name__ == '__main__':
+ sys.exit(main())
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish_grader.py b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish_grader.py
new file mode 100755
index 000000000..8266c91e4
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish_grader.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+import os
+import sys
+import argparse
+sys.path.append('../scripts/labtainer-student/bin')
+import labutils
+import ParseLabtainerConfig
+import LabtainerLogging
+import VersionInfo
+def relabel(image, version, base_image, base_id, registry):
+ with open('./dfile', 'w') as fh:
+ fh.write('FROM %s\n' % image)
+ fh.write('ARG version\n')
+ fh.write('LABEL version=%s\n' % version)
+ fh.write('LABEL base=%s.%s' % (base_image, base_id))
+
+ cmd = 'docker build -f dfile -t %s.tmp .' % image
+ os.system(cmd)
+ cmd = 'docker tag %s.tmp %s/%s' % (image, registry, image)
+ print cmd
+ os.system(cmd)
+ cmd = 'docker push %s/%s' % (registry, image)
+ print cmd
+ os.system(cmd)
+ cmd = 'docker tag %s.tmp %s/%s:base_image%s' % (image, registry, image, base_id)
+ print cmd
+ os.system(cmd)
+ cmd = 'docker push %s/%s:base_image%s' % (registry, image, base_id)
+ print cmd
+ os.system(cmd)
+
+def main():
+ parser = argparse.ArgumentParser(description='Build and publish the grader')
+ parser.add_argument('-t', '--test_registry', action='store_true', help='Use image from test registry')
+ args = parser.parse_args()
+ if args.test_registry:
+ if os.getenv('TEST_REGISTRY') is None:
+ print('use putenv to set it')
+ os.putenv("TEST_REGISTRY", "TRUE")
+ ''' why does putenv not set the value? '''
+ os.environ['TEST_REGISTRY'] = 'TRUE'
+ else:
+ print('exists, set it true')
+ os.environ['TEST_REGISTRY'] = 'TRUE'
+ print('set TEST REG to %s' % os.getenv('TEST_REGISTRY'))
+ here = os.getcwd()
+ os.chdir('../scripts/designer/bin')
+ test_registry = ''
+ if args.test_registry:
+ test_registry = '-t'
+ cmd = './create_image.sh grader %s' % test_registry
+ os.system(cmd)
+ os.chdir(here)
+ src_path = '../'
+ labtainer_config_file = os.path.join(src_path, 'config', 'labtainer.config')
+ logger = LabtainerLogging.LabtainerLogging("publish_grader.log", 'publish', labtainer_config_file)
+ labutils.logger = logger
+
+ labtainer_config = ParseLabtainerConfig.ParseLabtainerConfig(labtainer_config_file, logger)
+ if args.test_registry:
+ registry = labtainer_config.test_registry
+ else:
+ registry = labtainer_config.default_registry
+ dfile_path = '../scripts/designer/base_dockerfiles/Dockerfile.labtainer.grader'
+ image_base = VersionInfo.getFrom(dfile_path, registry)
+ base_id = VersionInfo.getImageId(image_base)
+ framework_version = labutils.framework_version
+ relabel('labtainer.grader', framework_version, image_base, base_id, registry)
+
+
+
+if __name__ == '__main__':
+ sys.exit(main())
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/pull_tag_push.py b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/pull_tag_push.py
new file mode 100755
index 000000000..a3115dc64
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/pull_tag_push.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+import os
+import sys
+import argparse
+sys.path.append('../scripts/labtainer-student/bin')
+import InspectLocalReg
+import InspectRemoteReg
+'''
+Pull all labtainer container images from the docker hub, retag them, and push to a
+local registry. Only replace the local registry if its image is older than the remote.
+'''
+
+def do_lab(lab_dir, lab, role, source_reg, dest_reg, force):
+ docker_dir = os.path.join(labdir, lab, 'dockerfiles')
+ if not os.path.isdir(docker_dir):
+ return
+ df_list = [f for f in os.listdir(docker_dir) if os.path.isfile(os.path.join(docker_dir, f))]
+ for df in df_list:
+ if df.endswith('.swp'):
+ continue
+ try:
+ parts = df.split('.')
+ image = '%s.%s.%s' % (parts[1], parts[2], role)
+ except:
+ print('could not get image from %s' % df);
+ continue
+ local_created, local_user, version, tag = InspectLocalReg.inspectLocal(image, dest_reg)
+ if local_created is not None:
+ remote_created, remote_user, version, tag = InspectRemoteReg.inspectRemote(image)
+ if force or local_created is None or remote_created > local_created:
+ cmd = 'docker pull %s/%s' % (source_reg, image)
+ #print cmd
+ os.system(cmd)
+ cmd = 'docker tag %s/%s %s/%s' % (source_reg, image, dest_reg, image)
+ #print cmd
+ os.system(cmd)
+ cmd = 'docker push %s/%s' % (dest_reg, image)
+ #print cmd
+ os.system(cmd)
+ else:
+ print('local registry for %s is up to date.' % image)
+
+parser = argparse.ArgumentParser(description='pull from the docker hub and push to local registry')
+parser.add_argument('-l', '--lab', action='store', help='only pull/tag/push this lab')
+parser.add_argument('-f', '--force', action='store_true', default=False, help='force pull/push')
+args = parser.parse_args()
+skip = []
+with open('skip-labs') as fh:
+ for line in fh:
+ f = os.path.basename(line).strip()
+ print('will skip [%s]' % f)
+ skip.append(f)
+
+labdir = '../labs'
+lab_list = os.listdir(labdir)
+#
+# test with a single lab. Then use loop below once it works.
+#
+testregistry = 'testregistry:5000'
+if args.lab is not None:
+ do_lab(labdir, args.lab, 'student', 'mfthomps', testregistry, args.force)
+ do_lab(labdir, args.lab, 'instructor', 'mfthomps', testregistry, args.force)
+else:
+ #print('commented out for now')
+ testregistry = 'testregistry:5000'
+ for lab in sorted(lab_list):
+ if lab not in skip:
+ do_lab(labdir, lab, 'student', 'mfthomps', testregistry, args.force)
+ do_lab(labdir, lab, 'instructor', 'mfthomps', testregistry, args.force)
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/push_base.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/push_base.sh
new file mode 100755
index 000000000..2f34fe2eb
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/push_base.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+pull_push(){
+ registry=mfthomps
+ test_registry=testregistry:5000
+ docker pull $registry/$1
+ docker tag $registry/$1 $test_registry/$1
+ docker push $test_registry/$1
+}
+pull_push labtainer.base
+pull_push labtainer.network
+pull_push labtainer.firefox
+pull_push labtainer.wireshark
+pull_push labtainer.java
+pull_push labtainer.centos
+pull_push labtainer.centos.xtra
+pull_push labtainer.lamp
+pull_push labtainer.lamp.xtra
+pull_push labtainer.kali
+pull_push labtainer.metasploitable
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/relabel.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/relabel.sh
new file mode 100755
index 000000000..1f8664106
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/relabel.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+REGISTRY=$1
+VERSION=$2
+IMAGE=$3
+BASE_IMAGE=$4
+BASE_ID=$5
+
+cat < dfile
+ARG registry
+FROM \$registry/$IMAGE
+ARG version
+LABEL version=\$version
+LABEL base=$BASE_IMAGE.$BASE_ID
+EOT
+
+docker build --build-arg registry=$REGISTRY --build-arg version=$VERSION \
+ --pull -f dfile -t $IMAGE .
+
+docker tag $IMAGE $REGISTRY/$IMAGE
+docker push $REGISTRY/$IMAGE
+docker tag $IMAGE $REGISTRY/$IMAGE:base_image$BASE_ID
+docker push $REGISTRY/$IMAGE:base_image$BASE_ID
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/remove-container.sh b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/remove-container.sh
new file mode 100755
index 000000000..6554ab1ce
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/remove-container.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+cont_list=$(docker ps -a | grep $1 | awk '{ print $1" }')
+if [ ! -z "$cont_list" ]; then
+ docker rm $cont_list
+fi
+image_list=$(docker images | grep $1 | awk '{ print $1":"$2 }')
+if [ ! -z "$image_list" ]; then
+ docker rmi -f $image_list
+fi
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/retag_all.py b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/retag_all.py
new file mode 100755
index 000000000..7594fb244
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/retag_all.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+import os
+import sys
+import argparse
+sys.path.append('../scripts/labtainer-student/bin')
+import InspectLocalReg
+import InspectRemoteReg
+import VersionInfo
+import labutils
+import subprocess
+'''
+Retag all labtainer images to include their base image id, and include the base
+image name in a label.
+'''
+
+def do_lab(lab_dir, lab, role, registry):
+ framework_version = labutils.framework_version
+ ''' use docker files to identify each docker image to relabel '''
+ docker_dir = os.path.join(lab_dir, lab, 'dockerfiles')
+ if not os.path.isdir(docker_dir):
+ print('%s not a directory' % docker_dir)
+ return
+ df_list = [f for f in os.listdir(docker_dir) if os.path.isfile(os.path.join(docker_dir, f))]
+ for df in df_list:
+ if df.endswith('.swp'):
+ continue
+ dfile_path = os.path.join(docker_dir,df)
+ ''' get the image name from the docker file '''
+ image_base = VersionInfo.getFrom(dfile_path, registry)
+ ''' get the base identifier of the image present on this installation for that image '''
+ base_id = VersionInfo.getImageId(image_base)
+ try:
+ parts = df.split('.')
+ image = '%s.%s.%s' % (parts[1], parts[2], role)
+ except:
+ print('could not get image from %s' % df);
+ continue
+ cmd = './relabel.sh %s %s %s %s %s' % (registry, framework_version , image, image_base, base_id)
+ print cmd
+ os.system(cmd)
+
+def main():
+ parser = argparse.ArgumentParser(description='Build the images labs and publish to a registry')
+ parser.add_argument('-l', '--lab', action='store', help='retag just this lab')
+ parser.add_argument('-t', '--test_registry', action='store_true', default=False, help='build and publish with test registry')
+ skip = []
+ with open('skip-labs') as fh:
+ for line in fh:
+ f = os.path.basename(line).strip()
+ #print('will skip [%s]' % f)
+ skip.append(f)
+
+ labdir = '../labs'
+ lab_list = os.listdir(labdir)
+ #
+ # test with a single lab. Then use loop below once it works.
+ #
+ args = parser.parse_args()
+ registry = 'mfthomps'
+ if args.test_registry:
+ registry = 'testregistry:5000'
+ if args.lab is not None:
+ print('retag lab %s' % args.lab)
+ do_lab(labdir, args.lab, 'student', registry)
+ else:
+ #print('commented out for now')
+ for lab in sorted(lab_list):
+ if lab not in skip:
+ do_lab(labdir, lab, 'student', registry)
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/skip-labs b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/skip-labs
new file mode 100644
index 000000000..4984db687
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/distrib/skip-labs
@@ -0,0 +1,14 @@
+labtainer/trunk/labs/nmaplab
+labtainer/trunk/labs/httplab
+labtainer/trunk/labs/liveforensics
+labtainer/trunk/labs/bind-shell
+labtainer/trunk/labs/tlab
+labtainer/trunk/labs/metasploitable-test
+labtainer/trunk/labs/kali-test
+labtainer/trunk/labs/my-remote-dns
+labtainer/trunk/labs/remote-dns2
+labtainer/trunk/labs/remote-dns
+labtainer/trunk/labs/backups
+labtainer/trunk/labs/centos-log
+labtainer/trunk/labs/dhcp-test
+labtainer/trunk/labs/xlab
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/Makefile b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/Makefile
new file mode 100644
index 000000000..a06cd457a
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/Makefile
@@ -0,0 +1,6 @@
+development.pdf: development.tex
+ latex development
+ pdflatex development
+clean:
+ rm -fr auto
+ rm -fr development.aux development.pdf
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/apt-sources.txt b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/apt-sources.txt
new file mode 100644
index 000000000..a9a422467
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/apt-sources.txt
@@ -0,0 +1,5 @@
+The apt sources.list may name mirrors that cannot be reached.
+The container from ubuntu initially names archive.ubuntu.com
+The Labtainer config file will include an entry for an alternate
+source. A sed command in the dockerfile will effect the change.
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/compat.tex b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/compat.tex
new file mode 100644
index 000000000..e0d1b408b
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/compat.tex
@@ -0,0 +1,115 @@
+Note on backward compatibility
+
+A user may easily get a new container image that requires framework
+script support not present in the user's environment, e.g., has
+not yet done an update-labtainer.sh.
+
+A user may have an old container not supported by framework scripts
+obtained via an update-labtainer.sh
+
+\section{Lab Versions}
+Substantive changes to an existing published lab should be made in
+a new named lab. A "substantive" change is defined as one that would
+break any existing installation. The sole exception is the case in
+which a newer lab image would require a Labtainers update.
+
+Never change container names for existing labs.
+
+Management of multiple versions of the same lab will be achieved entirely
+by the user environment and what is distributed to it.
+
+\subsection{Managing versions}
+Labtainer updates will not remove old labs from installed systems, however
+they may stop distributing old labs.
+
+If a user installation contains two versions of a lab, only the latest will
+be displayed in the labtainer command -- unless the installation includes
+containers for the older -- in which case both will be listed.
+
+If a user starts an older version of a lab for the first time, warn the user
+with a prompt. Subsequently, note the existence of the newer lab without a prompt.
+
+Lab names change with versions, e.g., centos-logv2. (tab completion would really
+help here).
+
+Defining multiple labs as being different versions of the same lab is achieved
+in a "version" file in the lab/config directory. Absence of the file implies the
+lab is its only version and is its base name. Otherwise, the file includes the
+lab basename and its version number, which is syntatically independent of the name
+of the lab, e.g., lab names need not incorporate a "v2". Version numbers are integers.
+Lab basnames are ONLY used to distinguish versions of the same lab. Students and
+instructors name labs using their lab name, not their basename.
+
+\subsection{Images dependent on framework versions}
+The sole exception to the requirement for compatability of lab versions is the
+case where we can request the user to update the labtainers framework in order
+to run the new labs. This concept is not limited to versions of the same lab,
+it also pertains to changes to scripts in images that require corresponding
+support from the framework. An example might be a new argument to the
+parameterize.sh script. If new images expect this parameter, then the framework
+must provide it, i.e., it must be updated. (Backward compatability must still be
+supported, i.e., old images MUST run with all new frameworks.)
+
+These versions relationships will be managed crudely. Once any new lab requires an
+updated framework, all subsequent labs will require at least that framework version,
+(whether it needs it or not).
+
+These versions are managed by a version number imbedded in the build process.
+
+
+\subsection{Base image replacements and changes}
+Transitioning to new base images will force some users to wait for new large downloads
+when starting a new lab.
+
+Can we tell the student how large the download will be? not likely.
+But we can identify the lack of a base image on the student computer, and notify them
+of that.
+
+MOTIVE: Reduce cumulative size of all base images needed to perform labs.
+This means always rebuilding all labs whenever a base changes.
+
+OPTIMIZE for size of the VM.
+
+Roadmap:
+\begin{itemize}
+\item Replace existing images with identical images having new version labels,
+thus forcing an update of the framework.
+\item New framework version will be sensitive to base image versions.
+
+\item Re-tag all lab images to reflect an initial base image version.
+
+\item Before a pull (or a update-labtainer.sh!), the framework will determine its
+base-image version, and pull the lab image versions consistent with that base image.
+
+\item The tag associated with each lab image will reflect its base image
+dependency. The "latest" image version implies the latest base image version.
+
+\item The initial base image version is 1. All images will be tagged to reflect
+that version.
+
+\item Separate logic for ensuring student has necessary base for a lab, and prompt if
+a big download is needed.
+\end{itemize}
+
+NEVER PULL and old base. NEVER build from an old base
+
+If a base is updated, you MUST rebuild all labs.
+
+
+
+PROCEDURE
+publish new framework
+retag all images
+
+rebuild base images and push
+
+rebuild all images
+
+
+HOW to run and test old images?
+
+Keep an old VM!
+
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/dev.tex b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/dev.tex
new file mode 100644
index 000000000..f58cde9d2
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/dev.tex
@@ -0,0 +1,93 @@
+The framework has not yet been adapted to use Linux package managers.
+Currently, scripts are run from a workspace directory and python
+paths are managed relatively between scripts.
+
+Student scripts, e.g., start.py, run from the trunk/scripts/labtainer-student directory.
+That directory also contains the labutils.py, which contains most of the framework
+functions.
+
+When a student container is first started "docker exec" is used
+to run parameterize.sh on the container.
+
+That script also invokes hookBash.sh, which adds the bash
+sdtin/stout capturing hook, and adds the startup.sh call
+into the .profile.
+
+The startup.sh scripts differ between instructor and student. The latter
+displays instructions.txt. The former runs grading.
+The startup.sh uses a lock to control which
+terminal displays the instructions or grading. In practice instruction
+display and the running of the instructor.py script is done by
+an xterm that explicitly runs the startup.sh directly, and thus
+the startup.sh invoked by profile.sh typically never does anything.
+HOWEVER... the startup.sh invoked by student will source a student_startup.sh if present.
+
+Regression testing of grading functions is performed by labtainer-instructor/regress.py.
+Expected results are stored in the labtainer/testsets directory.
+
+\section{Developer Software Prerequisits}
+\begin {itemize}
+\item Subversion
+\item Latex (texlive-full)
+\end {itemize}
+
+
+\section{Getting Labtainers from Subversion}
+svn co https://tor.ern.nps.edu/svn/proj/labtainer
+Change directory to trunk/setup-scripts and run ./build-docs.sh to build the PDF lab
+manuals so that you can reference the manuals while you test or otherwise reference
+existing labs. (Please follow the lab manual and report discrepancies!)
+Then run ./pull-all.sh to pull all the baseline images (so that your running of
+existing labs is more akin to what students and instructors do so we can better test that).
+
+\section{Testing and Running Existing Labs}
+There are situations where you will run an existing lab, e.g., to test it, or to
+observe some example. When running labs, please refer to the lab manuals
+so that they get reivewed and tested by different people. Also, please first delete
+the lab using trunk/setup\_scripts/removelab.sh to ensure that you are running the latest
+version of the published lab. If you find the lab to be broken, e.g., missing a file, please
+attempt to run "rebuild.py" on the lab. Report these findings to the lab author. And always
+run removelab.sh after you have run an existing lab via rebuild.py. Again, the goal is to
+force ourselves to run the distributed labs unless we have specific reasons to do otherwise.
+
+
+\section{Automation and Distributions}
+The mkdist.sh script runs on a Linux VM hosted on windows, and creates the distribution tar
+and copies it into a shared folder. From that folder, it is copied to the
+\\my.nps.edu@SSL\DavWWWRoot\webdav\c30-staging\document\_library" and then "Publish to Live" is
+performed on the Liferay site.
+Two prepackaged VMs are maintained: one for VirtualBox, and one for VMWare. Each include
+their respective guest additions. The VMs are maintained on a Linux system using command line
+utilities, e.g., VBoxManage. The VMs are rigged to update labtainers, including a pull of
+baseline images, on each boot until the first lab is commenced. Scripts named "export*" are
+used to created the appliance files. The scripts re-import into test images, which must be
+manually tested. The WinSCP script pushes new applicance images to the CyberCIEGE download
+directory on the C3O web server. (Wine and WinSCP must be installed on the Linux host that
+manages the VMs.
+
+\section {Race condition on checklocal.sh output}
+If an mynotify.py event causes an output from checklocal.py, that may conflict with
+concurrent output from checklocal.py resulting from some program/script running. In
+theory, the program/script should complete its run of checklocal before the program/script
+actually gets to access the file that triggers a mynotify watch. So, the latter's output
+to the timestamped file is appended. Further, the mynotify.py looks for an existing timestamped
+file, and if not found, looks for one from the previous second. This hack is an attempt to
+keep the outputs merged. It will fail if the access does not happen within a second of the
+program start. See the acl lab.
+
+\section {installation sizes}
+An initial install, including the base images, requires about 4GB. Installing a larger lab,
+e.g., snort, requires an additional 1GB. Running bufoverflow added 22M.
+
+\section {temporal logic considerations}
+When evaluating results from logfiles containing timestamps use FILE\_TS or FILE\_TS\_REGEX
+to ensure you get timestamped values for only matching records. Reliance on goals.config to
+matchany can result in timestamped results that don't corrolate to the desired record.
+
+\section {parameterizing the start.config}
+Is difficult. The current parameterization features only affect containers, and leave no
+persistent trail. Thus, several students could share a computer and, via "redo.py", each
+perform that same lab with parameterization maintained for each student. There is only one
+start.config per Labtainers installation. But... the start.config is only used during
+docker create container. So that could be driven from a copy that is parameterized as needed?
+Except, the parameterized values are available for assessment.
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.aux b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.aux
new file mode 100644
index 000000000..220293f47
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.aux
@@ -0,0 +1,47 @@
+\relax
+\providecommand\hyper@newdestlabel[2]{}
+\providecommand\BKM@entry[2]{}
+\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
+\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
+\global\let\oldcontentsline\contentsline
+\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
+\global\let\oldnewlabel\newlabel
+\gdef\newlabel#1#2{\newlabelxx{#1}#2}
+\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
+\AtEndDocument{\ifx\hyper@anchor\@undefined
+\let\contentsline\oldcontentsline
+\let\newlabel\oldnewlabel
+\fi}
+\fi}
+\global\let\hyper@last\relax
+\gdef\HyperFirstAtBeginDocument#1{#1}
+\providecommand\HyField@AuxAddToFields[1]{}
+\providecommand\HyField@AuxAddToCoFields[2]{}
+\BKM@entry{id=1,dest={73656374696F6E2E31},srcline={21}}{496E74726F64756374696F6E}
+\BKM@entry{id=2,dest={73656374696F6E2E32},srcline={27}}{446576656C6F70657220536F66747761726520507265726571756973697473}
+\BKM@entry{id=3,dest={73656374696F6E2E33},srcline={34}}{47657474696E67204C61627461696E6572732066726F6D2053756276657273696F6E}
+\BKM@entry{id=4,dest={73656374696F6E2E34},srcline={43}}{54657374696E6720616E642052756E6E696E67204578697374696E67204C616273}
+\BKM@entry{id=5,dest={73656374696F6E2E35},srcline={53}}{4F76657276696577206F66204C61627461696E657220456C656D656E7473}
+\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{2}{section.1}}
+\@writefile{toc}{\contentsline {section}{\numberline {2}Developer Software Prerequisits}{2}{section.2}}
+\@writefile{toc}{\contentsline {section}{\numberline {3}Getting Labtainers from Subversion}{2}{section.3}}
+\@writefile{toc}{\contentsline {section}{\numberline {4}Testing and Running Existing Labs}{2}{section.4}}
+\@writefile{toc}{\contentsline {section}{\numberline {5}Overview of Labtainer Elements}{2}{section.5}}
+\BKM@entry{id=6,dest={73656374696F6E2E36},srcline={77}}{436F6E74726F6C20466C6F77}
+\BKM@entry{id=7,dest={73656374696F6E2E37},srcline={94}}{4175746F6D6174696F6E20616E6420446973747269627574696F6E73}
+\@writefile{toc}{\contentsline {section}{\numberline {6}Control Flow}{3}{section.6}}
+\@writefile{toc}{\contentsline {section}{\numberline {7}Automation and Distributions}{3}{section.7}}
+\BKM@entry{id=8,dest={73656374696F6E2E38},srcline={145}}{696E7374616C6C6174696F6E2073697A6573}
+\BKM@entry{id=9,dest={73656374696F6E2E39},srcline={150}}{4E6F746573}
+\BKM@entry{id=10,dest={73756273656374696F6E2E392E31},srcline={151}}{5261636520636F6E646974696F6E206F6E20636865636B6C6F63616C2E7368206F7574707574}
+\BKM@entry{id=11,dest={73756273656374696F6E2E392E32},srcline={161}}{74656D706F72616C206C6F67696320636F6E73696465726174696F6E73}
+\BKM@entry{id=12,dest={73756273656374696F6E2E392E33},srcline={166}}{706172616D65746572697A696E67207468652073746172742E636F6E666967}
+\BKM@entry{id=13,dest={73756273656374696F6E2E392E34},srcline={171}}{5061636B6167696E67}
+\BKM@entry{id=14,dest={73756273656374696F6E2E392E35},srcline={176}}{546F646F}
+\@writefile{toc}{\contentsline {section}{\numberline {8}installation sizes}{4}{section.8}}
+\@writefile{toc}{\contentsline {section}{\numberline {9}Notes}{4}{section.9}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {9.1}Race condition on checklocal.sh output}{4}{subsection.9.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {9.2}temporal logic considerations}{4}{subsection.9.2}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {9.3}parameterizing the start.config}{4}{subsection.9.3}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {9.4}Packaging}{4}{subsection.9.4}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {9.5}Todo}{5}{subsection.9.5}}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.dvi b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.dvi
new file mode 100644
index 000000000..3f8050885
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.dvi differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.log b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.log
new file mode 100644
index 000000000..e111a3381
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.log
@@ -0,0 +1,363 @@
+This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/Debian) (preloaded format=pdflatex 2019.6.19) 19 JUN 2019 12:21
+entering extended mode
+ restricted \write18 enabled.
+ %&-line parsing enabled.
+**development
+(./development.tex
+LaTeX2e <2016/02/01>
+Babel <3.9q> and hyphenation patterns for 3 language(s) loaded.
+(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
+Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
+(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo
+File: size12.clo 2014/09/29 v1.4h Standard LaTeX file (size option)
+)
+\c@part=\count79
+\c@section=\count80
+\c@subsection=\count81
+\c@subsubsection=\count82
+\c@paragraph=\count83
+\c@subparagraph=\count84
+\c@figure=\count85
+\c@table=\count86
+\abovecaptionskip=\skip41
+\belowcaptionskip=\skip42
+\bibindent=\dimen102
+)
+(/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty
+Package: geometry 2010/09/12 v5.6 Page Geometry
+
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty
+Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
+\KV@toks@=\toks14
+)
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifpdf.sty
+Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO)
+Package ifpdf Info: pdfTeX in PDF mode is detected.
+)
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifvtex.sty
+Package: ifvtex 2010/03/01 v1.5 Detect VTeX and its facilities (HO)
+Package ifvtex Info: VTeX not detected.
+)
+(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty
+Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
+)
+\Gm@cnth=\count87
+\Gm@cntv=\count88
+\c@Gm@tempcnt=\count89
+\Gm@bindingoffset=\dimen103
+\Gm@wd@mp=\dimen104
+\Gm@odd@mp=\dimen105
+\Gm@even@mp=\dimen106
+\Gm@layoutwidth=\dimen107
+\Gm@layoutheight=\dimen108
+\Gm@layouthoffset=\dimen109
+\Gm@layoutvoffset=\dimen110
+\Gm@dimlist=\toks15
+)
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
+Package: hyperref 2012/11/06 v6.83m Hypertext links for LaTeX
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty
+Package: hobsub-hyperref 2012/05/28 v1.13 Bundle oberdiek, subset hyperref (HO)
+
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty
+Package: hobsub-generic 2012/05/28 v1.13 Bundle oberdiek, subset generic (HO)
+Package: hobsub 2012/05/28 v1.13 Construct package bundles (HO)
+Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO)
+Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO)
+Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
+Package ifluatex Info: LuaTeX not detected.
+Package hobsub Info: Skipping package `ifvtex' (already loaded).
+Package: intcalc 2007/09/27 v1.1 Expandable calculations with integers (HO)
+Package hobsub Info: Skipping package `ifpdf' (already loaded).
+Package: etexcmds 2011/02/16 v1.5 Avoid name clashes with e-TeX commands (HO)
+Package etexcmds Info: Could not find \expanded.
+(etexcmds) That can mean that you are not using pdfTeX 1.50 or
+(etexcmds) that some package has redefined \expanded.
+(etexcmds) In the latter case, load this package earlier.
+Package: kvsetkeys 2012/04/25 v1.16 Key value parser (HO)
+Package: kvdefinekeys 2011/04/07 v1.3 Define keys (HO)
+Package: pdftexcmds 2011/11/29 v0.20 Utility functions of pdfTeX for LuaTeX (HO
+)
+Package pdftexcmds Info: LuaTeX not detected.
+Package pdftexcmds Info: \pdf@primitive is available.
+Package pdftexcmds Info: \pdf@ifprimitive is available.
+Package pdftexcmds Info: \pdfdraftmode found.
+Package: pdfescape 2011/11/25 v1.13 Implements pdfTeX's escape features (HO)
+Package: bigintcalc 2012/04/08 v1.3 Expandable calculations on big integers (HO
+)
+Package: bitset 2011/01/30 v1.1 Handle bit-vector datatype (HO)
+Package: uniquecounter 2011/01/30 v1.2 Provide unlimited unique counter (HO)
+)
+Package hobsub Info: Skipping package `hobsub' (already loaded).
+Package: letltxmacro 2010/09/02 v1.4 Let assignment for LaTeX macros (HO)
+Package: hopatch 2012/05/28 v1.2 Wrapper for package hooks (HO)
+Package: xcolor-patch 2011/01/30 xcolor patch
+Package: atveryend 2011/06/30 v1.8 Hooks at the very end of document (HO)
+Package atveryend Info: \enddocument detected (standard20110627).
+Package: atbegshi 2011/10/05 v1.16 At begin shipout hook (HO)
+Package: refcount 2011/10/16 v3.4 Data extraction from label references (HO)
+Package: hycolor 2011/01/30 v1.7 Color options for hyperref/bookmark (HO)
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/auxhook.sty
+Package: auxhook 2011/03/04 v1.3 Hooks for auxiliary files (HO)
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty
+Package: kvoptions 2011/06/30 v3.11 Key value format for package options (HO)
+)
+\@linkdim=\dimen111
+\Hy@linkcounter=\count90
+\Hy@pagecounter=\count91
+
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def
+File: pd1enc.def 2012/11/06 v6.83m Hyperref: PDFDocEncoding definition (HO)
+)
+\Hy@SavedSpaceFactor=\count92
+
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg
+File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive
+)
+Package hyperref Info: Option `colorlinks' set `true' on input line 4319.
+Package hyperref Info: Hyper figures OFF on input line 4443.
+Package hyperref Info: Link nesting OFF on input line 4448.
+Package hyperref Info: Hyper index ON on input line 4451.
+Package hyperref Info: Plain pages OFF on input line 4458.
+Package hyperref Info: Backreferencing OFF on input line 4463.
+Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
+Package hyperref Info: Bookmarks ON on input line 4688.
+\c@Hy@tempcnt=\count93
+
+(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty
+\Urlmuskip=\muskip10
+Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
+)
+LaTeX Info: Redefining \url on input line 5041.
+\XeTeXLinkMargin=\dimen112
+\Fld@menulength=\count94
+\Field@Width=\dimen113
+\Fld@charsize=\dimen114
+Package hyperref Info: Hyper figures OFF on input line 6295.
+Package hyperref Info: Link nesting OFF on input line 6300.
+Package hyperref Info: Hyper index ON on input line 6303.
+Package hyperref Info: backreferencing OFF on input line 6310.
+Package hyperref Info: Link coloring ON on input line 6313.
+Package hyperref Info: Link coloring with OCG OFF on input line 6320.
+Package hyperref Info: PDF/A mode OFF on input line 6325.
+LaTeX Info: Redefining \ref on input line 6365.
+LaTeX Info: Redefining \pageref on input line 6369.
+\Hy@abspage=\count95
+\c@Item=\count96
+\c@Hfootnote=\count97
+)
+
+Package hyperref Message: Driver (autodetected): hpdftex.
+
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
+File: hpdftex.def 2012/11/06 v6.83m Hyperref driver for pdfTeX
+\Fld@listcount=\count98
+\c@bookmark@seq@number=\count99
+
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty
+Package: rerunfilecheck 2011/04/15 v1.7 Rerun checks for auxiliary files (HO)
+Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2
+82.
+)
+\Hy@SectionHShift=\skip43
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/bookmark.sty
+Package: bookmark 2011/12/02 v1.24 PDF bookmarks (HO)
+
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/bkm-pdftex.def
+File: bkm-pdftex.def 2011/12/02 v1.24 bookmark driver for pdfTeX (HO)
+\BKM@id=\count100
+))
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.sty
+Package: csquotes 2016/01/31 v5.1g context-sensitive quotations (JAW)
+
+(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty
+Package: etoolbox 2015/08/02 v2.2a e-TeX tools for LaTeX (JAW)
+\etb@tempcnta=\count101
+)
+\csq@reset=\count102
+\csq@gtype=\count103
+\csq@glevel=\count104
+\csq@qlevel=\count105
+\csq@maxlvl=\count106
+\csq@tshold=\count107
+\csq@ltx@everypar=\toks16
+
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.def
+File: csquotes.def 2016/01/31 v5.1g csquotes generic definitions (JAW)
+)
+Package csquotes Info: Trying to load configuration file 'csquotes.cfg'...
+Package csquotes Info: ... configuration file loaded successfully.
+
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.cfg
+File: csquotes.cfg
+)
+Package csquotes Info: Enabling multilingual quotes.
+Package csquotes Info: Redefining alias 'english' -> 'english/american'.
+)
+Package csquotes Info: Checking for multilingual support...
+Package csquotes Info: ... none found.
+
+
+Package csquotes Warning: No multilingual support.
+(csquotes) Cannot enable multilingual quotes on input line 7.
+
+(./development.aux)
+\openout1 = `development.aux'.
+
+LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 7.
+LaTeX Font Info: ... okay on input line 7.
+LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 7.
+LaTeX Font Info: ... okay on input line 7.
+LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 7.
+LaTeX Font Info: ... okay on input line 7.
+LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 7.
+LaTeX Font Info: ... okay on input line 7.
+LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 7.
+LaTeX Font Info: ... okay on input line 7.
+LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 7.
+LaTeX Font Info: ... okay on input line 7.
+LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 7.
+LaTeX Font Info: ... okay on input line 7.
+
+*geometry* driver: auto-detecting
+*geometry* detected driver: pdftex
+*geometry* verbose mode - [ preamble ] result:
+* driver: pdftex
+* paper: a4paper
+* layout:
+* layoutoffset:(h,v)=(0.0pt,0.0pt)
+* modes:
+* h-part:(L,W,R)=(56.9055pt, 483.69684pt, 56.90553pt)
+* v-part:(T,H,B)=(56.9055pt, 731.23582pt, 56.90552pt)
+* \paperwidth=597.50787pt
+* \paperheight=845.04684pt
+* \textwidth=483.69684pt
+* \textheight=731.23582pt
+* \oddsidemargin=-15.36449pt
+* \evensidemargin=-15.36449pt
+* \topmargin=-52.36449pt
+* \headheight=12.0pt
+* \headsep=25.0pt
+* \topskip=12.0pt
+* \footskip=30.0pt
+* \marginparwidth=44.0pt
+* \marginparsep=10.0pt
+* \columnsep=10.0pt
+* \skip\footins=10.8pt plus 4.0pt minus 2.0pt
+* \hoffset=0.0pt
+* \voffset=0.0pt
+* \mag=1000
+* \@twocolumnfalse
+* \@twosidefalse
+* \@mparswitchfalse
+* \@reversemarginfalse
+* (1in=72.27pt=25.4mm, 1cm=28.453pt)
+
+\AtBeginShipoutBox=\box26
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty
+Package: color 2016/01/03 v1.1b Standard LaTeX Color (DPC)
+
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/color.cfg
+File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive
+)
+Package color Info: Driver file: pdftex.def on input line 143.
+
+(/usr/share/texlive/texmf-dist/tex/latex/pdftex-def/pdftex.def
+File: pdftex.def 2011/05/27 v0.06d Graphics/color for pdfTeX
+\Gread@gobject=\count108
+
+(/usr/share/texlive/texmf-dist/tex/context/base/supp-pdf.mkii
+[Loading MPS to PDF converter (version 2006.09.02).]
+\scratchcounter=\count109
+\scratchdimen=\dimen115
+\scratchbox=\box27
+\nofMPsegments=\count110
+\nofMParguments=\count111
+\everyMPshowfont=\toks17
+\MPscratchCnt=\count112
+\MPscratchDim=\dimen116
+\MPnumerator=\count113
+\makeMPintoPDFobject=\count114
+\everyMPtoPDFconversion=\toks18
+)))
+Package hyperref Info: Link coloring ON on input line 7.
+ (/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
+Package: nameref 2012/10/27 v2.43 Cross-referencing by name of section
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty
+Package: gettitlestring 2010/12/03 v1.4 Cleanup title references (HO)
+)
+\c@section@level=\count115
+)
+LaTeX Info: Redefining \ref on input line 7.
+LaTeX Info: Redefining \pageref on input line 7.
+LaTeX Info: Redefining \nameref on input line 7.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <14.4> on input line 11.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <7> on input line 11.
+
+
+LaTeX Warning: No \author given.
+
+[1
+
+{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] (./development.toc
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <12> on input line 10.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <8> on input line 10.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <6> on input line 10.
+)
+\tf@toc=\write3
+\openout3 = `development.toc'.
+
+pdfTeX warning (ext4): destination with the same identifier (name{page.1}) has
+been already used, duplicate ignored
+
+ \relax
+l.20 \newpage
+ [1]
+LaTeX Font Info: Try loading font information for OMS+cmr on input line 29.
+ (/usr/share/texlive/texmf-dist/tex/latex/base/omscmr.fd
+File: omscmr.fd 2014/09/29 v2.5h Standard LaTeX font definitions
+)
+LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <12> not available
+(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 29.
+
+[2] [3]
+Package atveryend Info: Empty hook `BeforeClearDocument' on input line 181.
+ [4] [5]
+Package atveryend Info: Empty hook `AfterLastShipout' on input line 181.
+ (./development.aux)
+Package atveryend Info: Executing hook `AtVeryEndDocument' on input line 181.
+Package atveryend Info: Empty hook `AtEndAfterFileList' on input line 181.
+Package atveryend Info: Empty hook `AtVeryVeryEnd' on input line 181.
+ )
+Here is how much of TeX's memory you used:
+ 6398 strings out of 494953
+ 94524 string characters out of 6180977
+ 193703 words of memory out of 5000000
+ 9643 multiletter control sequences out of 15000+600000
+ 9324 words of font info for 33 fonts, out of 8000000 for 9000
+ 14 hyphenation exceptions out of 8191
+ 29i,6n,30p,928b,486s stack positions out of 5000i,500n,10000p,200000b,80000s
+
+Output written on development.pdf (6 pages, 86437 bytes).
+PDF statistics:
+ 133 PDF objects out of 1000 (max. 8388607)
+ 117 compressed objects within 2 object streams
+ 21 named destinations out of 1000 (max. 500000)
+ 113 words of extra memory for PDF output out of 10000 (max. 10000000)
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.out.ps b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.out.ps
new file mode 100644
index 000000000..746f06ee3
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.out.ps
@@ -0,0 +1,61 @@
+%!
+/pdfmark where{pop}
+{/globaldict where{pop globaldict}{userdict}ifelse/pdfmark/cleartomark load put}
+ifelse
+[
+/Title(Introduction)
+/Action/GoTo/Dest(section.1)cvn
+/OUT pdfmark
+[
+/Title(Developer Software Prerequisits)
+/Action/GoTo/Dest(section.2)cvn
+/OUT pdfmark
+[
+/Title(Getting Labtainers from Subversion)
+/Action/GoTo/Dest(section.3)cvn
+/OUT pdfmark
+[
+/Title(Testing and Running Existing Labs)
+/Action/GoTo/Dest(section.4)cvn
+/OUT pdfmark
+[
+/Title(Overview of Labtainer Elements)
+/Action/GoTo/Dest(section.5)cvn
+/OUT pdfmark
+[
+/Title(Control Flow)
+/Action/GoTo/Dest(section.6)cvn
+/OUT pdfmark
+[
+/Title(Automation and Distributions)
+/Action/GoTo/Dest(section.7)cvn
+/OUT pdfmark
+[
+/Title(installation sizes)
+/Action/GoTo/Dest(section.8)cvn
+/OUT pdfmark
+[
+/Title(Notes)
+/Count -5
+/Action/GoTo/Dest(section.9)cvn
+/OUT pdfmark
+[
+/Title(Race condition on checklocal.sh output)
+/Action/GoTo/Dest(subsection.9.1)cvn
+/OUT pdfmark
+[
+/Title(temporal logic considerations)
+/Action/GoTo/Dest(subsection.9.2)cvn
+/OUT pdfmark
+[
+/Title(parameterizing the start.config)
+/Action/GoTo/Dest(subsection.9.3)cvn
+/OUT pdfmark
+[
+/Title(Packaging)
+/Action/GoTo/Dest(subsection.9.4)cvn
+/OUT pdfmark
+[
+/Title(Todo)
+/Action/GoTo/Dest(subsection.9.5)cvn
+/OUT pdfmark
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.pdf b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.pdf
new file mode 100644
index 000000000..f78eaeabe
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.pdf differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.tex b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.tex
new file mode 100644
index 000000000..f3d002575
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.tex
@@ -0,0 +1,181 @@
+\documentclass[12pt]{article}
+\usepackage{geometry}
+\geometry{a4paper, total={170mm,257mm},left=20mm, top=20mm,}
+\usepackage[colorlinks=true,linkcolor=blue,urlcolor=black]{hyperref}
+\usepackage{bookmark}
+\usepackage[autostyle, english = american]{csquotes}
+\begin{document}
+\begin{titlepage}
+\title {Labtainer Framework Development Guide}
+\maketitle
+
+\vspace{2.0in}
+This document was created by United States Government employees at
+The Center for Cybersecurity and Cyber Operations (C3O) at the Naval Postgraduate School NPS.
+Please note that within the United States, copyright protection is not available for any works created
+by United States Government employees, pursuant to Title 17 United States Code Section 105.
+This document is in the public domain and is not subject to copyright.
+\end{titlepage}
+\tableofcontents
+\newpage
+\section {Introduction}
+This document is intended for use by developers who maintain the
+Labtainer framework. It does not address lab creation, which is
+covered in the \textit {Labtainers Lab Designer User Guide}.
+
+
+\section{Developer Software Prerequisits}
+\begin {itemize}
+\item Subversion
+\item Latex (texlive-full)
+\end {itemize}
+
+
+\section{Getting Labtainers from Subversion}
+svn co https://tor.ern.nps.edu/svn/proj/labtainer
+Change directory to trunk/setup-scripts and run ./after-checkout.sh. The will build the PDF lab
+manuals so that you can reference the manuals while you test or otherwise reference
+existing labs. (Please follow the lab manual and report discrepancies!)
+It will also create any executables required by the framework.
+Then run ./pull-all.sh to pull all the baseline images (so that your running of
+existing labs is more akin to what students and instructors do so we can better test that).
+
+\section{Testing and Running Existing Labs}
+There are situations where you will run an existing lab, e.g., to test it, or to
+observe some example. When running labs, please refer to the lab manuals
+so that they get reivewed and tested by different people. Also, please first delete
+the lab using trunk/setup\_scripts/removelab.sh to ensure that you are running the latest
+version of the published lab. If you find the lab to be broken, e.g., missing a file, please
+attempt to run "rebuild.py" on the lab. Report these findings to the lab author. And always
+run removelab.sh after you have run an existing lab via rebuild.py. Again, the goal is to
+force ourselves to run the distributed labs unless we have specific reasons to do otherwise.
+
+\section{Overview of Labtainer Elements}
+The Labtainer framework implementation is primarily python scripts. A number of the
+top level scripts share functions found in bin/labutils.py. The
+top level scripts are organized as follows:
+
+\begin{itemize}
+\item Student {\tt labtainers} (start) and {\tt stoplab} -- In the labtainers-student/bin directory, these run on the
+Linux host and manage the pulling, starting and stopping of containers. They also coordinate
+collection of student artifacts.
+\item Student container scripts -- In the labtainers-student/lab\_bin directory, these execute on
+containers, e.g., to hook bash and parameterize containers.
+\item Instructor {\tt gradelab} and {\tt stopgrader}-- Push student artifacts onto grader container and get assessment results.
+\item Instructor container scripts -- perform grading functions.
+\item Developer building -- rebuild.py in labtainers-student/bin and labtainers-instructor/bin.
+\item Publishing labs -- labtainers/distrib/publish.py
+\item Base Labtainer images -- /trunk/scripts/designer/bin, create and publish the base images.
+\item VM appliances -- /trunk/host\_scripts, update and publish VM appliances as OVA files for
+VirtualBox and VMWare.
+\item Regression testing of grading functions is performed by labtainer-instructor/regress.py.
+Expected results are stored in the labtainer/testsets directory.
+\item Regression testing of labs and grading combined: scripts in trunk/testsets/bin; data sets
+are not distributed, they are in labtainer/simlab/
+\end{itemize}
+
+\section {Control Flow}
+Student scripts, e.g., start.py, run from the trunk/scripts/labtainer-student directory.
+That directory also contains the bin/labutils.py, which contains most of the framework
+functions.
+
+When a student container is first started "docker exec" is used
+to run parameterize.sh on the container.
+
+That script also invokes hookBash.sh, which adds the bash
+sdtin/stout capturing hook, and adds the startup.sh call
+into the .profile.
+
+The startup.sh uses a lock to control which
+terminal displays the instructions or grading. In practice most
+instructions are now pdf files.
+The startup.sh invoked by student will source a student\_startup.sh if present.
+
+\section{Automation and Distributions}
+The Labtainer framework is distributed via the c3o website as a tar file, or, optionally a
+VM applicance (both VMWare and VirtualBox). The Docker images are distributed via the Docker Hub.
+
+The labtainer/distrib/mkdist.sh script runs on a Linux VM hosted on windows or Linux, and creates the distribution tar
+and copies it into a shared folder. The mk-devel.sh script makes the developers version of the tar.
+From that shared folder, the two tar files are copied to the
+\begin{verbatim}
+\\my.nps.edu@SSL\DavWWWRoot\webdav\c30-staging\document\_library"
+\end{verbatim}
+\noindent and then "Publish to Live" is
+performed on the Liferay site.
+
+Two prepackaged VMs are maintained: one for VirtualBox, and one for VMWare. Each include
+their respective guest additions. The VMs are maintained on a native Linux system using command line
+utilities, e.g., VBoxManage. The VMs are rigged to update labtainers, including a pull of
+baseline images, on each boot until the first lab is commenced. Scripts named "export*" are
+used to created the appliance files. The scripts re-import into test images, which must be
+manually tested. The WinSCP script pushes new applicance images to the CyberCIEGE download
+directory on the C3O web server. (Wine and WinSCP must be installed on the Linux host that
+manages the VMs.
+
+New baseline images are created using scripts/designer/bin/create\_all.sh. Note its comment
+about deleting all docker images first. When new baselines are created, use the labtainer-scripts
+on the native Linux system to update the VM appliances so they contain the latest baseline images.
+After the VM starts and updates the baseline images, use:
+\begin{verbatim}
+sudo dd if=/dev/zero of=/emptyfile bs=1M
+sudo rm -fr /emptyfile
+\end{verbatim}
+\noindent to zero unused space and then run
+\begin{verbatim}
+./poweroffVB.sh
+./compact.sh
+\end{verbatim}
+\noindent to compact the VM image. Then export it:
+\begin{verbatim}
+./exportVB.sh
+\end{verbatim}
+\noindent This will create the appliance OVA image, and will create a test
+VM from that appliance. The test VM will start. Use that to run ad-hoc
+tests.
+
+Do the same for vmware.
+
+Then push the images to the web server
+
+The appliances automatically update the baselines and the Labtainer scripts on boot, so there
+is only really advantage to doing this for baseline changes, since they take a while to download.
+After running the poweron/poweroff scripts, then run the exportVM.sh to
+
+\section {installation sizes}
+An initial install, including the base images, requires about 4GB. Installing a larger lab,
+e.g., snort, requires an additional 1GB. Running bufoverflow added 22M.
+
+
+\section {Notes}
+\subsection {Race condition on checklocal.sh output}
+If an mynotify.py event causes an output from checklocal.py, that may conflict with
+concurrent output from checklocal.py resulting from some program/script running. In
+theory, the program/script should complete its run of checklocal before the program/script
+actually gets to access the file that triggers a mynotify watch. So, the latter's output
+to the timestamped file is appended. Further, the mynotify.py looks for an existing timestamped
+file, and if not found, looks for one from the previous second. This hack is an attempt to
+keep the outputs merged. It will fail if the access does not happen within a second of the
+program start. See the acl lab.
+
+\subsection {temporal logic considerations}
+When evaluating results from logfiles containing timestamps use FILE\_TS or FILE\_TS\_REGEX
+to ensure you get timestamped values for only matching records. Reliance on goals.config to
+matchany can result in timestamped results that don't corrolate to the desired record.
+
+\subsection {parameterizing the start.config}
+A copy of the parameterized version of start.config is placed into
+labtainer-student/.tmp//. This ensures that subsequent runs of the lab always
+have the same psuedo random values.
+
+\subsection {Packaging}
+The framework has not yet been adapted to use Linux package managers.
+Currently, scripts are run from a workspace directory and python
+paths are managed relatively between scripts.
+
+\subsection{Todo}
+Change smoke test to look for email in expected results and set that as the email before starting a lab.
+Validation should catch results.config naming of non-existent container.
+
+
+\end{document}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.toc b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.toc
new file mode 100644
index 000000000..cc41b3da7
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/development.toc
@@ -0,0 +1,14 @@
+\contentsline {section}{\numberline {1}Introduction}{2}{section.1}
+\contentsline {section}{\numberline {2}Developer Software Prerequisits}{2}{section.2}
+\contentsline {section}{\numberline {3}Getting Labtainers from Subversion}{2}{section.3}
+\contentsline {section}{\numberline {4}Testing and Running Existing Labs}{2}{section.4}
+\contentsline {section}{\numberline {5}Overview of Labtainer Elements}{2}{section.5}
+\contentsline {section}{\numberline {6}Control Flow}{3}{section.6}
+\contentsline {section}{\numberline {7}Automation and Distributions}{3}{section.7}
+\contentsline {section}{\numberline {8}installation sizes}{4}{section.8}
+\contentsline {section}{\numberline {9}Notes}{4}{section.9}
+\contentsline {subsection}{\numberline {9.1}Race condition on checklocal.sh output}{4}{subsection.9.1}
+\contentsline {subsection}{\numberline {9.2}temporal logic considerations}{4}{subsection.9.2}
+\contentsline {subsection}{\numberline {9.3}parameterizing the start.config}{4}{subsection.9.3}
+\contentsline {subsection}{\numberline {9.4}Packaging}{4}{subsection.9.4}
+\contentsline {subsection}{\numberline {9.5}Todo}{5}{subsection.9.5}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/git.txt b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/git.txt
new file mode 100644
index 000000000..45dcff170
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/git.txt
@@ -0,0 +1,5 @@
+DO NOT git svn fetch
+git svn rebase
+### IF NEEDED ? git pull https://github.com/mfthomps/Labtainers
+git push origin master
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/tars b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/tars
new file mode 100644
index 000000000..d21860178
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/tars
@@ -0,0 +1,21 @@
+Large compressible file sets, e.g., system programs with a lot of files, or
+big password crackign files, can be managed using lab directories ending in
+"_tar". for example trunk/labs//m_tar might contain several large
+files. These files are kept in svn as descrete files (the tar is not in svn).
+The image build process will tar (and compress) all such files into
+a "m_tar.tar" The designer must direct the Dockerfile to "Add" this file
+to the desired destination within the appropriate container. (The name
+of the tar directory has no semantics beyond selecting the name of the
+tar file and directing the build to tar its content.) The build function
+WILL DELETE any .tar files in such directores before performing the tar.
+
+The mkdist function will create a tar, but will also remove all other files
+from its temporary copy of the _tar directory. In other words, only tar files
+will appear in the distribution tar. NOTE: this makes a "rebuild" of a
+distributed repo precarious. As such, the build function will not do anything
+if the only file in a _tar directory is the tarball.
+
+The home_tar directory has distinct semantics. Files that originate from
+there will not be collected in studnet artifacts SO DO NOT PUT modifiable files
+there if you student mods are graded or germane to the lab. A home_tar.list
+file is created in config & referenced when zipping up home.
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/testing.md b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/testing.md
new file mode 100644
index 000000000..949323836
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/development/testing.md
@@ -0,0 +1,70 @@
+Labtainer Regression Testing Guide
+==================================
+
+This manual is intended for use by lab designers wanting
+to perform regression testing, i.e., verify labs previously
+created will have the same result (grades.txt) after code changes
+(for example code changes to instructor's side related to grading, etc.)
+
+Regression Testing root (TESTSETS_ROOT) directory will be located in
+directory ../../../testsets/labs (this is relative to the script
+regresstest.py that is located in ...../labtainer/trunk/scripts/labtainer-instructor
+
+Under the TESTSETS_ROOT directory, there will be directory for each labs.
+In each of the lab directories, there will be zip files and corresponding '.grades.txt'
+
+The regresstest.py script will use the zip files for each lab,
+spawns the corresponding instructor's containers for the lab,
+the zip files are copied into the instructor's container,
+then the 'instructor.py' script is ran to create/generate the '.grades.txt'
+The generated grade file is compared to the one stored in the TESTSETS_ROOT for that lab,
+if they are the same, then the regression test for that lab is considered successful.
+otherwise, it is considered as failure and regresstest.py script will terminate.
+
+1. Preparing the test sets or Populating the TESTSETS_ROOT directory
+
+ The zip files that are stored in the TESTSETS_ROOT directory are obtained
+by running the lab as a student, i.e., performing the tasks required by the lab
+as a student. Once the container for the lab is stopped, the zip files for the lab
+is created (and stored in the host transfer directory).
+
+ The zip files must be copied to the TESTSETS_ROOT directory.
+
+Note: It might be easier to perform each task for a lab as separate user (i.e., using
+ different e-mail addresses).
+ For example: for the formatstring lab, crash the vulnerable program as joe@nps.edu
+ stop the container and save the zip file
+ then, modify the secret1 value as ann@nps.edu
+ stop the container and save the zip file
+ The zip file will have the e-mail address as part of the name
+
+2. Creating the 'GOLD' grades.txt file
+
+ Once the zip files are created from step 1 above, perform the grading using the
+corresponding instructor's container for the lab (by running the 'instructor.py' script)
+
+The 'instructor.py' script will create the '.grades.txt' file for each 'student'
+corresponding to the e-mail addresses found as part of the zip files.
+
+Verify that the grades file generated is correct.
+Once the grades file is verified as correct, when the instructor's container is stopped,
+the grades file (.grades.txt) is copied to the host transfer directory.
+
+This grades file must then be copied into the TESTSETS_ROOT directory for that lab
+and will be treated as the 'GOLD' grades.txt file, i.e., when regresstest.py is re-run
+(after some code changes), the generated grades file will be compared against that GOLD file
+
+3. Running Regression Testing
+
+ To run the regression testing (if there is any change to the code), it is simply done
+by running the 'regresstest.py' script.
+
+The regresstest.py script maybe given one argument (reflecting a specific labname) to test
+or no argument (in which case all labs will be tested).
+
+
+
+
+
+
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/Makefile b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/Makefile
new file mode 100644
index 000000000..fb422e0e0
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/Makefile
@@ -0,0 +1,6 @@
+labtainer-instructor.pdf: labtainer-instructor.tex
+ latex labtainer-instructor
+ pdflatex labtainer-instructor
+clean:
+ rm -fr auto
+ rm -fr labtainer-instructor.aux labtainer-instructor.pdf *.ps *.dvi
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.aux b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.aux
new file mode 100644
index 000000000..149233bdc
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.aux
@@ -0,0 +1,36 @@
+\relax
+\providecommand\hyper@newdestlabel[2]{}
+\providecommand\BKM@entry[2]{}
+\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
+\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
+\global\let\oldcontentsline\contentsline
+\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
+\global\let\oldnewlabel\newlabel
+\gdef\newlabel#1#2{\newlabelxx{#1}#2}
+\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
+\AtEndDocument{\ifx\hyper@anchor\@undefined
+\let\contentsline\oldcontentsline
+\let\newlabel\oldnewlabel
+\fi}
+\fi}
+\global\let\hyper@last\relax
+\gdef\HyperFirstAtBeginDocument#1{#1}
+\providecommand\HyField@AuxAddToFields[1]{}
+\providecommand\HyField@AuxAddToCoFields[2]{}
+\BKM@entry{id=1,dest={73656374696F6E2E31},srcline={12}}{496E74726F64756374696F6E}
+\BKM@entry{id=2,dest={73756273656374696F6E2E312E31},srcline={34}}{41737369676E696E672061204C6162}
+\BKM@entry{id=3,dest={73756273656374696F6E2E312E32},srcline={49}}{417373657373696E672061204C6162}
+\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{1}{section.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Assigning a Lab}{1}{subsection.1.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Assessing a Lab}{1}{subsection.1.2}}
+\BKM@entry{id=4,dest={73756273756273656374696F6E2E312E322E31},srcline={97}}{5265766965772061727469666163742064657461696C73}
+\BKM@entry{id=5,dest={73656374696F6E2E32},srcline={120}}{4D616E6167696E67204C61627461696E657220496E7374616C6C6174696F6E7320616E642055706461746573}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {1.2.1}Review artifact details}{2}{subsubsection.1.2.1}}
+\BKM@entry{id=6,dest={73756273656374696F6E2E322E31},srcline={140}}{53756767657374696F6E7320666F722073747564656E7420776F726B666C6F77}
+\@writefile{toc}{\contentsline {section}{\numberline {2}Managing Labtainer Installations and Updates}{3}{section.2}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Suggestions for student workflow}{3}{subsection.2.1}}
+\BKM@entry{id=7,dest={617070656E6469782E41},srcline={150}}{4C4D532041737369676E6D656E7420436F6C6C656374696F6E}
+\BKM@entry{id=8,dest={73756273656374696F6E2E412E31},srcline={152}}{53616B6169}
+\@writefile{toc}{\contentsline {section}{\numberline {A}\\LMS Assignment Collection}{4}{appendix.A}}
+\newlabel{lms collection}{{A}{4}{\\LMS Assignment Collection}{appendix.A}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {A.1}Sakai}{4}{subsection.A.1}}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.dvi b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.dvi
new file mode 100644
index 000000000..5d44fe84a
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.dvi differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.log b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.log
new file mode 100644
index 000000000..553ba475e
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.log
@@ -0,0 +1,362 @@
+This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/Debian) (preloaded format=pdflatex 2019.6.19) 19 JUN 2019 12:22
+entering extended mode
+ restricted \write18 enabled.
+ %&-line parsing enabled.
+**labtainer-instructor
+(./labtainer-instructor.tex
+LaTeX2e <2016/02/01>
+Babel <3.9q> and hyphenation patterns for 3 language(s) loaded.
+(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
+Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
+(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo
+File: size12.clo 2014/09/29 v1.4h Standard LaTeX file (size option)
+)
+\c@part=\count79
+\c@section=\count80
+\c@subsection=\count81
+\c@subsubsection=\count82
+\c@paragraph=\count83
+\c@subparagraph=\count84
+\c@figure=\count85
+\c@table=\count86
+\abovecaptionskip=\skip41
+\belowcaptionskip=\skip42
+\bibindent=\dimen102
+)
+(/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty
+Package: geometry 2010/09/12 v5.6 Page Geometry
+
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty
+Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
+\KV@toks@=\toks14
+)
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifpdf.sty
+Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO)
+Package ifpdf Info: pdfTeX in PDF mode is detected.
+)
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifvtex.sty
+Package: ifvtex 2010/03/01 v1.5 Detect VTeX and its facilities (HO)
+Package ifvtex Info: VTeX not detected.
+)
+(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty
+Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
+)
+\Gm@cnth=\count87
+\Gm@cntv=\count88
+\c@Gm@tempcnt=\count89
+\Gm@bindingoffset=\dimen103
+\Gm@wd@mp=\dimen104
+\Gm@odd@mp=\dimen105
+\Gm@even@mp=\dimen106
+\Gm@layoutwidth=\dimen107
+\Gm@layoutheight=\dimen108
+\Gm@layouthoffset=\dimen109
+\Gm@layoutvoffset=\dimen110
+\Gm@dimlist=\toks15
+)
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
+Package: hyperref 2012/11/06 v6.83m Hypertext links for LaTeX
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty
+Package: hobsub-hyperref 2012/05/28 v1.13 Bundle oberdiek, subset hyperref (HO)
+
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty
+Package: hobsub-generic 2012/05/28 v1.13 Bundle oberdiek, subset generic (HO)
+Package: hobsub 2012/05/28 v1.13 Construct package bundles (HO)
+Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO)
+Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO)
+Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
+Package ifluatex Info: LuaTeX not detected.
+Package hobsub Info: Skipping package `ifvtex' (already loaded).
+Package: intcalc 2007/09/27 v1.1 Expandable calculations with integers (HO)
+Package hobsub Info: Skipping package `ifpdf' (already loaded).
+Package: etexcmds 2011/02/16 v1.5 Avoid name clashes with e-TeX commands (HO)
+Package etexcmds Info: Could not find \expanded.
+(etexcmds) That can mean that you are not using pdfTeX 1.50 or
+(etexcmds) that some package has redefined \expanded.
+(etexcmds) In the latter case, load this package earlier.
+Package: kvsetkeys 2012/04/25 v1.16 Key value parser (HO)
+Package: kvdefinekeys 2011/04/07 v1.3 Define keys (HO)
+Package: pdftexcmds 2011/11/29 v0.20 Utility functions of pdfTeX for LuaTeX (HO
+)
+Package pdftexcmds Info: LuaTeX not detected.
+Package pdftexcmds Info: \pdf@primitive is available.
+Package pdftexcmds Info: \pdf@ifprimitive is available.
+Package pdftexcmds Info: \pdfdraftmode found.
+Package: pdfescape 2011/11/25 v1.13 Implements pdfTeX's escape features (HO)
+Package: bigintcalc 2012/04/08 v1.3 Expandable calculations on big integers (HO
+)
+Package: bitset 2011/01/30 v1.1 Handle bit-vector datatype (HO)
+Package: uniquecounter 2011/01/30 v1.2 Provide unlimited unique counter (HO)
+)
+Package hobsub Info: Skipping package `hobsub' (already loaded).
+Package: letltxmacro 2010/09/02 v1.4 Let assignment for LaTeX macros (HO)
+Package: hopatch 2012/05/28 v1.2 Wrapper for package hooks (HO)
+Package: xcolor-patch 2011/01/30 xcolor patch
+Package: atveryend 2011/06/30 v1.8 Hooks at the very end of document (HO)
+Package atveryend Info: \enddocument detected (standard20110627).
+Package: atbegshi 2011/10/05 v1.16 At begin shipout hook (HO)
+Package: refcount 2011/10/16 v3.4 Data extraction from label references (HO)
+Package: hycolor 2011/01/30 v1.7 Color options for hyperref/bookmark (HO)
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/auxhook.sty
+Package: auxhook 2011/03/04 v1.3 Hooks for auxiliary files (HO)
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty
+Package: kvoptions 2011/06/30 v3.11 Key value format for package options (HO)
+)
+\@linkdim=\dimen111
+\Hy@linkcounter=\count90
+\Hy@pagecounter=\count91
+
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def
+File: pd1enc.def 2012/11/06 v6.83m Hyperref: PDFDocEncoding definition (HO)
+)
+\Hy@SavedSpaceFactor=\count92
+
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg
+File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive
+)
+Package hyperref Info: Option `colorlinks' set `true' on input line 4319.
+Package hyperref Info: Hyper figures OFF on input line 4443.
+Package hyperref Info: Link nesting OFF on input line 4448.
+Package hyperref Info: Hyper index ON on input line 4451.
+Package hyperref Info: Plain pages OFF on input line 4458.
+Package hyperref Info: Backreferencing OFF on input line 4463.
+Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
+Package hyperref Info: Bookmarks ON on input line 4688.
+\c@Hy@tempcnt=\count93
+
+(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty
+\Urlmuskip=\muskip10
+Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
+)
+LaTeX Info: Redefining \url on input line 5041.
+\XeTeXLinkMargin=\dimen112
+\Fld@menulength=\count94
+\Field@Width=\dimen113
+\Fld@charsize=\dimen114
+Package hyperref Info: Hyper figures OFF on input line 6295.
+Package hyperref Info: Link nesting OFF on input line 6300.
+Package hyperref Info: Hyper index ON on input line 6303.
+Package hyperref Info: backreferencing OFF on input line 6310.
+Package hyperref Info: Link coloring ON on input line 6313.
+Package hyperref Info: Link coloring with OCG OFF on input line 6320.
+Package hyperref Info: PDF/A mode OFF on input line 6325.
+LaTeX Info: Redefining \ref on input line 6365.
+LaTeX Info: Redefining \pageref on input line 6369.
+\Hy@abspage=\count95
+\c@Item=\count96
+\c@Hfootnote=\count97
+)
+
+Package hyperref Message: Driver (autodetected): hpdftex.
+
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
+File: hpdftex.def 2012/11/06 v6.83m Hyperref driver for pdfTeX
+\Fld@listcount=\count98
+\c@bookmark@seq@number=\count99
+
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty
+Package: rerunfilecheck 2011/04/15 v1.7 Rerun checks for auxiliary files (HO)
+Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2
+82.
+)
+\Hy@SectionHShift=\skip43
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/bookmark.sty
+Package: bookmark 2011/12/02 v1.24 PDF bookmarks (HO)
+
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/bkm-pdftex.def
+File: bkm-pdftex.def 2011/12/02 v1.24 bookmark driver for pdfTeX (HO)
+\BKM@id=\count100
+))
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.sty
+Package: csquotes 2016/01/31 v5.1g context-sensitive quotations (JAW)
+
+(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty
+Package: etoolbox 2015/08/02 v2.2a e-TeX tools for LaTeX (JAW)
+\etb@tempcnta=\count101
+)
+\csq@reset=\count102
+\csq@gtype=\count103
+\csq@glevel=\count104
+\csq@qlevel=\count105
+\csq@maxlvl=\count106
+\csq@tshold=\count107
+\csq@ltx@everypar=\toks16
+
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.def
+File: csquotes.def 2016/01/31 v5.1g csquotes generic definitions (JAW)
+)
+Package csquotes Info: Trying to load configuration file 'csquotes.cfg'...
+Package csquotes Info: ... configuration file loaded successfully.
+
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.cfg
+File: csquotes.cfg
+)
+Package csquotes Info: Enabling multilingual quotes.
+Package csquotes Info: Redefining alias 'english' -> 'english/american'.
+)
+(/usr/share/texlive/texmf-dist/tex/latex/appendix/appendix.sty
+Package: appendix 2009/09/02 v1.2b extra appendix facilities
+\c@@pps=\count108
+\c@@ppsavesec=\count109
+\c@@ppsaveapp=\count110
+)
+Package csquotes Info: Checking for multilingual support...
+Package csquotes Info: ... none found.
+
+
+Package csquotes Warning: No multilingual support.
+(csquotes) Cannot enable multilingual quotes on input line 8.
+
+(./labtainer-instructor.aux)
+\openout1 = `labtainer-instructor.aux'.
+
+LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 8.
+LaTeX Font Info: ... okay on input line 8.
+LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 8.
+LaTeX Font Info: ... okay on input line 8.
+LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 8.
+LaTeX Font Info: ... okay on input line 8.
+LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 8.
+LaTeX Font Info: ... okay on input line 8.
+LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 8.
+LaTeX Font Info: ... okay on input line 8.
+LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 8.
+LaTeX Font Info: ... okay on input line 8.
+LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 8.
+LaTeX Font Info: ... okay on input line 8.
+
+*geometry* driver: auto-detecting
+*geometry* detected driver: pdftex
+*geometry* verbose mode - [ preamble ] result:
+* driver: pdftex
+* paper: a4paper
+* layout:
+* layoutoffset:(h,v)=(0.0pt,0.0pt)
+* modes:
+* h-part:(L,W,R)=(56.9055pt, 483.69684pt, 56.90553pt)
+* v-part:(T,H,B)=(56.9055pt, 731.23582pt, 56.90552pt)
+* \paperwidth=597.50787pt
+* \paperheight=845.04684pt
+* \textwidth=483.69684pt
+* \textheight=731.23582pt
+* \oddsidemargin=-15.36449pt
+* \evensidemargin=-15.36449pt
+* \topmargin=-52.36449pt
+* \headheight=12.0pt
+* \headsep=25.0pt
+* \topskip=12.0pt
+* \footskip=30.0pt
+* \marginparwidth=44.0pt
+* \marginparsep=10.0pt
+* \columnsep=10.0pt
+* \skip\footins=10.8pt plus 4.0pt minus 2.0pt
+* \hoffset=0.0pt
+* \voffset=0.0pt
+* \mag=1000
+* \@twocolumnfalse
+* \@twosidefalse
+* \@mparswitchfalse
+* \@reversemarginfalse
+* (1in=72.27pt=25.4mm, 1cm=28.453pt)
+
+\AtBeginShipoutBox=\box26
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty
+Package: color 2016/01/03 v1.1b Standard LaTeX Color (DPC)
+
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/color.cfg
+File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive
+)
+Package color Info: Driver file: pdftex.def on input line 143.
+
+(/usr/share/texlive/texmf-dist/tex/latex/pdftex-def/pdftex.def
+File: pdftex.def 2011/05/27 v0.06d Graphics/color for pdfTeX
+\Gread@gobject=\count111
+
+(/usr/share/texlive/texmf-dist/tex/context/base/supp-pdf.mkii
+[Loading MPS to PDF converter (version 2006.09.02).]
+\scratchcounter=\count112
+\scratchdimen=\dimen115
+\scratchbox=\box27
+\nofMPsegments=\count113
+\nofMParguments=\count114
+\everyMPshowfont=\toks17
+\MPscratchCnt=\count115
+\MPscratchDim=\dimen116
+\MPnumerator=\count116
+\makeMPintoPDFobject=\count117
+\everyMPtoPDFconversion=\toks18
+)))
+Package hyperref Info: Link coloring ON on input line 8.
+ (/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
+Package: nameref 2012/10/27 v2.43 Cross-referencing by name of section
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty
+Package: gettitlestring 2010/12/03 v1.4 Cleanup title references (HO)
+)
+\c@section@level=\count118
+)
+LaTeX Info: Redefining \ref on input line 8.
+LaTeX Info: Redefining \pageref on input line 8.
+LaTeX Info: Redefining \nameref on input line 8.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <14.4> on input line 11.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <7> on input line 11.
+
+
+LaTeX Warning: No \author given.
+
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <12> on input line 17.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <8> on input line 17.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <6> on input line 17.
+[1
+
+{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}]
+
+LaTeX Warning: Reference `review-artifacts' on page 2 undefined on input line 8
+4.
+
+[2] [3]
+
+Package hyperref Warning: Token not allowed in a PDF string (PDFDocEncoding):
+(hyperref) removing `\\' on input line 150.
+
+Package atveryend Info: Empty hook `BeforeClearDocument' on input line 169.
+[4]
+Package atveryend Info: Empty hook `AfterLastShipout' on input line 169.
+ (./labtainer-instructor.aux)
+Package atveryend Info: Executing hook `AtVeryEndDocument' on input line 169.
+Package atveryend Info: Empty hook `AtEndAfterFileList' on input line 169.
+
+
+LaTeX Warning: There were undefined references.
+
+Package atveryend Info: Empty hook `AtVeryVeryEnd' on input line 169.
+ )
+Here is how much of TeX's memory you used:
+ 6461 strings out of 494953
+ 95580 string characters out of 6180977
+ 196169 words of memory out of 5000000
+ 9718 multiletter control sequences out of 15000+600000
+ 8977 words of font info for 32 fonts, out of 8000000 for 9000
+ 14 hyphenation exceptions out of 8191
+ 29i,6n,30p,942b,380s stack positions out of 5000i,500n,10000p,200000b,80000s
+
+Output written on labtainer-instructor.pdf (4 pages, 60396 bytes).
+PDF statistics:
+ 83 PDF objects out of 1000 (max. 8388607)
+ 72 compressed objects within 1 object stream
+ 13 named destinations out of 1000 (max. 500000)
+ 65 words of extra memory for PDF output out of 10000 (max. 10000000)
+
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.out.ps b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.out.ps
new file mode 100644
index 000000000..23268d60e
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.out.ps
@@ -0,0 +1,40 @@
+%!
+/pdfmark where{pop}
+{/globaldict where{pop globaldict}{userdict}ifelse/pdfmark/cleartomark load put}
+ifelse
+[
+/Title(Introduction)
+/Count -2
+/Action/GoTo/Dest(section.1)cvn
+/OUT pdfmark
+[
+/Title(Assigning a Lab)
+/Action/GoTo/Dest(subsection.1.1)cvn
+/OUT pdfmark
+[
+/Title(Assessing a Lab)
+/Count -1
+/Action/GoTo/Dest(subsection.1.2)cvn
+/OUT pdfmark
+[
+/Title(Review artifact details)
+/Action/GoTo/Dest(subsubsection.1.2.1)cvn
+/OUT pdfmark
+[
+/Title(Managing Labtainer Installations and Updates)
+/Count -1
+/Action/GoTo/Dest(section.2)cvn
+/OUT pdfmark
+[
+/Title(Suggestions for student workflow)
+/Action/GoTo/Dest(subsection.2.1)cvn
+/OUT pdfmark
+[
+/Title(LMS Assignment Collection)
+/Count -1
+/Action/GoTo/Dest(appendix.A)cvn
+/OUT pdfmark
+[
+/Title(Sakai)
+/Action/GoTo/Dest(subsection.A.1)cvn
+/OUT pdfmark
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.pdf b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.pdf
new file mode 100644
index 000000000..2f7ab7f1b
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.pdf differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.tex b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.tex
new file mode 100644
index 000000000..51ae9ec84
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/instructor/labtainer-instructor.tex
@@ -0,0 +1,169 @@
+\documentclass[12pt]{article}
+\usepackage{geometry}
+\geometry{a4paper, total={170mm,257mm},left=20mm, top=20mm, }
+\usepackage[colorlinks=true,linkcolor=blue,urlcolor=black]{hyperref}
+\usepackage{bookmark}
+\usepackage[autostyle, english = american]{csquotes}
+\usepackage{appendix}
+\begin{document}
+\title {Labtainer Instructor Guide\vspace{-4ex}}
+\maketitle
+
+\section {Introduction}
+This manual is intended for use by instructors who assign and/or grade
+labs using Labtainers.
+Labtainers assume you have a Linux system, e.g., a virtual machine (VM).
+The easiest path is to use our pre-built VM available at the Labtainer
+website \url{https://my.nps.edu/web/c3o/virtual-machine-images}.
+Alternately, refer to
+in Appendix A of the \underline{Labtainer Student Guide} for installation of VirtualBox
+and a Linux system.
+Note that any Linux system can be used as long as it supports Docker.
+If Labtainers is to be used on a Linux system other than the pre-built VM,
+refer to the \underline{Labtainer Student Guide} for information on
+installing Labtainers.
+
+Labtainers provide a consistent execution environment for performing
+laboratory exercises, and can include execution of several different
+computers interconnected via virtual networks. Refer to our published
+papers at \url{https://my.nps.edu/web/c3o/labtainers} for additional information
+on the use of Labtainers. And see the \underline{Lab Designer User Guide}"
+at \url{https://my.nps.edu/documents/107523844/109121513/labdesigner.pdf} for
+information on creating and maintaining Labtainer exercises.
+
+\subsection{Assigning a Lab}
+Student instructions for using Labtainers are in the \underline{Labtainer Student Guide}.
+Students work from the {\tt labtainer-student} directory, i.e.,
+\begin{verbatim}
+ cd ~/labtainer/trunk/scripts/labtainer-student
+\end{verbatim}
+Available labs are listed via the {\tt labtainer} script:
+\begin{verbatim}
+ labtainer
+\end{verbatim}
+\noindent Start a lab by providing its name as an argument to the {\tt labtainer} command.
+This will typically display a link to a lab manual, or will display a lab manual in one of
+the resulting virtual terminals. You can interact with the resulting computers just as a
+student would.
+
+\subsection{Assessing a Lab}
+When the student stops a lab, i.e., using {\tt stoplab}, Labtainers creates a zip file of
+student artifacts (including lab reports) and then displays the path to this zip file to
+the student. The easiest way for the student to forward this zip file to you is by starting
+a browser on the Linux VM and either emailing you the zip file, or uploading the file
+into an LMS, (e.g., Sakai). Alternately, the student can define a shared folder in the VM
+and copy the zip to the host computer.
+
+Collect all of the lab zip files from each student into your Labtainer transfer directory, which
+is typically at
+\begin{verbatim}
+ ~/labtainer_xfer/
+\end{verbatim}
+\noindent where labname is the name of the lab. Do not unzip the files. Alternately student
+assignments can be bulk-collected from a learning management system (LMS) per Appendix \ref{lms collection}
+and the resulting zip would be copied into the
+Labtainer transfer directory. Again, do not unzip files and do not change the file names of zip files.
+
+Instructor assessment of labs takes place from the {\tt labtainer-instructor} directory, i.e.,
+\begin{verbatim}
+ cd ~/labtainer/trunk/scripts/labtainer-instructor
+\end{verbatim}
+
+\noindent Use the {\tt gradelab} command to assess results for a given lab:
+\begin{verbatim}
+ gradelab
+\end{verbatim}
+\noindent A table of lab results with one row per student and
+a column for each goal will be displayed. A description of the goals follows the table.
+Note that not all labs include automated assessment. For those labs, you will see this
+messsage:
+\begin{verbatim}
+ No automated assessment for this lab
+\end{verbatim}
+\noindent Even when no automated assessment is performed, you can still observe student performance
+artifacts, e.g., the {\tt .bash\_history} file as described below in \ref{review-artifacts}.
+
+Student reports (if any) are copied into
+\begin{verbatim}
+ ~/labtainer_xfer//docs
+\end{verbatim}
+\noindent on the Linux host. If LMS assignment collection is used, then student reports should
+be looked for in
+\begin{verbatim}
+ ~/labtainer_xfer//reports
+\end{verbatim}
+\noindent which also includes reports separately uploaded into the LMS.
+
+\subsubsection{Review artifact details}
+You can view all student results, including their original artifacts by using the {\tt -d} flag
+with the {\tt gradelab} command. This results in a virtual terminal connected to a grading
+container that contains all student artifacts and results. If you have not first run the
+{\tt gradelab} command without the ``-d'' option, run {\tt instructor.py} from within the
+virtual terminal to cause the zip files to be extracted. A student's home directory can
+then be found in
+\begin{verbatim}
+/..student
+\end{verbatim}
+\noindent There you will find the {\tt .bash\_history} file along with the student-created files.
+Student artifacts collected by the framework are found in
+\begin{verbatim}
+/..student/.local/result
+\end{verbatim}
+
+\noindent The {\tt -d} option is also used when debugging automated assessment configuration
+files. You can create additional virtual terminals into the grading container by reissuing
+the gradelab command with the {\tt -a} flag. When you are finished, or wish to stop working, type:
+\begin{verbatim}
+ stopgrader
+\end{verbatim}
+
+\section{Managing Labtainer Installations and Updates}
+Any given Labtainers installation can be brought up to date to the latest version by using the
+\begin{verbatim}
+ update-labtainer.sh
+\end{verbatim}
+\noindent command from the {\tt labtainer-student} directory. The current version of a Labtainer installation is seen by using:
+\begin{verbatim}
+ labtainer -v
+\end{verbatim}
+\noindent
+The first time any given lab exercise is started, the latest version of that lab is automatically pulled from
+the Docker Hub registry.
+Note however that any given lab is not updated by the {\tt update-labtainer.sh} command once the lab has been started.
+To update a specific lab to the latest version after it has been started the previous version of that lab must be deleted
+using:
+\begin{verbatim}
+ removelab.py
+\end{verbatim}
+\noindent The next time the lab is started, the latest version will be retrieved from the Docker registry.
+
+\subsection{Suggestions for student workflow}
+A student's work on any given lab is preserved until and unless the student restarts the lab using the ``-r''
+option on the {\tt labtainer -r} command. When taking a break from work on a lab, the student can
+either stop the lab using {\tt stoplab}, or simply pause the VM. However, if the student wishes to perform other
+Labtainer-related work on the VM, (e.g., revisit a previous lab), they should first use {\tt stoplab} for the current
+lab. When the restart the lab, none of their work will be lost.
+
+
+\newpage
+\appendix
+\section{\\LMS Assignment Collection}
+\label{lms collection}
+\subsection{Sakai}
+In the Sakai Assignments section, select the ``In / New'' entry for the appropriate assignment.
+The resulting page should enumerate each student who has submitted an assignment. In the upper right,
+click the ``Download All'' link, and then click the ``Student submission attachment(s)'' option and
+click the ``Download'' button. Copy the resulting zip into the lab transfer directory
+on the Linux host, i.e.,
+\begin{verbatim}
+ ~/labtainer_xfer/
+\end{verbatim}
+\noindent Do not unzip the file and do not change its file name.
+You can then run the {\tt gradelab } command from the {\tt labtainer-instructor} directory.
+In addition to the assessment summary, any student lab reports will be available in:
+\begin{verbatim}
+ ~/labtainer_xfer//reports/
+\end{verbatim}
+\noindent Those reports will include any that the student separately uploaded into Sakai (it is
+important to remind students to NOT change the name of lab report documents.)
+\end{document}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/ExternalNetworks.jpg b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/ExternalNetworks.jpg
new file mode 100644
index 000000000..3da071a97
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/ExternalNetworks.jpg differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/ExternalNetworks.odg b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/ExternalNetworks.odg
new file mode 100644
index 000000000..1719ce505
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/ExternalNetworks.odg differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/Makefile b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/Makefile
new file mode 100644
index 000000000..a925edd48
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/Makefile
@@ -0,0 +1,6 @@
+labdesigner.pdf: labdesigner.tex
+ latex labdesigner
+ pdflatex labdesigner
+clean:
+ rm -fr auto
+ rm -fr labdesigner.aux labdesigner.pdf
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/dmz-lab.jpg b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/dmz-lab.jpg
new file mode 100644
index 000000000..e2a3b1e02
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/dmz-lab.jpg differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.aux b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.aux
new file mode 100644
index 000000000..ab207bd11
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.aux
@@ -0,0 +1,228 @@
+\relax
+\providecommand\hyper@newdestlabel[2]{}
+\providecommand\BKM@entry[2]{}
+\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
+\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
+\global\let\oldcontentsline\contentsline
+\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
+\global\let\oldnewlabel\newlabel
+\gdef\newlabel#1#2{\newlabelxx{#1}#2}
+\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
+\AtEndDocument{\ifx\hyper@anchor\@undefined
+\let\contentsline\oldcontentsline
+\let\newlabel\oldnewlabel
+\fi}
+\fi}
+\global\let\hyper@last\relax
+\gdef\HyperFirstAtBeginDocument#1{#1}
+\providecommand\HyField@AuxAddToFields[1]{}
+\providecommand\HyField@AuxAddToCoFields[2]{}
+\BKM@entry{id=1,dest={73656374696F6E2E31},srcline={23}}{496E74726F64756374696F6E}
+\BKM@entry{id=2,dest={73756273656374696F6E2E312E31},srcline={36}}{42656E6566697473206F66204C61627461696E657273}
+\BKM@entry{id=3,dest={73756273656374696F6E2E312E32},srcline={91}}{4F627461696E696E6720746865204C61627461696E657220646576656C6F706D656E74206B6974}
+\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{3}{section.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Benefits of Labtainers}{3}{subsection.1.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Obtaining the Labtainer development kit}{3}{subsection.1.2}}
+\BKM@entry{id=4,dest={73756273656374696F6E2E312E33},srcline={112}}{436F6E74656E74206F662074686973206775696465}
+\BKM@entry{id=5,dest={73656374696F6E2E32},srcline={132}}{4F76657276696577206F66207468652073747564656E7420656E7669726F6E6D656E7420616E6420776F726B666C6F77}
+\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Example Labtainers network topology}}{4}{figure.1}}
+\newlabel{fig:dmz}{{1}{4}{Example Labtainers network topology}{figure.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {1.3}Content of this guide}{4}{subsection.1.3}}
+\@writefile{toc}{\contentsline {section}{\numberline {2}Overview of the student environment and workflow}{5}{section.2}}
+\newlabel{student environment}{{2}{5}{Overview of the student environment and workflow}{section.2}{}}
+\BKM@entry{id=6,dest={73656374696F6E2E33},srcline={197}}{4372656174696E67206E6577206C616273}
+\BKM@entry{id=7,dest={73756273656374696F6E2E332E31},srcline={220}}{43726561746520746865206669727374206C616220636F6D7075746572}
+\BKM@entry{id=8,dest={73756273656374696F6E2E332E32},srcline={248}}{54657374696E6720746865206E6577206C6162}
+\@writefile{toc}{\contentsline {section}{\numberline {3}Creating new labs}{6}{section.3}}
+\newlabel{sec:new_labs}{{3}{6}{Creating new labs}{section.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Create the first lab computer}{6}{subsection.3.1}}
+\BKM@entry{id=9,dest={73756273656374696F6E2E332E33},srcline={311}}{4D756C7469706C6520636F6E7461696E657273}
+\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Testing the new lab}{7}{subsection.3.2}}
+\BKM@entry{id=10,dest={73656374696F6E2E34},srcline={328}}{446566696E696E6720746865206C616220657865637574696F6E20656E7669726F6E6D656E74}
+\BKM@entry{id=11,dest={73756273656374696F6E2E342E31},srcline={347}}{446F636B65722066696C6573}
+\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Multiple containers}{8}{subsection.3.3}}
+\@writefile{toc}{\contentsline {section}{\numberline {4}Defining the lab execution environment}{8}{section.4}}
+\newlabel{execution environment}{{4}{8}{Defining the lab execution environment}{section.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Docker files}{8}{subsection.4.1}}
+\BKM@entry{id=12,dest={73756273656374696F6E2E342E32},srcline={397}}{436F6E7461696E657220646566696E6974696F6E7320696E2073746172742E636F6E666967}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Container definitions in start.config}{9}{subsection.4.2}}
+\newlabel{start config}{{4.2}{9}{Container definitions in start.config}{subsection.4.2}{}}
+\BKM@entry{id=13,dest={73756273656374696F6E2E342E33},srcline={507}}{4C61622D73706563696669632066696C657320696E207468652073747564656E74277320686F6D65206469726563746F7279}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}Lab-specific files in the student's home directory}{11}{subsection.4.3}}
+\newlabel{home files}{{4.3}{11}{Lab-specific files in the student's home directory}{subsection.4.3}{}}
+\BKM@entry{id=14,dest={73756273756273656374696F6E2E342E332E31},srcline={528}}{4C61726765206F72206E756D65726F75732066696C657320696E2074686520686F6D65206469726563746F7279}
+\BKM@entry{id=15,dest={73756273656374696F6E2E342E34},srcline={556}}{4C61622D73706563696669632073797374656D2066696C6573}
+\BKM@entry{id=16,dest={73756273656374696F6E2E342E35},srcline={582}}{53797374656D207365727669636573}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.3.1}Large or numerous files in the home directory}{12}{subsubsection.4.3.1}}
+\newlabel{large files}{{4.3.1}{12}{Large or numerous files in the home directory}{subsubsection.4.3.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.4}Lab-specific system files}{12}{subsection.4.4}}
+\BKM@entry{id=17,dest={73756273656374696F6E2E342E36},srcline={596}}{496E737472756374696F6E7320666F722053747564656E7473}
+\BKM@entry{id=18,dest={73756273656374696F6E2E342E37},srcline={616}}{52756E6E696E672070726F6772616D7320696E205669727475616C205465726D696E616C73}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.5}System services}{13}{subsection.4.5}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.6}Instructions for Students}{13}{subsection.4.6}}
+\newlabel{instructions}{{4.6}{13}{Instructions for Students}{subsection.4.6}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.7}Running programs in Virtual Terminals}{13}{subsection.4.7}}
+\newlabel{student start}{{4.7}{13}{Running programs in Virtual Terminals}{subsection.4.7}{}}
+\BKM@entry{id=19,dest={73756273656374696F6E2E342E38},srcline={664}}{46696E616C206C616220656E7669726F6E6D656E74206669787570}
+\BKM@entry{id=20,dest={73756273656374696F6E2E342E39},srcline={682}}{4175746F6D6174696320636F7079696E672066696C65732066726F6D20636F6E7461696E65727320746F2074686520686F7374}
+\BKM@entry{id=21,dest={73656374696F6E2E35},srcline={692}}{506172616D65746572697A696E672061206C6162}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.8}Final lab environment fixup}{14}{subsection.4.8}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.9}Automatic copying files from containers to the host}{14}{subsection.4.9}}
+\BKM@entry{id=22,dest={73756273656374696F6E2E352E31},srcline={717}}{506172616D65746572697A6174696F6E20636F6E66696775726174696F6E2066696C652073796E746178}
+\@writefile{toc}{\contentsline {section}{\numberline {5}Parameterizing a lab}{15}{section.5}}
+\newlabel{parameterize}{{5}{15}{Parameterizing a lab}{section.5}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Parameterization configuration file syntax}{15}{subsection.5.1}}
+\BKM@entry{id=23,dest={73756273656374696F6E2E352E32},srcline={803}}{53796E6368726F6E697A696E67207374617274757020616E6420706172616D65746572697A6174696F6E}
+\BKM@entry{id=24,dest={73756273656374696F6E2E352E33},srcline={824}}{506172616D65746572697A696E672073746172742E636F6E666967}
+\BKM@entry{id=25,dest={73756273656374696F6E2E352E34},srcline={829}}{53696D706C6520506172616D65746572697A6174696F6E20666F7220436865636B696E67204F776E2D776F726B}
+\BKM@entry{id=26,dest={73656374696F6E2E36},srcline={838}}{4175746F6D61746564206173736573736D656E74206F662073747564656E74206C616273}
+\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}Synchronizing startup and parameterization}{17}{subsection.5.2}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {5.3}Parameterizing start.config}{17}{subsection.5.3}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {5.4}Simple Parameterization for Checking Own-work}{17}{subsection.5.4}}
+\@writefile{toc}{\contentsline {section}{\numberline {6}Automated assessment of student labs}{17}{section.6}}
+\newlabel{assessment}{{6}{17}{Automated assessment of student labs}{section.6}{}}
+\BKM@entry{id=27,dest={73756273656374696F6E2E362E31},srcline={859}}{41727469666163742066696C6573}
+\BKM@entry{id=28,dest={73756273756273656374696F6E2E362E312E31},srcline={878}}{436170747572696E6720737464696E20616E64207374646F7574}
+\BKM@entry{id=29,dest={73756273756273656374696F6E2E362E312E32},srcline={905}}{436170747572696E672070726F6772616D2066696C65206F7574707574}
+\@writefile{toc}{\contentsline {subsection}{\numberline {6.1}Artifact files}{18}{subsection.6.1}}
+\newlabel{artifact files}{{6.1}{18}{Artifact files}{subsection.6.1}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.1}Capturing stdin and stdout}{18}{subsubsection.6.1.1}}
+\newlabel{stdin and stdout}{{6.1.1}{18}{Capturing stdin and stdout}{subsubsection.6.1.1}{}}
+\BKM@entry{id=30,dest={73756273756273656374696F6E2E362E312E33},srcline={934}}{4261736820486973746F7279}
+\BKM@entry{id=31,dest={73756273756273656374696F6E2E362E312E34},srcline={939}}{53797374656D206C6F6773}
+\BKM@entry{id=32,dest={73756273756273656374696F6E2E362E312E35},srcline={943}}{436170747572696E6720696E666F726D6174696F6E2061626F75742074686520656E7669726F6E6D656E74}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.2}Capturing program file output}{19}{subsubsection.6.1.2}}
+\newlabel{program output}{{6.1.2}{19}{Capturing program file output}{subsubsection.6.1.2}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.3}Bash History}{19}{subsubsection.6.1.3}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.4}System logs}{19}{subsubsection.6.1.4}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.5}Capturing information about the environment}{19}{subsubsection.6.1.5}}
+\newlabel{precheck}{{6.1.5}{19}{Capturing information about the environment}{subsubsection.6.1.5}{}}
+\BKM@entry{id=33,dest={73756273756273656374696F6E2E362E312E36},srcline={978}}{436170747572696E672066696C6520616363657373206576656E7473}
+\BKM@entry{id=34,dest={73756273756273656374696F6E2E362E312E37},srcline={1020}}{47656E65726174696E6720726573756C74732075706F6E2073746F7070696E6720746865206C6162}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.6}Capturing file access events}{20}{subsubsection.6.1.6}}
+\newlabel{notify}{{6.1.6}{20}{Capturing file access events}{subsubsection.6.1.6}{}}
+\BKM@entry{id=35,dest={73756273756273656374696F6E2E362E312E38},srcline={1037}}{4172746966616374206172636869766573}
+\BKM@entry{id=36,dest={73756273656374696F6E2E362E32},srcline={1049}}{417274696661637420726573756C742076616C756573}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.7}Generating results upon stopping the lab}{21}{subsubsection.6.1.7}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.8}Artifact archives}{21}{subsubsection.6.1.8}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {6.2}Artifact result values}{21}{subsection.6.2}}
+\newlabel{results.config}{{6.2}{21}{Artifact result values}{subsection.6.2}{}}
+\BKM@entry{id=37,dest={73756273756273656374696F6E2E362E322E31},srcline={1202}}{436F6E76657274696E672061727469666163742066696C6520666F726D617473}
+\BKM@entry{id=38,dest={73756273656374696F6E2E362E33},srcline={1214}}{4576616C756174696E6720726573756C7473}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.2.1}Converting artifact file formats}{24}{subsubsection.6.2.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {6.3}Evaluating results}{24}{subsection.6.3}}
+\newlabel{goals.config}{{6.3}{24}{Evaluating results}{subsection.6.3}{}}
+\BKM@entry{id=39,dest={73756273756273656374696F6E2E362E332E31},srcline={1389}}{4173736573736D656E74205265706F7274}
+\BKM@entry{id=40,dest={73756273756273656374696F6E2E362E332E32},srcline={1399}}{446F63756D656E7420746865206D65616E696E67206F6620676F616C73}
+\BKM@entry{id=41,dest={73756273656374696F6E2E362E34},srcline={1420}}{4173736573736D656E74206578616D706C6573}
+\BKM@entry{id=42,dest={73756273756273656374696F6E2E362E342E31},srcline={1425}}{446F2061727469666163742066696C657320636F6E7461696E20737065636966696320737472696E67733F}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.3.1}Assessment Report}{28}{subsubsection.6.3.1}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.3.2}Document the meaning of goals}{28}{subsubsection.6.3.2}}
+\newlabel{document goals}{{6.3.2}{28}{Document the meaning of goals}{subsubsection.6.3.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {6.4}Assessment examples}{28}{subsection.6.4}}
+\newlabel{examples}{{6.4}{28}{Assessment examples}{subsection.6.4}{}}
+\BKM@entry{id=43,dest={73756273756273656374696F6E2E362E342E32},srcline={1445}}{436F6D706172652076616C7565206F662061206669656C642066726F6D20612073656C6563746564206C696E6520696E20616E2061727469666163742066696C65}
+\BKM@entry{id=44,dest={73756273756273656374696F6E2E362E342E33},srcline={1462}}{4D7920646573697265642061727469666163747320617265206E6F7420696E20737464696E206F72207374646F75742C207468652070726F6772616D206F75747075747320612066696C65}
+\BKM@entry{id=45,dest={73756273756273656374696F6E2E362E342E34},srcline={1465}}{44697374696E6775697368206C6F672066696C6520656E74726965732067656E657261746564206265666F726520616E6420616674657220636F6E66696775726174696F6E206368616E676573}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.1}Do artifact files contain specific strings?}{29}{subsubsection.6.4.1}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.2}Compare value of a field from a selected line in an artifact file}{29}{subsubsection.6.4.2}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.3}My desired artifacts are not in stdin or stdout, the program outputs a file}{29}{subsubsection.6.4.3}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.4}Distinguish log file entries generated before and after configuration changes}{29}{subsubsection.6.4.4}}
+\newlabel{time delimeter}{{6.4.4}{29}{Distinguish log file entries generated before and after configuration changes}{subsubsection.6.4.4}{}}
+\BKM@entry{id=46,dest={73756273756273656374696F6E2E362E342E35},srcline={1526}}{44656C696D6974696E67206C6F6773206279207374617274696E67207365727669636573}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.5}Delimiting logs by starting services}{30}{subsubsection.6.4.5}}
+\newlabel{time delimiter services}{{6.4.5}{30}{Delimiting logs by starting services}{subsubsection.6.4.5}{}}
+\BKM@entry{id=47,dest={73756273756273656374696F6E2E362E342E36},srcline={1552}}{44656C696D6974696E672074696D65207573696E67206C6F672066696C6520656E7472696573}
+\BKM@entry{id=48,dest={73756273656374696F6E2E362E35},srcline={1565}}{446562756767696E67206175746F6D61746564206173736573736D656E7420696E206C616273}
+\BKM@entry{id=49,dest={73656374696F6E2E37},srcline={1597}}{4E6574776F726B696E67}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.6}Delimiting time using log file entries}{31}{subsubsection.6.4.6}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {6.5}Debugging automated assessment in labs}{31}{subsection.6.5}}
+\@writefile{toc}{\contentsline {section}{\numberline {7}Networking}{31}{section.7}}
+\newlabel{networking}{{7}{31}{Networking}{section.7}{}}
+\BKM@entry{id=50,dest={73756273656374696F6E2E372E31},srcline={1616}}{5265616C6973746963204E6574776F726B20526F7574696E6720616E6420444E53}
+\BKM@entry{id=51,dest={73756273656374696F6E2E372E32},srcline={1639}}{436F6D6D756E69636174696E6720776974682065787465726E616C20686F737473206F7220564D73}
+\@writefile{toc}{\contentsline {subsection}{\numberline {7.1}Realistic Network Routing and DNS}{32}{subsection.7.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {7.2}Communicating with external hosts or VMs}{32}{subsection.7.2}}
+\newlabel{external hosts}{{7.2}{32}{Communicating with external hosts or VMs}{subsection.7.2}{}}
+\BKM@entry{id=52,dest={73656374696F6E2E38},srcline={1672}}{4275696C64696E672C204D61696E7461696E696E6720616E64205075626C697368696E67204C616273}
+\BKM@entry{id=53,dest={73756273656374696F6E2E382E31},srcline={1689}}{4E505320446576656C6F706D656E74204F7065726174696F6E73}
+\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Networking with external hosts.}}{33}{figure.2}}
+\newlabel{fig:external hosts}{{2}{33}{Networking with external hosts}{figure.2}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {8}Building, Maintaining and Publishing Labs}{33}{section.8}}
+\newlabel{publishing}{{8}{33}{Building, Maintaining and Publishing Labs}{section.8}{}}
+\BKM@entry{id=54,dest={73756273656374696F6E2E382E32},srcline={1744}}{416C7465726E61746520726567697374727920666F722074657374696E67}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.1}NPS Development Operations}{34}{subsection.8.1}}
+\BKM@entry{id=55,dest={73756273656374696F6E2E382E33},srcline={1753}}{5265757365206F66206C617267652066696C652073657473}
+\BKM@entry{id=56,dest={73756273656374696F6E2E382E34},srcline={1771}}{5061636B61676520736F757263657320666F722061707420616E642079756D}
+\BKM@entry{id=57,dest={73756273656374696F6E2E382E35},srcline={1787}}{4C6F63616C652073657474696E6773}
+\BKM@entry{id=58,dest={73756273656374696F6E2E382E36},srcline={1795}}{4C61622076657273696F6E73}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.2}Alternate registry for testing}{35}{subsection.8.2}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.3}Reuse of large file sets}{35}{subsection.8.3}}
+\newlabel{manifest}{{8.3}{35}{Reuse of large file sets}{subsection.8.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.4}Package sources for apt and yum}{35}{subsection.8.4}}
+\newlabel{package sources}{{8.4}{35}{Package sources for apt and yum}{subsection.8.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.5}Locale settings}{35}{subsection.8.5}}
+\BKM@entry{id=59,dest={73656374696F6E2E39},srcline={1836}}{4D756C74692D75736572204C61627461696E657273}
+\BKM@entry{id=60,dest={73756273756273656374696F6E2E392E302E31},srcline={1866}}{4D756C74692D75736572204C61627461696E6572732C206F6E65204C61627461696E657220564D207065722073747564656E74}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.6}Lab versions}{36}{subsection.8.6}}
+\@writefile{toc}{\contentsline {section}{\numberline {9}Multi-user Labtainers}{36}{section.9}}
+\newlabel{multi user}{{9}{36}{Multi-user Labtainers}{section.9}{}}
+\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Multi-user Labtainers with multiple instances of Labtainers.}}{37}{figure.3}}
+\newlabel{fig:multi-multi}{{3}{37}{Multi-user Labtainers with multiple instances of Labtainers}{figure.3}{}}
+\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces Multi-user Labtainers via SSH.}}{37}{figure.4}}
+\newlabel{fig:multi-single}{{4}{37}{Multi-user Labtainers via SSH}{figure.4}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {9.0.1}Multi-user Labtainers, one Labtainer VM per student}{37}{subsubsection.9.0.1}}
+\BKM@entry{id=61,dest={73756273756273656374696F6E2E392E302E32},srcline={1898}}{53696E676C65204C61627461696E65727320564D2077697468206D756C7469706C652073747564656E7473}
+\BKM@entry{id=62,dest={73756273656374696F6E2E392E31},srcline={1922}}{4372656174696E6720636F6E666F726D616E74206D756C74692D75736572206C616273}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {9.0.2}Single Labtainers VM with multiple students}{38}{subsubsection.9.0.2}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {9.1}Creating conformant multi-user labs}{38}{subsection.9.1}}
+\newlabel{conformant multi-user}{{9.1}{38}{Creating conformant multi-user labs}{subsection.9.1}{}}
+\BKM@entry{id=63,dest={73656374696F6E2E3130},srcline={1997}}{4C696D69746174696F6E73}
+\BKM@entry{id=64,dest={73656374696F6E2E3131},srcline={2029}}{4E6F746573}
+\BKM@entry{id=65,dest={73756273656374696F6E2E31312E31},srcline={2031}}{46697265666F78}
+\BKM@entry{id=66,dest={73756273656374696F6E2E31312E32},srcline={2044}}{57697265736861726B}
+\BKM@entry{id=67,dest={73756273656374696F6E2E31312E33},srcline={2060}}{456C6767}
+\@writefile{toc}{\contentsline {section}{\numberline {10}Limitations}{40}{section.10}}
+\newlabel{limitations}{{10}{40}{Limitations}{section.10}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {11}Notes}{40}{section.11}}
+\newlabel{Notes}{{11}{40}{Notes}{section.11}{}}
+\newlabel{Notes}{{11}{40}{Notes}{section.11}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.1}Firefox}{40}{subsection.11.1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.2}Wireshark}{40}{subsection.11.2}}
+\BKM@entry{id=68,dest={73756273656374696F6E2E31312E34},srcline={2064}}{486F7374204F5320646570656E64656E63696573}
+\BKM@entry{id=69,dest={73756273656374696F6E2E31312E35},srcline={2072}}{4C6F67696E2050726F6D707473}
+\BKM@entry{id=70,dest={73756273656374696F6E2E31312E36},srcline={2076}}{4E6574776F726B696E67204E6F746573}
+\BKM@entry{id=71,dest={73756273756273656374696F6E2E31312E362E31},srcline={2078}}{535348}
+\BKM@entry{id=72,dest={73756273756273656374696F6E2E31312E362E32},srcline={2085}}{583131206F76657220535348}
+\BKM@entry{id=73,dest={73756273756273656374696F6E2E31312E362E33},srcline={2090}}{54726166666963206D6972726F72696E67}
+\BKM@entry{id=74,dest={73756273756273656374696F6E2E31312E362E34},srcline={2102}}{444E53}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.3}Elgg}{41}{subsection.11.3}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.4}Host OS dependencies}{41}{subsection.11.4}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.5}Login Prompts}{41}{subsection.11.5}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.6}Networking Notes}{41}{subsection.11.6}}
+\newlabel{Networking Notes}{{11.6}{41}{Networking Notes}{subsection.11.6}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {11.6.1}SSH}{41}{subsubsection.11.6.1}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {11.6.2}X11 over SSH}{41}{subsubsection.11.6.2}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {11.6.3}Traffic mirroring}{41}{subsubsection.11.6.3}}
+\BKM@entry{id=75,dest={73756273756273656374696F6E2E31312E362E35},srcline={2106}}{4F766572726964696E6720446F636B657220726F7574696E6720616E6420444E53}
+\BKM@entry{id=76,dest={73756273656374696F6E2E31312E37},srcline={2124}}{55736572206D616E6167656D656E7420616E64207375646F}
+\BKM@entry{id=77,dest={73756273656374696F6E2E31312E38},srcline={2133}}{53756767657374696F6E7320666F7220446576656C6F70657273}
+\BKM@entry{id=78,dest={73756273656374696F6E2E31312E39},srcline={2152}}{436F6E7461696E65722069736F6C6174696F6E}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {11.6.4}DNS}{42}{subsubsection.11.6.4}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {11.6.5}Overriding Docker routing and DNS}{42}{subsubsection.11.6.5}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.7}User management and sudo}{42}{subsection.11.7}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.8}Suggestions for Developers}{42}{subsection.11.8}}
+\BKM@entry{id=79,dest={73756273656374696F6E2E31312E3130},srcline={2167}}{53747564656E742073656C66206173736573736D656E74}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.9}Container isolation}{43}{subsection.11.9}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {11.10}Student self assessment}{43}{subsection.11.10}}
+\BKM@entry{id=80,dest={617070656E6469782E41},srcline={2176}}{53696D4C616220666F722074657374696E67206C616273}
+\BKM@entry{id=81,dest={73756273656374696F6E2E412E31},srcline={2197}}{53696D4C61622044697265637469766573}
+\@writefile{toc}{\contentsline {section}{\numberline {A}\\SimLab for testing labs}{44}{appendix.A}}
+\newlabel{testing}{{A}{44}{\\SimLab for testing labs}{appendix.A}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {A.1}SimLab Directives}{44}{subsection.A.1}}
+\BKM@entry{id=82,dest={73756273656374696F6E2E412E32},srcline={2243}}{53696D4C6162207370706C69636174696F6E206E6F746573}
+\BKM@entry{id=83,dest={73756273656374696F6E2E412E33},srcline={2250}}{52656772657373696F6E2074657374696E67207769746820736D6F6B65746573742E7079}
+\@writefile{toc}{\contentsline {subsection}{\numberline {A.2}SimLab spplication notes}{45}{subsection.A.2}}
+\newlabel{simlab_notes}{{A.2}{45}{SimLab spplication notes}{subsection.A.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {A.3}Regression testing with smoketest.py}{45}{subsection.A.3}}
+\newlabel{smoketest}{{A.3}{45}{Regression testing with smoketest.py}{subsection.A.3}{}}
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.dvi b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.dvi
new file mode 100644
index 000000000..1d0dbbc78
Binary files /dev/null and b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.dvi differ
diff --git a/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.log b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.log
new file mode 100644
index 000000000..2ff60f5e8
--- /dev/null
+++ b/modules/utilities/unix/labtainers/files/Labtainers-master/docs/labdesigner/labdesigner.log
@@ -0,0 +1,967 @@
+This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/Debian) (preloaded format=pdflatex 2019.6.19) 19 JUN 2019 12:22
+entering extended mode
+ restricted \write18 enabled.
+ %&-line parsing enabled.
+**labdesigner
+(./labdesigner.tex
+LaTeX2e <2016/02/01>
+Babel <3.9q> and hyphenation patterns for 3 language(s) loaded.
+(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
+Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
+(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo
+File: size12.clo 2014/09/29 v1.4h Standard LaTeX file (size option)
+)
+\c@part=\count79
+\c@section=\count80
+\c@subsection=\count81
+\c@subsubsection=\count82
+\c@paragraph=\count83
+\c@subparagraph=\count84
+\c@figure=\count85
+\c@table=\count86
+\abovecaptionskip=\skip41
+\belowcaptionskip=\skip42
+\bibindent=\dimen102
+)
+(/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty
+Package: geometry 2010/09/12 v5.6 Page Geometry
+
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty
+Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
+\KV@toks@=\toks14
+)
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifpdf.sty
+Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO)
+Package ifpdf Info: pdfTeX in PDF mode is detected.
+)
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifvtex.sty
+Package: ifvtex 2010/03/01 v1.5 Detect VTeX and its facilities (HO)
+Package ifvtex Info: VTeX not detected.
+)
+(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty
+Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
+)
+\Gm@cnth=\count87
+\Gm@cntv=\count88
+\c@Gm@tempcnt=\count89
+\Gm@bindingoffset=\dimen103
+\Gm@wd@mp=\dimen104
+\Gm@odd@mp=\dimen105
+\Gm@even@mp=\dimen106
+\Gm@layoutwidth=\dimen107
+\Gm@layoutheight=\dimen108
+\Gm@layouthoffset=\dimen109
+\Gm@layoutvoffset=\dimen110
+\Gm@dimlist=\toks15
+)
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
+Package: hyperref 2012/11/06 v6.83m Hypertext links for LaTeX
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty
+Package: hobsub-hyperref 2012/05/28 v1.13 Bundle oberdiek, subset hyperref (HO)
+
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty
+Package: hobsub-generic 2012/05/28 v1.13 Bundle oberdiek, subset generic (HO)
+Package: hobsub 2012/05/28 v1.13 Construct package bundles (HO)
+Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO)
+Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO)
+Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
+Package ifluatex Info: LuaTeX not detected.
+Package hobsub Info: Skipping package `ifvtex' (already loaded).
+Package: intcalc 2007/09/27 v1.1 Expandable calculations with integers (HO)
+Package hobsub Info: Skipping package `ifpdf' (already loaded).
+Package: etexcmds 2011/02/16 v1.5 Avoid name clashes with e-TeX commands (HO)
+Package etexcmds Info: Could not find \expanded.
+(etexcmds) That can mean that you are not using pdfTeX 1.50 or
+(etexcmds) that some package has redefined \expanded.
+(etexcmds) In the latter case, load this package earlier.
+Package: kvsetkeys 2012/04/25 v1.16 Key value parser (HO)
+Package: kvdefinekeys 2011/04/07 v1.3 Define keys (HO)
+Package: pdftexcmds 2011/11/29 v0.20 Utility functions of pdfTeX for LuaTeX (HO
+)
+Package pdftexcmds Info: LuaTeX not detected.
+Package pdftexcmds Info: \pdf@primitive is available.
+Package pdftexcmds Info: \pdf@ifprimitive is available.
+Package pdftexcmds Info: \pdfdraftmode found.
+Package: pdfescape 2011/11/25 v1.13 Implements pdfTeX's escape features (HO)
+Package: bigintcalc 2012/04/08 v1.3 Expandable calculations on big integers (HO
+)
+Package: bitset 2011/01/30 v1.1 Handle bit-vector datatype (HO)
+Package: uniquecounter 2011/01/30 v1.2 Provide unlimited unique counter (HO)
+)
+Package hobsub Info: Skipping package `hobsub' (already loaded).
+Package: letltxmacro 2010/09/02 v1.4 Let assignment for LaTeX macros (HO)
+Package: hopatch 2012/05/28 v1.2 Wrapper for package hooks (HO)
+Package: xcolor-patch 2011/01/30 xcolor patch
+Package: atveryend 2011/06/30 v1.8 Hooks at the very end of document (HO)
+Package atveryend Info: \enddocument detected (standard20110627).
+Package: atbegshi 2011/10/05 v1.16 At begin shipout hook (HO)
+Package: refcount 2011/10/16 v3.4 Data extraction from label references (HO)
+Package: hycolor 2011/01/30 v1.7 Color options for hyperref/bookmark (HO)
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/auxhook.sty
+Package: auxhook 2011/03/04 v1.3 Hooks for auxiliary files (HO)
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty
+Package: kvoptions 2011/06/30 v3.11 Key value format for package options (HO)
+)
+\@linkdim=\dimen111
+\Hy@linkcounter=\count90
+\Hy@pagecounter=\count91
+
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def
+File: pd1enc.def 2012/11/06 v6.83m Hyperref: PDFDocEncoding definition (HO)
+)
+\Hy@SavedSpaceFactor=\count92
+
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg
+File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive
+)
+Package hyperref Info: Option `colorlinks' set `true' on input line 4319.
+Package hyperref Info: Hyper figures OFF on input line 4443.
+Package hyperref Info: Link nesting OFF on input line 4448.
+Package hyperref Info: Hyper index ON on input line 4451.
+Package hyperref Info: Plain pages OFF on input line 4458.
+Package hyperref Info: Backreferencing OFF on input line 4463.
+Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
+Package hyperref Info: Bookmarks ON on input line 4688.
+\c@Hy@tempcnt=\count93
+
+(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty
+\Urlmuskip=\muskip10
+Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
+)
+LaTeX Info: Redefining \url on input line 5041.
+\XeTeXLinkMargin=\dimen112
+\Fld@menulength=\count94
+\Field@Width=\dimen113
+\Fld@charsize=\dimen114
+Package hyperref Info: Hyper figures OFF on input line 6295.
+Package hyperref Info: Link nesting OFF on input line 6300.
+Package hyperref Info: Hyper index ON on input line 6303.
+Package hyperref Info: backreferencing OFF on input line 6310.
+Package hyperref Info: Link coloring ON on input line 6313.
+Package hyperref Info: Link coloring with OCG OFF on input line 6320.
+Package hyperref Info: PDF/A mode OFF on input line 6325.
+LaTeX Info: Redefining \ref on input line 6365.
+LaTeX Info: Redefining \pageref on input line 6369.
+\Hy@abspage=\count95
+\c@Item=\count96
+\c@Hfootnote=\count97
+)
+
+Package hyperref Message: Driver (autodetected): hpdftex.
+
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
+File: hpdftex.def 2012/11/06 v6.83m Hyperref driver for pdfTeX
+\Fld@listcount=\count98
+\c@bookmark@seq@number=\count99
+
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty
+Package: rerunfilecheck 2011/04/15 v1.7 Rerun checks for auxiliary files (HO)
+Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2
+82.
+)
+\Hy@SectionHShift=\skip43
+)
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/bookmark.sty
+Package: bookmark 2011/12/02 v1.24 PDF bookmarks (HO)
+
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/bkm-pdftex.def
+File: bkm-pdftex.def 2011/12/02 v1.24 bookmark driver for pdfTeX (HO)
+\BKM@id=\count100
+))
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
+Package: graphicx 2014/10/28 v1.0g Enhanced LaTeX Graphics (DPC,SPQR)
+
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
+Package: graphics 2016/01/03 v1.0q Standard LaTeX Graphics (DPC,SPQR)
+
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty
+Package: trig 2016/01/03 v1.10 sin cos tan (DPC)
+)
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/graphics.cfg
+File: graphics.cfg 2010/04/23 v1.9 graphics configuration of TeX Live
+)
+Package graphics Info: Driver file: pdftex.def on input line 95.
+
+(/usr/share/texlive/texmf-dist/tex/latex/pdftex-def/pdftex.def
+File: pdftex.def 2011/05/27 v0.06d Graphics/color for pdfTeX
+\Gread@gobject=\count101
+))
+\Gin@req@height=\dimen115
+\Gin@req@width=\dimen116
+)
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.sty
+Package: csquotes 2016/01/31 v5.1g context-sensitive quotations (JAW)
+
+(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty
+Package: etoolbox 2015/08/02 v2.2a e-TeX tools for LaTeX (JAW)
+\etb@tempcnta=\count102
+)
+\csq@reset=\count103
+\csq@gtype=\count104
+\csq@glevel=\count105
+\csq@qlevel=\count106
+\csq@maxlvl=\count107
+\csq@tshold=\count108
+\csq@ltx@everypar=\toks16
+
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.def
+File: csquotes.def 2016/01/31 v5.1g csquotes generic definitions (JAW)
+)
+Package csquotes Info: Trying to load configuration file 'csquotes.cfg'...
+Package csquotes Info: ... configuration file loaded successfully.
+
+(/usr/share/texlive/texmf-dist/tex/latex/csquotes/csquotes.cfg
+File: csquotes.cfg
+)
+Package csquotes Info: Enabling multilingual quotes.
+Package csquotes Info: Redefining alias 'english' -> 'english/american'.
+)
+(/usr/share/texlive/texmf-dist/tex/latex/appendix/appendix.sty
+Package: appendix 2009/09/02 v1.2b extra appendix facilities
+\c@@pps=\count109
+\c@@ppsavesec=\count110
+\c@@ppsaveapp=\count111
+)
+Package csquotes Info: Checking for multilingual support...
+Package csquotes Info: ... none found.
+
+
+Package csquotes Warning: No multilingual support.
+(csquotes) Cannot enable multilingual quotes on input line 9.
+
+(./labdesigner.aux
+
+LaTeX Warning: Label `Notes' multiply defined.
+
+)
+\openout1 = `labdesigner.aux'.
+
+LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 9.
+LaTeX Font Info: ... okay on input line 9.
+LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 9.
+LaTeX Font Info: ... okay on input line 9.
+LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 9.
+LaTeX Font Info: ... okay on input line 9.
+LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 9.
+LaTeX Font Info: ... okay on input line 9.
+LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 9.
+LaTeX Font Info: ... okay on input line 9.
+LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 9.
+LaTeX Font Info: ... okay on input line 9.
+LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 9.
+LaTeX Font Info: ... okay on input line 9.
+
+*geometry* driver: auto-detecting
+*geometry* detected driver: pdftex
+*geometry* verbose mode - [ preamble ] result:
+* driver: pdftex
+* paper: a4paper
+* layout:
+* layoutoffset:(h,v)=(0.0pt,0.0pt)
+* modes:
+* h-part:(L,W,R)=(56.9055pt, 483.69684pt, 56.90553pt)
+* v-part:(T,H,B)=(56.9055pt, 731.23582pt, 56.90552pt)
+* \paperwidth=597.50787pt
+* \paperheight=845.04684pt
+* \textwidth=483.69684pt
+* \textheight=731.23582pt
+* \oddsidemargin=-15.36449pt
+* \evensidemargin=-15.36449pt
+* \topmargin=-52.36449pt
+* \headheight=12.0pt
+* \headsep=25.0pt
+* \topskip=12.0pt
+* \footskip=30.0pt
+* \marginparwidth=44.0pt
+* \marginparsep=10.0pt
+* \columnsep=10.0pt
+* \skip\footins=10.8pt plus 4.0pt minus 2.0pt
+* \hoffset=0.0pt
+* \voffset=0.0pt
+* \mag=1000
+* \@twocolumnfalse
+* \@twosidefalse
+* \@mparswitchfalse
+* \@reversemarginfalse
+* (1in=72.27pt=25.4mm, 1cm=28.453pt)
+
+\AtBeginShipoutBox=\box26
+(/usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty
+Package: color 2016/01/03 v1.1b Standard LaTeX Color (DPC)
+
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/color.cfg
+File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive
+)
+Package color Info: Driver file: pdftex.def on input line 143.
+)
+Package hyperref Info: Link coloring ON on input line 9.
+
+(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
+Package: nameref 2012/10/27 v2.43 Cross-referencing by name of section
+
+(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty
+Package: gettitlestring 2010/12/03 v1.4 Cleanup title references (HO)
+)
+\c@section@level=\count112
+)
+LaTeX Info: Redefining \ref on input line 9.
+LaTeX Info: Redefining \pageref on input line 9.
+LaTeX Info: Redefining \nameref on input line 9.
+
+(/usr/share/texlive/texmf-dist/tex/context/base/supp-pdf.mkii
+[Loading MPS to PDF converter (version 2006.09.02).]
+\scratchcounter=\count113
+\scratchdimen=\dimen117
+\scratchbox=\box27
+\nofMPsegments=\count114
+\nofMParguments=\count115
+\everyMPshowfont=\toks17
+\MPscratchCnt=\count116
+\MPscratchDim=\dimen118
+\MPnumerator=\count117
+\makeMPintoPDFobject=\count118
+\everyMPtoPDFconversion=\toks18
+) (/usr/share/texlive/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty
+Package: epstopdf-base 2010/02/09 v2.5 Base part for package epstopdf
+
+(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/grfext.sty
+Package: grfext 2010/08/19 v1.1 Manage graphics extensions (HO)
+)
+Package grfext Info: Graphics extension search list:
+(grfext) [.png,.pdf,.jpg,.mps,.jpeg,.jbig2,.jb2,.PNG,.PDF,.JPG,.JPE
+G,.JBIG2,.JB2,.eps]
+(grfext) \AppendGraphicsExtensions on input line 452.
+
+(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
+File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
+e
+))
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <14.4> on input line 13.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <7> on input line 13.
+
+
+LaTeX Warning: No \author given.
+
+[1
+
+{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] (./labdesigner.toc
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <12> on input line 2.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <8> on input line 2.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <6> on input line 2.
+pdfTeX warning (ext4): destination with the same identifier (name{page.1}) has
+been already used, duplicate ignored
+
+ \relax
+l.46 ...tarting services}{29}{subsubsection.6.4.5}
+ [1])
+\tf@toc=\write3
+\openout3 = `labdesigner.toc'.
+
+ [2]
+
+File: dmz-lab.jpg Graphic file (type jpg)
+