mirror of
https://github.com/cliffe/SecGen.git
synced 2026-02-21 11:18:06 +00:00
Merge branch 'ff2'
This commit is contained in:
1
Gemfile
1
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
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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'
|
||||
VERSION_NUMBER = '0.0.1.1'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
2
lib/resources/ascii_art/README-sources.md
Normal file
2
lib/resources/ascii_art/README-sources.md
Normal file
@@ -0,0 +1,2 @@
|
||||
Ascii art:
|
||||
https://www.asciiart.eu
|
||||
13
lib/resources/ascii_art/computers/laptop
Normal file
13
lib/resources/ascii_art/computers/laptop
Normal file
@@ -0,0 +1,13 @@
|
||||
+--------------+
|
||||
|.------------.|
|
||||
|| ||
|
||||
|| ||
|
||||
|| ||
|
||||
|| ||
|
||||
|+------------+|
|
||||
+-..--------..-+
|
||||
.--------------.
|
||||
/ /============\ \
|
||||
/ /==============\ \
|
||||
/____________________\
|
||||
\____________________/
|
||||
13
lib/resources/ascii_art/computers/pc
Normal file
13
lib/resources/ascii_art/computers/pc
Normal file
@@ -0,0 +1,13 @@
|
||||
__________
|
||||
.'----------`.
|
||||
| .--------. |
|
||||
| |########| | __________
|
||||
| |########| | /__________\
|
||||
.--------| `--------' |------| --=-- |-------------.
|
||||
| `----,-.-----' |o ====== | |
|
||||
| ______|_|_______ |__________| |
|
||||
| / %%%%%%%%%%%% \ |
|
||||
| / %%%%%%%%%%%%%% \ |
|
||||
| ^^^^^^^^^^^^^^^^^^^^ |
|
||||
+-----------------------------------------------------+
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
15
lib/resources/ascii_art/computers/pc2
Normal file
15
lib/resources/ascii_art/computers/pc2
Normal file
@@ -0,0 +1,15 @@
|
||||
___________________
|
||||
| _______________ |
|
||||
| |XXXXXXXXXXXXX| |
|
||||
| |XXXXXXXXXXXXX| |
|
||||
| |XXXXXXXXXXXXX| |
|
||||
| |XXXXXXXXXXXXX| |
|
||||
| |XXXXXXXXXXXXX| |
|
||||
|_________________|
|
||||
_[_______]_
|
||||
___[___________]___
|
||||
| [_____] []|__
|
||||
| [_____] []| \__
|
||||
L___________________J \ \___\/
|
||||
___________________ /\
|
||||
/###################\ (__)
|
||||
18
lib/resources/ascii_art/computers/pc3
Normal file
18
lib/resources/ascii_art/computers/pc3
Normal file
@@ -0,0 +1,18 @@
|
||||
_______
|
||||
| ___ o|
|
||||
|[_-_]_ |
|
||||
______________ |[_____]|
|
||||
|.------------.| |[_____]|
|
||||
|| || |[====o]|
|
||||
|| || |[_.--_]|
|
||||
|| || |[_____]|
|
||||
|| || | :|
|
||||
||____________|| | :|
|
||||
.==.|"" ...... |.==.| :|
|
||||
|::| '-.________.-' |::|| :|
|
||||
|''| (__________)-.|''||______:|
|
||||
`""`_.............._\""`______
|
||||
/:::::::::::'':::\`;'-.-. `\
|
||||
/::=========.:.-::"\ \ \--\ \
|
||||
\`""""""""""""""""`/ \ \__) \
|
||||
jgs `""""""""""""""""` '========'
|
||||
30
lib/resources/ascii_art/computers/server
Normal file
30
lib/resources/ascii_art/computers/server
Normal file
@@ -0,0 +1,30 @@
|
||||
,=====================.
|
||||
| |
|
||||
|.-------------------.|
|
||||
||[ _ o . . _ ]_||
|
||||
|`-------------------'|
|
||||
|| ||
|
||||
|`-------------------'|
|
||||
|| ||
|
||||
|`-------------------'|
|
||||
|| ||
|
||||
|`-----------------_-'|
|
||||
||[=========]| o (@) |
|
||||
|`---------=='/u\ --- |
|
||||
|------_--------------|
|
||||
| (/) (_) []|
|
||||
|---==--==----------==|
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||||||||
|
||||
|||||||||||||||||dxm|||
|
||||
|||||||||||||||||||||||
|
||||
|=====================|
|
||||
.' `.
|
||||
"""""""""""""""""""""""""""
|
||||
@@ -88,6 +88,8 @@
|
||||
<xs:attribute name="description" type="xs:string"/>
|
||||
|
||||
<xs:attribute name="type" type="xs:string"/>
|
||||
<xs:attribute name="challenge_type" type="xs:string"/>
|
||||
<xs:attribute name="challenge_subtype" type="xs:string"/>
|
||||
<xs:attribute name="privilege" type="xs:string"/>
|
||||
<xs:attribute name="access" type="xs:string"/>
|
||||
<xs:attribute name="platform" type="xs:string"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<distro>Debian 7.8 (wheezy) 32-bit (i386)</distro>
|
||||
<url>https://app.vagrantup.com/secgen/boxes/debian_wheezy_puppet/versions/1.0.2/providers/virtualbox.box</url>
|
||||
<esxi_url>https://app.vagrantup.com/redwiz666/boxes/debian_wheezy_puppet/versions/1.0.0/providers/vmware_esxi.box</esxi_url>
|
||||
<ovirt_template>debian_server</ovirt_template>
|
||||
<ovirt_template>debian_wheezy_server</ovirt_template>
|
||||
|
||||
<reference>https://atlas.hashicorp.com/puppetlabs</reference>
|
||||
<software_license>various</software_license>
|
||||
0
modules/encoders/format/ascii_art/ascii_art.pp
Normal file
0
modules/encoders/format/ascii_art/ascii_art.pp
Normal file
37
modules/encoders/format/ascii_art/secgen_local/local.rb
Normal file
37
modules/encoders/format/ascii_art/secgen_local/local.rb
Normal file
@@ -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
|
||||
61
modules/encoders/format/ascii_art/secgen_metadata.xml
Normal file
61
modules/encoders/format/ascii_art/secgen_metadata.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<encoder xmlns="http://www.github/cliffe/SecGen/encoder"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/encoder">
|
||||
<name>Text to ASCII Art</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>MIT</module_license>
|
||||
<description>Outputs an ASCII art version of the text. Works best with short strings.
|
||||
</description>
|
||||
|
||||
<type>string_format_encoder</type>
|
||||
<platform>linux</platform>
|
||||
<platform>windows</platform>
|
||||
|
||||
<read_fact>strings_to_encode</read_fact>
|
||||
<read_fact>font</read_fact>
|
||||
<!-- Select one of the clearer ascii fonts -->
|
||||
<default_input into="font">
|
||||
<encoder type="string_selector">
|
||||
<input into="strings_to_encode">
|
||||
<value>banner</value>
|
||||
<value>big</value>
|
||||
<value>bubble</value>
|
||||
<value>bulbhead</value>
|
||||
<value>contessa</value>
|
||||
<value>doom</value>
|
||||
<value>drpepper</value>
|
||||
<value>fourtops</value>
|
||||
<value>invita</value>
|
||||
<value>italic</value>
|
||||
<value>larry3d</value>
|
||||
<value>maxfour</value>
|
||||
<value>mini</value>
|
||||
<value>moscow</value>
|
||||
<value>ntgreek</value>
|
||||
<value>ogre</value>
|
||||
<value>pawp</value>
|
||||
<value>pebbles</value>
|
||||
<value>puffy</value>
|
||||
<value>rectangles</value>
|
||||
<value>serifcap</value>
|
||||
<value>short</value>
|
||||
<value>slant</value>
|
||||
<value>slscript</value>
|
||||
<value>small</value>
|
||||
<value>smisome1</value>
|
||||
<value>smslant</value>
|
||||
<value>speed</value>
|
||||
<value>standard</value>
|
||||
<value>straight</value>
|
||||
<value>twopoint</value>
|
||||
</input>
|
||||
</encoder>
|
||||
</default_input>
|
||||
|
||||
<!-- TODO default fonts, random, and read in local.rb -->
|
||||
|
||||
<output_type>encoded_strings</output_type>
|
||||
|
||||
</encoder>
|
||||
@@ -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
|
||||
ZipGenerator.new.run
|
||||
|
||||
@@ -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
|
||||
ImageGenerator.new.run
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<generator xmlns="http://www.github/cliffe/SecGen/generator"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/generator">
|
||||
<name>Random ASCII Art Generator</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>MIT</module_license>
|
||||
<description>Selects and outputs random ascii art image from the lib/resources/ascii_art/computers directory.</description>
|
||||
|
||||
<type>message_generator</type>
|
||||
<type>ascii_art_generator</type>
|
||||
<type>local_calculation</type>
|
||||
<platform>linux</platform>
|
||||
<platform>windows</platform>
|
||||
|
||||
<output_type>ascii_art</output_type>
|
||||
|
||||
</generator>
|
||||
@@ -41,7 +41,7 @@
|
||||
<generator type="username_generator"/>
|
||||
</default_input>
|
||||
<default_input into="password">
|
||||
<generator type="password_generator"/>
|
||||
<generator type="strong_password_generator"/>
|
||||
</default_input>
|
||||
<default_input into="credit_card">
|
||||
<generator type="credit_card_generator"/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class irc2::config{
|
||||
class irc2::config {
|
||||
service { 'ircd-irc2':
|
||||
enable => true,
|
||||
ensure => 'running',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class irc2::install{
|
||||
package { ['ircd-irc2']:
|
||||
class irc2::install {
|
||||
package { 'ircd-irc2':
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<type>ircd</type>
|
||||
</conflict>
|
||||
<conflict>
|
||||
<!-- install stalls and times out on Stretch -->
|
||||
<name>.*Debian.*Stretch.*</name>
|
||||
</conflict>
|
||||
<requires>
|
||||
|
||||
2
modules/services/unix/irc/ircd_hybrid/ircd_hybrid.pp
Normal file
2
modules/services/unix/irc/ircd_hybrid/ircd_hybrid.pp
Normal file
@@ -0,0 +1,2 @@
|
||||
include ircd_hybrid::install
|
||||
include ircd_hybrid::config
|
||||
@@ -0,0 +1,6 @@
|
||||
class ircd_hybrid::config {
|
||||
service { 'ircd-hybrid':
|
||||
enable => true,
|
||||
ensure => 'running',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class ircd_hybrid::install {
|
||||
package { 'ircd-hybrid':
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
33
modules/services/unix/irc/ircd_hybrid/secgen_metadata.xml
Normal file
33
modules/services/unix/irc/ircd_hybrid/secgen_metadata.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<service xmlns="http://www.github/cliffe/SecGen/service"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/service">
|
||||
<name>IRC Server ircd-hybrid</name>
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>MIT</module_license>
|
||||
<description>A lightweight, high-performance internet relay chat daemon.
|
||||
</description>
|
||||
|
||||
<type>ircd</type>
|
||||
<platform>linux</platform>
|
||||
|
||||
<!--optional details-->
|
||||
<software_name>ircd-hybrid</software_name>
|
||||
<software_license>MIT</software_license>
|
||||
|
||||
<conflict>
|
||||
<type>ircd</type>
|
||||
</conflict>
|
||||
<conflict>
|
||||
<!-- install stalls and times out on Kali -->
|
||||
<name>.*Kali.*</name>
|
||||
</conflict>
|
||||
<conflict>
|
||||
<!-- Service start returns 1 on Wheezy -->
|
||||
<name>.*Wheezy.*</name>
|
||||
</conflict>
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
</service>
|
||||
@@ -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
|
||||
@@ -1,5 +1,5 @@
|
||||
class kali_top10::install{
|
||||
package { ['kali-linux-top10']:
|
||||
package { ['kali-linux-top10', 'nfs-common', 'ftp']:
|
||||
ensure => 'installed',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<author>Z. Cliffe Schreuders</author>
|
||||
<module_license>GPLv3</module_license>
|
||||
<description>Installs 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</description>
|
||||
|
||||
|
||||
@@ -14,9 +14,14 @@
|
||||
<read_fact>chroot_dir</read_fact>
|
||||
|
||||
<default_input into="chroot_dir">
|
||||
<value>/srv/chroot</value>
|
||||
<value>/opt/chroot</value>
|
||||
</default_input>
|
||||
|
||||
<conflict>
|
||||
<!-- On Wheezy: Could not find init script for 'chroot' -->
|
||||
<name>.*Debian.*Wheezy.*</name>
|
||||
</conflict>
|
||||
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
|
||||
@@ -29,8 +29,13 @@
|
||||
<value>busybox</value>
|
||||
</default_input>
|
||||
|
||||
<conflict>
|
||||
<!-- fails to add a required repo key in Wheezy -->
|
||||
<name>.*Debian.*Wheezy.*</name>
|
||||
</conflict>
|
||||
|
||||
<requires>
|
||||
<type>update</type>
|
||||
</requires>
|
||||
|
||||
</utility>
|
||||
|
||||
@@ -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 <https://my.nps.edu/web/c3o/labtainers>.
|
||||
|
||||
[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 <https://my.nps.edu/web/c3o/support1>
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="GoalsUI_Sep13" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project GoalsUI_Sep13.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar: JAR building
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="GoalsUI_Sep13-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
||||
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
compile.on.save=true
|
||||
user.properties.file=C:\\Users\\Dan\\AppData\\Roaming\\NetBeans\\8.2\\build.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
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>GoalsUI_Sep13</name>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
@@ -0,0 +1,422 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1110, 69]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="rowLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="ArtifactPanel" min="-2" pref="1390" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="UpButton" max="32767" attributes="0"/>
|
||||
<Component id="DownButton" min="-2" pref="41" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="DeleteButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="73" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="ArtifactPanel" alignment="0" min="-2" pref="80" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="UpButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="DownButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="DeleteButton" min="-2" pref="58" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="rowLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="ArtifactPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.SoftBevelBorderInfo">
|
||||
<BevelBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1400, 0]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1300, 34]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="GoalIDTextField" min="-2" pref="125" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="GoalTypeComboBox" min="-2" pref="147" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="OperatorComboBox" min="-2" pref="139" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ExecutableFileTextField" min="-2" pref="143" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ResultTagComboBox" min="-2" pref="168" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||
<Component id="ArithmeticResultTagTextField" min="-2" pref="179" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="AnswerTypeComboBox" min="-2" pref="150" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="AnswerTagTextField" min="-2" pref="193" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ResultTag2ComboBox" linkSize="11" min="-2" pref="155" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ParameterComboBox" linkSize="11" pref="150" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="BooleanTextField" min="-2" pref="404" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ValueTextField" min="-2" pref="110" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="SubgoalTextField" min="-2" pref="643" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="Goal1TextField" linkSize="9" min="-2" pref="185" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="Goal2TextField" linkSize="9" min="-2" pref="126" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="BooleanResultTagsComboBox" linkSize="13" min="-2" pref="162" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="PreviousMatchanyComboBox" linkSize="13" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="ValueTextField" linkSize="8" alignment="3" min="-2" pref="44" max="-2" attributes="0"/>
|
||||
<Component id="SubgoalTextField" linkSize="8" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="Goal2TextField" linkSize="8" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="GoalIDTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="GoalTypeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="BooleanTextField" linkSize="10" alignment="3" min="-2" pref="41" max="-2" attributes="0"/>
|
||||
<Component id="Goal1TextField" linkSize="8" alignment="3" min="-2" pref="41" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="OperatorComboBox" linkSize="10" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="ExecutableFileTextField" linkSize="10" alignment="3" min="-2" pref="44" max="-2" attributes="0"/>
|
||||
<Component id="ResultTagComboBox" linkSize="10" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="ArithmeticResultTagTextField" linkSize="10" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="AnswerTypeComboBox" linkSize="10" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="AnswerTagTextField" linkSize="10" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="ResultTag2ComboBox" linkSize="10" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="ParameterComboBox" linkSize="10" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="BooleanResultTagsComboBox" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="PreviousMatchanyComboBox" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="83" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextField" name="GoalIDTextField">
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="GoalTypeComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="goalTypeItemChanged"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ToolTipWrapper>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="OperatorComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Identifies how the line is to be identified"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Operator">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ToolTipWrapper>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="AnswerTagTextField">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Parameter based on Line Type"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="AnswerTag">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="BooleanTextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Boolean">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="Goal1TextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Goal 1">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="Goal2TextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Goal 2">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="ValueTextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Value">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="SubgoalTextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Subgoal List">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="ResultTagComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Result Tag">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="ExecutableFileTextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Executable File">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="ArithmeticResultTagTextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Arithmetic Result Tag">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="AnswerTypeComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Answer Type">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="AnswerTypeComboBoxItemStateChanged"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="ResultTag2ComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="ParameterComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="BooleanResultTagsComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Boolean Result Tags">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="PreviousMatchanyComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="DeleteButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Delete"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="DeleteButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="rowLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="24" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="10"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="UpButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="^"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="UpButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="DownButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="v"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="DownButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -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<String> resultTags;
|
||||
private List<String> parameterIDs;
|
||||
private List<String> 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")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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)))
|
||||
);
|
||||
}// </editor-fold>//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<ToolTipWrapper> getGoalTypeComboBox(){
|
||||
return GoalTypeComboBox;
|
||||
}
|
||||
|
||||
public JComboBox<ToolTipWrapper> getOperatorComboBox(){
|
||||
return OperatorComboBox;
|
||||
}
|
||||
|
||||
public JTextField getExecutableFileTextField(){
|
||||
return ExecutableFileTextField;
|
||||
}
|
||||
|
||||
public JComboBox<String> 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<String> AnswerTypeComboBox;
|
||||
private javax.swing.JTextField ArithmeticResultTagTextField;
|
||||
private javax.swing.JPanel ArtifactPanel;
|
||||
private javax.swing.JComboBox<String> 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<ToolTipWrapper> GoalTypeComboBox;
|
||||
private javax.swing.JComboBox<ToolTipWrapper> OperatorComboBox;
|
||||
private javax.swing.JComboBox<String> ParameterComboBox;
|
||||
private javax.swing.JComboBox<String> PreviousMatchanyComboBox;
|
||||
private javax.swing.JComboBox<String> ResultTag2ComboBox;
|
||||
private javax.swing.JComboBox<String> 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
|
||||
}
|
||||
@@ -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<String> 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<String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="3"/>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ff" green="ff" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1590, 500]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1110, 389]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<Events>
|
||||
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosing"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="ScrollPaneOfGoals" alignment="0" pref="1300" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="CreateButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="RemoveAllButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="98" max="-2" attributes="0"/>
|
||||
<Component id="jLabel9" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="LabNameTextField" min="-2" pref="378" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="LabNotExist" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="344" max="32767" attributes="0"/>
|
||||
<Component id="UpdateButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="89" max="-2" attributes="0"/>
|
||||
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="CreateButton" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="RemoveAllButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel9" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="LabNameTextField" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="UpdateButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="LabNotExist" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ScrollPaneOfGoals" pref="317" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="ScrollPaneOfGoals">
|
||||
<Properties>
|
||||
<Property name="autoscrolls" type="boolean" value="true"/>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1300, 800]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="PanelofGoals">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="3"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="UpdateButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Update"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="UpdateButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="RemoveAllButton">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Dialog" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Remove All"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="RemoveAllButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel9">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial Black" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Lab Name: "/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="CreateButton">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Dialog" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Create"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="CreateButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel3">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Goal Type"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The mode in which a value is found."/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Goal ID"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The symbolic name of the result, which will be referenced in the goals configuration file. 

(It must be alphanumeric, underscores permitted) "/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="LabNameTextField">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[6, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="LabNameTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="LabNotExist">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="14" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Lab does not exist!"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -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")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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();
|
||||
}// </editor-fold>//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 */
|
||||
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
|
||||
/* 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);
|
||||
}
|
||||
//</editor-fold>
|
||||
//</editor-fold>
|
||||
|
||||
//</editor-fold>
|
||||
|
||||
/* 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
|
||||
}
|
||||
@@ -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", "<html>Results from all timestamped sets are evaluated.<br>" +
|
||||
"If the answertag names a result, then both that<br>" +
|
||||
"result and the resulttag must occur in the same<br>" +
|
||||
"timestamped set. The ’matchany’ goals are treated<br>" +
|
||||
"as a set of values, each timestamped based on the<br>" +
|
||||
"timestamp of the reference resulttag.</html>"),
|
||||
// 1
|
||||
new ToolTipWrapper("matchlast", "<html>only results from the latest timestamped set are<br>" +
|
||||
"evaluated.</html>"),
|
||||
// 2
|
||||
new ToolTipWrapper("matchacross", "<html>The resulttag and answertag name results. The<br>" +
|
||||
"operator is applied against values in different<br>" +
|
||||
"timestamped sets. For example, a \"string_diff\"<br>" +
|
||||
"operator would require the named results to have<br>" +
|
||||
"at least two distinct values in different<br>" +
|
||||
"timestamped sets.</html>"),
|
||||
// 3
|
||||
new ToolTipWrapper("boolean", "<html>The goal value is computed from a boolean expression<br>" +
|
||||
"consisting of goal_id’s and boolean operators, (\"and\",<br>" +
|
||||
"\"or\", \"and_not\", \"or_not\", and \"not\"), and parenthisis<br>" +
|
||||
"for precedence. The goal_id’s must be from goals defined<br>" +
|
||||
"earlier in the goals.config file, or boolean results<br>" +
|
||||
"from results.config. The goal evalutes to<br>" +
|
||||
"TRUE if the boolen expression evaluates to TRUE for any<br>" +
|
||||
"of the timestamped sets of goal_ids, (see the ’matchany’<br>" +
|
||||
"discussion above). The goal_id’s cannot include any<br>" +
|
||||
"\"matchacross\" goals. NOTE: evaluation is within<br>" +
|
||||
"timestamped sets. If you want to evaluate across<br>" +
|
||||
"timestamps, use the count_greater_operator below.</html>"),
|
||||
// 4
|
||||
new ToolTipWrapper("count_greater", "<html>The goal is TRUE if the count of TRUE subgoals in the<br>" +
|
||||
"list exceeds the given value. The subgoals are<br>" +
|
||||
"summed across all timestamps. The subgoal list is<br>" +
|
||||
"comma-separated within parenthesis.</html>"),
|
||||
// 5
|
||||
new ToolTipWrapper("time_before", "<html>Both goal1 and goal2 must be goal_ids from previous<br>" +
|
||||
"matchany, or boolean values from results.config<br>" +
|
||||
"A timestamped goal is created for each goal2<br>" +
|
||||
"timestamped instance whose timestamp is proceeded<br>" +
|
||||
"by a goal1 timestamped instance. The goal for that<br>" +
|
||||
"timestamp will be TRUE if the goal2<br>" +
|
||||
"instance is TRUE, and at least one of the goal1<br>" +
|
||||
"instances is TRUE. These timestamped goals can<br>" +
|
||||
"then be evaluated within boolean goals.</html>"),
|
||||
// 6
|
||||
new ToolTipWrapper("time_during", "<html>Both goal1 and goal2 must be goal_ids from previous<br>" +
|
||||
"matchany goal types, or boolean values from<br>" +
|
||||
"results.config. Timestamps include a start and end<br>" +
|
||||
"time, reflecting when the program starts and when it<br>" +
|
||||
"terminates. A timestamped goal is created for each<br>" +
|
||||
"goal2 range that encompasses a goal1 timestamp.<br>" +
|
||||
"The goal for that timestamp will be TRUE if the<br>" +
|
||||
"goal2 instance is TRUE, and at least one goal1 instance<br>" +
|
||||
"is TRUE. These timestamped goals can then be<br>" +
|
||||
"evaluated within boolean goals.</html>"),
|
||||
// 7
|
||||
new ToolTipWrapper("time_not_during", "<html>Similar to time_during, but timestamped goals are<br>" +
|
||||
"always created for each goal2. Each such goal is True<br>" +
|
||||
"unless one or more goal1 times occur within a True goal2<br>" +
|
||||
"range.</html>"),
|
||||
// 8
|
||||
new ToolTipWrapper("execute", "<html>The <operator> is treated as a file name of a script to<br>" +
|
||||
"execute, with the resulttag and answertag passed to the<br>" +
|
||||
"script as arguments. The resulttag is expected to be<br>" +
|
||||
"one of the symbolic names defined in the results.config<br>" +
|
||||
"file, while the answertag is expected to be a literal<br>" +
|
||||
"value or the symbolic name in the parameters.config file<br>" +
|
||||
"Note: the answertag cannot be a symbolic name from<br>" +
|
||||
"results.config</html>"),
|
||||
// 9
|
||||
new ToolTipWrapper("count_value", "<html>If the remainder of the line only includes a resulttag,<br>" +
|
||||
"then the goal value is assigned the quanity of<br>" +
|
||||
"timestamped files containing the given resulttag.<br>" +
|
||||
"Otherwise the goal value is assigned the<br>" +
|
||||
"quantity of timestamped files having results<br>" +
|
||||
"that satisfy the given operator and arguments.</html>"),
|
||||
// 10
|
||||
new ToolTipWrapper("count_matches", "<html>If the remainder of the line only includes a resulttag,<br>" +
|
||||
"then the goal value is assigned the quanity of<br>" +
|
||||
"timestamped files containing the given resulttag.<br>" +
|
||||
"Otherwise the goal value is assigned the<br>" +
|
||||
"quantity of timestamped files having results<br>" +
|
||||
"that satisfy the given operator and arguments.</html>"),
|
||||
// 11
|
||||
new ToolTipWrapper("value", "<html>The goal value is assigned the given resulttag value from<br>" +
|
||||
"the most recent timestamped file that contains the resulttag.</html>"),
|
||||
|
||||
// 12
|
||||
new ToolTipWrapper("matchExpression", "<html>The resultTag is an arithmetic expression</html>")};
|
||||
|
||||
|
||||
public static final ToolTipWrapper[] Operator_ITEMS = new ToolTipWrapper[] {
|
||||
// 0
|
||||
new ToolTipWrapper("string_equal", "<html>The strings derived from answertag and resulttag<br>" +
|
||||
"are equal.</html>"),
|
||||
// 1
|
||||
new ToolTipWrapper("string_diff", "<html>The line_id is an integer line number<br>" +
|
||||
"(starting at one). Use of this to identify<br>" +
|
||||
"lines is discouraged since minor lab changes<br>" +
|
||||
"might alter the count.</html>"),
|
||||
// 2
|
||||
new ToolTipWrapper("string_start", "<html>the line_id is a string. This names the<br>" +
|
||||
"first occurrence of a line that starts with<br>" +
|
||||
"this string.</html>" ),
|
||||
// 3
|
||||
new ToolTipWrapper("string_end", "<html>The line_id is a string. This names the<br>" +
|
||||
"first occurrence of a line that contains the<br>" +
|
||||
"string.</html>" ),
|
||||
// 4
|
||||
new ToolTipWrapper("string_contains", "<html>The line_id is a regular expression. This names the<br>" +
|
||||
"first occurrence of a line that matches the regular<br>" +
|
||||
"expression. Also see the \"GROUP\" field_type.</html>" ),
|
||||
|
||||
// 5
|
||||
new ToolTipWrapper("integer_equal", "<html>The line_id is a regular expression. This names the<br>" +
|
||||
"first occurrence of a line that matches the regular<br>" +
|
||||
"expression. Also see the \"GROUP\" field_type.</html>" ),
|
||||
|
||||
// 6
|
||||
new ToolTipWrapper("integer_greater", "<html>The line_id is a regular expression. This names the<br>" +
|
||||
"first occurrence of a line that matches the regular<br>" +
|
||||
"expression. Also see the \"GROUP\" field_type.</html>" ),
|
||||
|
||||
// 7
|
||||
new ToolTipWrapper("integer_lessthan", "<html>The line_id is a regular expression. This names the<br>" +
|
||||
"first occurrence of a line that matches the regular<br>" +
|
||||
"expression. Also see the \"GROUP\" field_type.</html>" )};
|
||||
|
||||
|
||||
//Answer Types
|
||||
public static final String[] answerTypes = new String[] {
|
||||
"Literal",
|
||||
"Result Tag",
|
||||
"Parameter",
|
||||
"Parameter ASCII"
|
||||
};
|
||||
|
||||
//Boolean Result Types
|
||||
public static final ArrayList<String> booleanResultTypes = new ArrayList<String>(Arrays.asList(
|
||||
"CONTAINS",
|
||||
"FILE_REGEX",
|
||||
"LOG_TS",
|
||||
"FILE_REGEX_TS",
|
||||
"LOG_RANGE",
|
||||
"TIME_DELIM"
|
||||
));
|
||||
|
||||
//Input format 1: [operator : resultTag : answerTag]
|
||||
public static final ArrayList<String> opInput = new ArrayList<String>(Arrays.asList(
|
||||
"matchany",
|
||||
"matchlast",
|
||||
"matchacross",
|
||||
"count_matches"
|
||||
));
|
||||
|
||||
//Input format 2: [goal1 : goal2]
|
||||
public static final ArrayList<String> goalInput = new ArrayList<String>(Arrays.asList(
|
||||
"time_before",
|
||||
"time_during",
|
||||
"time_not_during"
|
||||
));
|
||||
|
||||
//Input format 2: [resultTag]
|
||||
public static final ArrayList<String> resultTagInput = new ArrayList<String>(Arrays.asList(
|
||||
"count_value",
|
||||
"value"
|
||||
));
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="ResultsUIAug30" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project ResultsUIAug30.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar: JAR building
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="ResultsUIAug30-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
||||
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
compile.on.save=true
|
||||
user.properties.file=C:\\Users\\Dan\\AppData\\Roaming\\NetBeans\\8.2\\build.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
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>ResultsUIAug30</name>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
@@ -0,0 +1,283 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1110, 69]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="rowLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="ArtifactPanel" min="-2" pref="1390" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="UpButton" max="32767" attributes="0"/>
|
||||
<Component id="DownButton" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="DeleteButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="ArtifactPanel" min="-2" pref="69" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="rowLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="UpButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="DownButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="DeleteButton" min="-2" pref="58" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="ArtifactPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.SoftBevelBorderInfo">
|
||||
<BevelBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1400, 0]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1300, 34]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="TagTextField" min="-2" pref="125" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ContainerComboBox" min="-2" pref="116" max="-2" attributes="0"/>
|
||||
<EmptySpace min="6" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="FileTextField" min="-2" pref="150" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="FieldTypeComboBox" min="-2" pref="160" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="FieldIDTextField" min="-2" pref="188" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
|
||||
<Component id="LineTypeComboBox" min="-2" pref="165" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="LineIDTextField" min="-2" pref="135" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="TimeStampComboBox" min="-2" pref="137" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="TimeDelimiterTextField" min="-2" pref="125" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="TagTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="ContainerComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="FileTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="FieldTypeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" max="-2" attributes="0">
|
||||
<Component id="LineTypeComboBox" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="LineIDTextField" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="TimeStampComboBox" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="FieldIDTextField" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="TimeDelimiterTextField" linkSize="2" alignment="3" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="12" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextField" name="TagTextField">
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="ContainerComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="FileTextField">
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="FieldTypeComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="FieldTypeComboBoxItemStateChanged"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ToolTipWrapper>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="LineTypeComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Identifies how the line is to be identified"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Line Type">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="LineTypeComboBoxItemStateChanged"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ToolTipWrapper>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="FieldIDTextField">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Field ID">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="LineIDTextField">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Parameter based on Line Type"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Line ID">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="TimeStampComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Timestamp Type">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="TimeStampComboBoxItemStateChanged"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ToolTipWrapper>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="TimeDelimiterTextField">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Time Delimiter">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[20, 100]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="DeleteButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Delete"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="DeleteButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="rowLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="24" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="10"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="UpButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="^"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="UpButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="DownButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="v"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="DownButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -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<String> 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<String> 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")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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))
|
||||
);
|
||||
}// </editor-fold>//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<String> getContainerComboBox(){
|
||||
return ContainerComboBox;
|
||||
}
|
||||
public JTextField getFieldIDTextField(){
|
||||
return FieldIDTextField;
|
||||
}
|
||||
public JTextField getTagTextField(){
|
||||
return TagTextField;
|
||||
}
|
||||
public JTextField getFileTextField(){
|
||||
return FileTextField;
|
||||
}
|
||||
public JComboBox<ToolTipWrapper> getFieldTypeComboBox(){
|
||||
return FieldTypeComboBox;
|
||||
}
|
||||
public JTextField getLineIDTextField(){
|
||||
return LineIDTextField;
|
||||
}
|
||||
public JComboBox<ToolTipWrapper> getLineTypeComboBox(){
|
||||
return LineTypeComboBox;
|
||||
}
|
||||
public JComboBox<ToolTipWrapper> 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<String> ContainerComboBox;
|
||||
private javax.swing.JButton DeleteButton;
|
||||
private javax.swing.JButton DownButton;
|
||||
private javax.swing.JTextField FieldIDTextField;
|
||||
private javax.swing.JComboBox<ToolTipWrapper> FieldTypeComboBox;
|
||||
private javax.swing.JTextField FileTextField;
|
||||
private javax.swing.JTextField LineIDTextField;
|
||||
private javax.swing.JComboBox<ToolTipWrapper> LineTypeComboBox;
|
||||
private javax.swing.JTextField TagTextField;
|
||||
private javax.swing.JTextField TimeDelimiterTextField;
|
||||
private javax.swing.JComboBox<ToolTipWrapper> TimeStampComboBox;
|
||||
private javax.swing.JButton UpButton;
|
||||
private javax.swing.JLabel rowLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
@@ -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<paramParsedLine.length && !itemExistCheck(LineType_ITEMS,paramParsedLine[i]); i++){
|
||||
fieldID+=paramParsedLine[i];
|
||||
if(i<(paramParsedLine.length-1) && !itemExistCheck(LineType_ITEMS,paramParsedLine[i+1])){
|
||||
properLineTypeIndex++;
|
||||
fieldID+=" : ";
|
||||
}
|
||||
}
|
||||
|
||||
//If properLineTypeIndex < paramParsedLine.length then that means the line type and line id was written in the config file
|
||||
if(properLineTypeIndex < paramParsedLine.length){
|
||||
lineType = itemFinder(LineType_ITEMS, paramParsedLine[properLineTypeIndex]);
|
||||
//If line type is null after searching though the LineType_ITEMS then the value could possibly be a special line type
|
||||
if(lineType == null)
|
||||
lineType = itemFinder(SpecialTimeStampType, paramParsedLine[properLineTypeIndex]);
|
||||
|
||||
//Special LineType cases
|
||||
if((lineType.getItem()).equals("HAVESTRING_TS")){
|
||||
lineType = LineType_ITEMS[3]; //HAVESTRING
|
||||
timeStampType = SpecialTimeStampType[0]; //LOG_TS
|
||||
}
|
||||
else if((lineType.getItem()).equals("REGEX_TS")){
|
||||
lineType = LineType_ITEMS[4]; //REGEX
|
||||
timeStampType = SpecialTimeStampType[0]; //LOG_TS
|
||||
}
|
||||
|
||||
|
||||
//accomplishes the same thing in the for-block below but more simply (Gets everything after the lineType as the lineID)
|
||||
lineID = artifactLine.split(lineType.getItem() + " : ")[1];
|
||||
|
||||
|
||||
/*The Line ID may include " : ". 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=properLineTypeIndex+1; i<paramParsedLine.length; i++){
|
||||
lineID+=paramParsedLine[i];
|
||||
if(i<(paramParsedLine.length-1)){
|
||||
lineID+=" : ";
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else{
|
||||
lineType = LineType_ITEMS[0]; //NONE
|
||||
lineID = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
fieldID = "";
|
||||
lineType = LineType_ITEMS[0]; //NONE
|
||||
lineID = "";
|
||||
timeStampType = TimestampType_ITEMS[0]; //File
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Constructor for temporarily storing values of artifacts in the UI
|
||||
ArtifactValues(String resultTag, String container, String fileID, ToolTipHandlers.ToolTipWrapper fieldType, String fieldID, ToolTipHandlers.ToolTipWrapper lineType, String lineID, ToolTipHandlers.ToolTipWrapper timeStampType, String timeStampDelimiter){
|
||||
this.resultTag = resultTag;
|
||||
this.container = container;
|
||||
this.fileID = fileID;
|
||||
this.fieldType = fieldType;
|
||||
this.fieldID = fieldID;
|
||||
this.lineType = lineType;
|
||||
this.lineID = lineID;
|
||||
this.timeStampType = timeStampType;
|
||||
this.timeStampDelimiter = timeStampDelimiter;
|
||||
}
|
||||
|
||||
private void handleFileRef(String fileRef){
|
||||
//Case 1: <prog>.[stdin | stdout | prgout] or file_path
|
||||
if(!fileRef.contains(":")){
|
||||
container = "ALL";
|
||||
fileID = fileRef;
|
||||
timeStampType = TimestampType_ITEMS[0]; //File
|
||||
}
|
||||
//Case 2: [container_name:]<prog>.[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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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", "<html>Treat the line as space-delimited tokens.</html>"),
|
||||
// 1
|
||||
new ToolTipWrapper("PARENS", "<html>The desired value is contained in parenthesis.</html>"),
|
||||
// 2
|
||||
new ToolTipWrapper("QUOTES", "<html>The desired value is contained in quotes.</html>"),
|
||||
// 3
|
||||
new ToolTipWrapper("SLASH", "<html>The desired value is contained within slashes<br>" +
|
||||
"e.g., /foo/</html>"),
|
||||
// 4
|
||||
new ToolTipWrapper("LINE_COUNT", "<html>The quantity of lines in the file. Remaining fields<br>" +
|
||||
"are ignored.</html>"),
|
||||
// 5
|
||||
new ToolTipWrapper("CHECKSUM", "<html>The result value is set to the md5 checksum<br>" +
|
||||
"of the file.</html>"),
|
||||
// 6
|
||||
new ToolTipWrapper("CONTAINS", "<html>The result value is set to TRUE if the file<br>" +
|
||||
"contains the string represented in field_id.</html>"),
|
||||
// 7
|
||||
new ToolTipWrapper("FILE_REGEX", "<html>The result value is set to TRUE if the file<br>" +
|
||||
"contains the regular expression represented in field_id.<br>" +
|
||||
"The python findall function is used on the entire file.<br>" +
|
||||
"See the acl lab for an example of multi-line expressions.</html>"),
|
||||
// 8
|
||||
new ToolTipWrapper("STRING_COUNT", "<html>The result value is set to the quantity of<br>" +
|
||||
"occurances of the string represented in field_id.</html>"),
|
||||
// 9
|
||||
new ToolTipWrapper("COMMAND_COUNT", "<html>Intended for use with bash_history files, counts<br>" +
|
||||
"the occurances of the command given in the field_id.<br>"),
|
||||
// 10
|
||||
new ToolTipWrapper("PARAM", "<html>The result value is set to nth parameter<br>" +
|
||||
"(0 is the program name), provided in the<br>" +
|
||||
"program invocation.</html>"),
|
||||
// 11
|
||||
new ToolTipWrapper("SEARCH", "<html>The result is assigned the value of the search<br>" +
|
||||
"defined by the given field_id, which is treated as an<br>" +
|
||||
"expression having the syntax of pythons parse.search<br>" +
|
||||
"function. E.g., \"frame.number=={:d}\" would<br>" +
|
||||
"yield the frame number.</html>"),
|
||||
// 12
|
||||
new ToolTipWrapper("GROUP", "<html>Intended for use with \"REGEX\" line types, the<br>" +
|
||||
"result is set to the value of the regex group<br>" +
|
||||
"number named by the field_id. Regular expressions<br>" +
|
||||
"and their groups are processed using the python<br>" +
|
||||
"re.search semantics.</html>" ),
|
||||
// 13
|
||||
new ToolTipWrapper("TIME_DELIM", "" )};
|
||||
|
||||
|
||||
public static final ToolTipWrapper[] LineType_ITEMS = new ToolTipWrapper[] {
|
||||
// 0
|
||||
new ToolTipWrapper("NONE", ""),
|
||||
// 1
|
||||
new ToolTipWrapper("LINE", "<html>The line_id is an integer line number<br>" +
|
||||
"(starting at one). Use of this to identify<br>" +
|
||||
"lines is discouraged since minor lab changes<br>" +
|
||||
"might alter the count.</html>"),
|
||||
// 2
|
||||
new ToolTipWrapper("STARTSWITH", "<html>the line_id is a string. This names the<br>" +
|
||||
"first occurrence of a line that starts with<br>" +
|
||||
"this string.</html>" ),
|
||||
// 3
|
||||
new ToolTipWrapper("HAVESTRING", "<html>The line_id is a string. This names the<br>" +
|
||||
"first occurrence of a line that contains the<br>" +
|
||||
"string.</html>" ),
|
||||
// 4
|
||||
new ToolTipWrapper("REGEX", "<html>The line_id is a regular expression. This names the<br>" +
|
||||
"first occurrence of a line that matches the regular<br>" +
|
||||
"expression. Also see the \"GROUP\" field_type.</html>" ),
|
||||
// 5
|
||||
new ToolTipWrapper("NEXT_STARTSWITH", "<html>the line_id is a string. This names the<br>" +
|
||||
"line preceeding the first occurrence of a line<br>" +
|
||||
"that starts with this string.</html>")};
|
||||
|
||||
|
||||
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", "<html>Used with timestamped log files, this results in a<br>" +
|
||||
"timestamped set of boolean results with a value<br>" +
|
||||
"of TRUE for each log line that contains the string<br>" +
|
||||
"represented in the field_id.</html>"),
|
||||
// 1
|
||||
new ToolTipWrapper("LOG_RANGE", "<html>Similar to LOG_TS, except the timestamped entries<br>" +
|
||||
"are ranges delimited by the matching log entries.</html>"),
|
||||
// 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<String> LOG_ACCESIBLE_FieldType = new HashSet<String>(Arrays.asList(
|
||||
new String[] {"CONTAINS", "FILE_REGEX", "SEARCH"}
|
||||
));
|
||||
|
||||
public static final Set<String> LOG_TS_ACCESSIBLE_LineType = new HashSet<String>(Arrays.asList(
|
||||
new String[] {"HAVESTRING", "REGEX"}
|
||||
));
|
||||
|
||||
public static final Set<String> lineParamAccessible = new HashSet<String>(Arrays.asList(
|
||||
new String[] {"TOKEN", "PARENS", "QUOTES", "SLASH", "GROUP", "SEARCH"}
|
||||
));
|
||||
|
||||
|
||||
public static final Set<String> justFieldType = new HashSet<String>(Arrays.asList(
|
||||
new String[] {"LINE_COUNT", "CHECKSUM", "TIME_DELIM"}
|
||||
));
|
||||
|
||||
|
||||
public static final Set<String> timeStampDelimiterAccessible = new HashSet<String>(Arrays.asList(
|
||||
new String[] {"Service", "Program"}
|
||||
));
|
||||
}
|
||||
@@ -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<ArtifactValues> listofArtifacts;
|
||||
ArrayList<String> 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<String> 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<String> 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 <prog>.[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<String> resultTags){
|
||||
ArrayList<ResultTagIndices> markedResultTags = new ArrayList<>();
|
||||
|
||||
//Store all the indices for each unique result tag
|
||||
for(int i=0;i<resultTags.size();i++){
|
||||
String resultTag = resultTags.get(i);
|
||||
//Is the resultTag a duplicate?
|
||||
//If so, add the the index number of the duplicate result tag to the corresponding result tag's list of indices
|
||||
if(isDuplicate(markedResultTags, resultTag)){
|
||||
getDuplicate(markedResultTags, resultTag).addIndex(i);
|
||||
}
|
||||
//If not, add it to the markedResultTags fresh
|
||||
else
|
||||
markedResultTags.add(new ResultTagIndices(resultTag, i));
|
||||
}
|
||||
|
||||
//Go through every result tag and see if any of them have more than 1 index, if they do then create a custom error message for the duplicate result tag
|
||||
String duplicateErrorMsg = "";
|
||||
for(ResultTagIndices rt : markedResultTags){
|
||||
if(rt.indices.size() > 1){
|
||||
duplicateErrorMsg+= "Duplicate Result Tag: \"" + rt.resultTag + "\" on rows ";
|
||||
|
||||
for(int i=0;i<rt.indices.size();i++){
|
||||
duplicateErrorMsg+=(rt.indices.get(i)+1); //The plus 1 offset to get the 1-based row num
|
||||
|
||||
if(rt.indices.size() == 2 && i == 0)
|
||||
duplicateErrorMsg+=" and ";
|
||||
else if(i == rt.indices.size()-1)
|
||||
duplicateErrorMsg+=".";
|
||||
else{
|
||||
duplicateErrorMsg+=", ";
|
||||
if(i == rt.indices.size()-2)
|
||||
duplicateErrorMsg+="and ";
|
||||
}
|
||||
}
|
||||
duplicateErrorMsg+=System.lineSeparator();
|
||||
overallPass = false;
|
||||
}
|
||||
}
|
||||
errorMsg+=duplicateErrorMsg;
|
||||
|
||||
}
|
||||
|
||||
//Stores a result tag's name and the row index they appear on
|
||||
class ResultTagIndices{
|
||||
protected String resultTag;
|
||||
protected ArrayList<Integer> 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<ResultTagIndices> 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<ResultTagIndices> 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<String> getArtifactLines(){
|
||||
ArrayList<String> 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<ArtifactValues> 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<ArtifactValues> getArtifactValuesOfConfigFile(){
|
||||
List<ArtifactValues> officialListofArtifacts = new ArrayList<>();
|
||||
|
||||
ArrayList<String> 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<ArtifactValues> list1, List<ArtifactValues> 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.size();i++){
|
||||
printlistValues(list1, list2, i);
|
||||
if(!list1.get(i).container.equals(list2.get(i).container))
|
||||
return true;
|
||||
else if(!list1.get(i).fieldID.equals(list2.get(i).fieldID))
|
||||
return true;
|
||||
else if(!list1.get(i).fieldType.getItem().equals(list2.get(i).fieldType.getItem()))
|
||||
return true;
|
||||
else if(!list1.get(i).fileID.equals(list2.get(i).fileID))
|
||||
return true;
|
||||
else if(!list1.get(i).lineID.equals(list2.get(i).lineID))
|
||||
return true;
|
||||
else if(!list1.get(i).lineType.getItem().equals(list2.get(i).lineType.getItem()))
|
||||
return true;
|
||||
else if(!list1.get(i).resultTag.equals(list2.get(i).resultTag))
|
||||
return true;
|
||||
else if(!list1.get(i).timeStampDelimiter.equals(list2.get(i).timeStampDelimiter))
|
||||
return true;
|
||||
else if(!list1.get(i).timeStampType.getItem().equals(list2.get(i).timeStampType.getItem()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Used for debugging in the artifactValuesDiffer(List<ArtifactValues> list1, List<ArtifactValues> list2) method
|
||||
static private void printlistValues(List<ArtifactValues> list1, List<ArtifactValues> 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<ArtifactValues> getListofArtifacts(){
|
||||
return listofArtifacts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="3"/>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ff" green="ff" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1590, 500]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1585, 389]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<Events>
|
||||
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosing"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="CreateButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="RemoveAllButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="98" max="-2" attributes="0"/>
|
||||
<Component id="jLabel9" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="LabNameTextField" min="-2" pref="378" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="LabNotExist" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="344" max="32767" attributes="0"/>
|
||||
<Component id="UpdateButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="ScrollPaneOfArtifacts" alignment="0" pref="1300" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="60" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="74" max="-2" attributes="0"/>
|
||||
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="66" max="-2" attributes="0"/>
|
||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="131" max="-2" attributes="0"/>
|
||||
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="CreateButton" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="RemoveAllButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel9" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="LabNameTextField" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="UpdateButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="LabNotExist" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ScrollPaneOfArtifacts" pref="317" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="ScrollPaneOfArtifacts">
|
||||
<Properties>
|
||||
<Property name="autoscrolls" type="boolean" value="true"/>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1300, 800]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="PanelofArtifacts">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="3"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="UpdateButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Update"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="UpdateButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel2">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Container"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Identifies the container hosting the file. 
If "ALL" is selected, then the file is across all the containers."/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="RemoveAllButton">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Dialog" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Remove All"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="RemoveAllButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel9">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial Black" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Lab Name: "/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="CreateButton">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Dialog" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Create"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="CreateButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel3">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Field Type"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The mode in which a value is found."/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel5">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="File"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="File should either be a file path or a program/utility name with the ".stdin", ".stdout", or ".prgout" extension.

 Ex. "test.stdin", ".local/result/sniff.txt" "/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Arial" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Result Tag"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The symbolic name of the result, which will be referenced in the goals configuration file. 

(It must be alphanumeric, underscores permitted) "/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="LabNameTextField">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[6, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="LabNameTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="LabNotExist">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="14" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Lab does not exist!"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -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")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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();
|
||||
}// </editor-fold>//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 */
|
||||
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
|
||||
/* 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);
|
||||
}
|
||||
//</editor-fold>
|
||||
//</editor-fold>
|
||||
//</editor-fold>
|
||||
//</editor-fold>
|
||||
|
||||
//</editor-fold>
|
||||
|
||||
/* 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
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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())
|
||||
@@ -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)
|
||||
|
||||
@@ -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) <linux@rodrigosilva.com>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
#
|
||||
# Stripped-down version: no fancy options or statistics. Just the core!
|
||||
#
|
||||
# Only works from inside the work tree. Assumes git dir is "<toplevel>/.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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
81
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkTars.sh
Executable file
81
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkTars.sh
Executable file
@@ -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
|
||||
96
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkdist.sh
Executable file
96
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mkdist.sh
Executable file
@@ -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
|
||||
24
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mktest.sh
Executable file
24
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/mktest.sh
Executable file
@@ -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/
|
||||
191
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish.py
Executable file
191
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/publish.py
Executable file
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
22
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/relabel.sh
Executable file
22
modules/utilities/unix/labtainers/files/Labtainers-master/distrib/relabel.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
REGISTRY=$1
|
||||
VERSION=$2
|
||||
IMAGE=$3
|
||||
BASE_IMAGE=$4
|
||||
BASE_ID=$5
|
||||
|
||||
cat <<EOT > 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
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
@@ -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
|
||||
@@ -0,0 +1,6 @@
|
||||
development.pdf: development.tex
|
||||
latex development
|
||||
pdflatex development
|
||||
clean:
|
||||
rm -fr auto
|
||||
rm -fr development.aux development.pdf
|
||||
@@ -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.
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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}}
|
||||
Binary file not shown.
@@ -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: <same size as paper>
|
||||
* 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
|
||||
<to be read again>
|
||||
\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
|
||||
</usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb></us
|
||||
r/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb></usr/share
|
||||
/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb></usr/share/texliv
|
||||
e/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb></usr/share/texlive/texm
|
||||
f-dist/fonts/type1/public/amsfonts/cm/cmti12.pfb></usr/share/texlive/texmf-dist
|
||||
/fonts/type1/public/amsfonts/cm/cmtt12.pfb>
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
Binary file not shown.
@@ -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/<labname>
|
||||
\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/<lab>/. 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}
|
||||
@@ -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}
|
||||
@@ -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
|
||||
|
||||
@@ -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/<labname>/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.
|
||||
@@ -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 '<labname>.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 '<labname>.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 '<labname>.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 (<labname>.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).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user