13 Commits
v2.4 ... v2.6

13 changed files with 106 additions and 164 deletions

View File

@ -0,0 +1,14 @@
branch-defaults:
master:
environment: new-life-songs-prod
global:
application_name: new-life-songs
branch: null
default_ec2_keyname: id_jdb@jdb-maingear
default_platform: Tomcat 8 Java 8
default_region: us-west-2
profile: eb-cli
repository: null
sc: git
deploy:
artifact: build/ROOT.war

View File

@ -1,48 +1,56 @@
import org.apache.tools.ant.filters.ReplaceTokens
buildscript {
repositories {
maven { url 'https://mvn.jdb-labs.com/repo' }
}
dependencies {
classpath 'com.jdbernard:gradle-exec-util:0.2.0'
}
}
plugins { id 'com.palantir.git-version' version '0.5.2' }
apply plugin: "groovy"
apply plugin: "maven"
apply plugin: "war"
apply plugin: "jetty"
apply from: 'shell.gradle'
group = "com.jdbernard"
version = new ProjectVersion()
import static com.jdbernard.gradle.ExecUtil.*
version = gitVersion()
// webAppDirName = "build/webapp/main"
repositories {
mavenLocal()
mavenCentral() }
mavenCentral()
}
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.2'
compile 'ch.qos.logback:logback-core:1.1.2'
compile 'com.impossibl.pgjdbc-ng:pgjdbc-ng:0.3'
compile 'ch.qos.logback:logback-classic:1.1.8'
compile 'ch.qos.logback:logback-core:1.1.8'
compile 'com.impossibl.pgjdbc-ng:pgjdbc-ng:0.6'
compile 'com.lambdaworks:scrypt:1.4.0'
compile 'com.zaxxer:HikariCP-java6:2.3.2'
compile 'com.zaxxer:HikariCP:2.5.1'
compile 'javax:javaee-api:7.0'
compile 'javax.ws.rs:javax.ws.rs-api:2.0.1'
compile 'joda-time:joda-time:2.7'
compile 'org.codehaus.groovy:groovy-all:2.3.6'
compile 'org.slf4j:slf4j-api:1.7.10'
compile 'org.codehaus.groovy:groovy-all:2.4.7'
compile 'org.slf4j:slf4j-api:1.7.22'
runtime 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.3.2'
runtime 'org.glassfish.jersey.containers:jersey-container-servlet:2.16'
runtime 'org.glassfish.jersey.media:jersey-media-json-jackson:2.16'
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
testCompile 'com.jdbernard:jdb-util:3.4'
testCompile 'junit:junit:4.12'
testRuntime 'com.h2database:h2:1.4.186'
}
war {
from "resources/webapp"
from "build/webapp"
version = project.version.releaseVersion
filter(ReplaceTokens, tokens: [version: version])
rename '(.+)(\\..*(css|js))', '$1-' + version + '$2'
webInf { from 'resources/main/WEB-INF' }
@ -53,7 +61,6 @@ test { testLogging { events 'failed' } }
task testWar(type: War) {
from 'resources/webapp'
version = project.version.releaseVersion
filter(ReplaceTokens, tokens: [version: version])
rename '(.+)(\\..*(css|js))', '$1-' + version + '$2'
webInf { from 'resources/test/WEB-INF' }
@ -71,99 +78,15 @@ task compileScss(
war.dependsOn compileScss
testWar.dependsOn compileScss
// ## Build Versioning task
task incrementBuildNumber(
group: 'versioning',
description: "Increment the project's build number."
) << { ++version.build }
task deployProd(dependsOn: ['build']) { doLast {
def warName = "${project.name}-${version}.war"
def artifactName = "ROOT.war"
task incrementMinorNumber(
group: 'versioning',
description: "Increment the project's minor version number."
) << { ++version.minor }
task incrementMajorNumber(
group: 'versioning',
description: "Increment the project's major version number."
) << { ++version.major }
task markReleaseBuild(
group: 'versioning',
description: "Mark this version of the project as a release version."
) << { version.release = true }
war.dependsOn << incrementBuildNumber
testWar.dependsOn << incrementBuildNumber
// ## Custom tasks for local deployment
task deployLocal(dependsOn: ['build']) << {
def warName = "${project.name}-${version.releaseVersion}.war"
def jettyHome = System.getenv("JETTY_HOME")
def deployedWar = new File("$jettyHome/webapps/$warName")
if (deployedWar.exists()) deployedWar.delete();
copy {
from "build/libs"
into "$jettyHome/webapps"
include warName } }
into "build"
include warName
rename warName, artifactName }
task killJettyLocal() << {
def pidFile = new File(System.properties['user.home'] + "/temp/jetty.pid")
println "Killing old Jetty instance."
shell_("sh", "-c", 'kill $(jps -l | grep start.jar | cut -f 1 -d " ")') }
task localJetty(dependsOn: ['killJettyLocal', 'deployLocal']) << {
spawn(["java", "-jar", "start.jar"], new File(jettyHome)) }
// ## Project Version
class ProjectVersion {
private File versionFile
int major
int minor
int build
boolean release
public ProjectVersion() { this(new File('version.properties')) }
public ProjectVersion(File versionFile) {
this.versionFile = versionFile
if (!versionFile.exists()) {
versionFile.createNewFile()
this.major = this.minor = this.build = 0
this.save() }
else this.load() }
@Override String toString() { "$major.$minor${release ? '' : '-build' + build}" }
public String getReleaseVersion() { "$major.$minor" }
public void setRelease(boolean release) { this.release = release; save() }
public void setMajor(int major) {
this.major = major; minor = build = 0; release = false; save() }
public void setMinor(int minor) {
this.minor = minor; build = 0; release = false; save() }
public void setBuild(int build) { this.build = build; save() }
private void save() {
def props = new Properties()
versionFile.withInputStream { props.load(it) }
["major", "minor", "build"].each { props[it] = this[it].toString() }
props["version.release"] = release.toString()
versionFile.withOutputStream { props.store(it, "") } }
private void load() {
def props = new Properties()
versionFile.withInputStream { props.load(it) }
["major", "minor", "build"].each {
this[it] = props[it] ? props[it] as int : 0 }
release = Boolean.parseBoolean(props["version.release"]) }
}
exec("eb", "deploy", "-l", "${project.name}-${version}")
} }

View File

@ -0,0 +1,18 @@
import ch.qos.logback.core.*;
import ch.qos.logback.core.encoder.*;
import ch.qos.logback.core.read.*;
import ch.qos.logback.core.rolling.*;
import ch.qos.logback.core.status.*;
import ch.qos.logback.classic.net.*;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
appender("STDOUT", ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%level %logger - %msg%n"
}
}
root(INFO, ["STDOUT"])
logger('com.jdbernard', INFO)

View File

@ -1,33 +0,0 @@
// ## Utility methods for working with processes.
def shell_(List<String> cmd) { shell(cmd, null, false) }
def shell_(String... cmd) { shell(cmd, null, false) }
def shell(String... cmd) { shell(cmd, null, true) }
def shell(List<String> cmd, File workingDir, boolean checkExit) {
shell(cmd as String[], workingDir, checkExit) }
def shell(String[] cmd, File workingDir, boolean checkExit) {
def pb = new ProcessBuilder(cmd)
if (workingDir) pb.directory(workingDir)
def process = pb.start()
process.waitForProcessOutput(System.out, System.err)
if (process.exitValue() != 0)
println "Command $cmd exited with non-zero result code."
if (checkExit) assert process.exitValue() == 0 : "Not ignoring failed command." }
def shell(List<List<String>> cmds, File workingDir) {
cmds.each {
ProcessBuilder pb = new ProcessBuilder(it)
pb.directory(workingDir)
pb.start().waitForProcessOutput(System.out, System.err) } }
def spawn(String... cmd) { spawn(cmd, null) }
def spawn(List<String> cmd, File workingDir) { spawn(cmd as String[], workingDir) }
def spawn(String[] cmd, File workingDir) {
def pb = new ProcessBuilder(cmd)
if (workingDir) pb.directory(workingDir)
def process = pb.start() }

View File

@ -27,10 +27,7 @@ public class NLSongsDB {
/// ### Common
public def save(def model) {
if (model.id > 0) return update(model)
else {
if (create(model) > 0) return model
else return null } }
else return create(model) }
/// ### Services
public Service findService(int id) {

View File

@ -16,7 +16,7 @@ public class Service implements Serializable {
Service that = (Service) thatObj
return (this.id == that.id &&
this.date == (that.@date) &&
this.date == (that.localDate) &&
this.serviceType == that.serviceType) }
public void setDate(Date date) { this.date = LocalDate.fromDateFields(date) }
@ -26,4 +26,8 @@ public class Service implements Serializable {
public Date getDate() { return this.date.toDate() }
public String toString() { return "$id: $date - $serviceType" }
// Needed only because the @directFieldAccesor syntax stopped working in
// Groovy 2.4.7
private LocalDate getLocalDate() { return this.date }
}

View File

@ -11,7 +11,7 @@ public class NLSongsContext {
public static String mediaBaseUrl
public static String makeUrl(Service service, Song song) {
return mediaBaseUrl + '/' + service.@date.toString('yyyy-MM-dd') + '_' +
return mediaBaseUrl + '/' + service.localDate.toString('yyyy-MM-dd') + '_' +
service.serviceType.name().toLowerCase() + '_' +
song.name.replaceAll(/[\s'"\\\/\?!]/, '') + '.mp3' }
}

View File

@ -9,20 +9,40 @@ import com.jdbernard.nlsongs.db.NLSongsDB
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import org.slf4j.Logger
import org.slf4j.LoggerFactory
public final class NLSongsContextListener implements ServletContextListener {
private static final log = LoggerFactory.getLogger(NLSongsContextListener)
public void contextInitialized(ServletContextEvent event) {
def context = event.servletContext
// Load the context configuration.
Properties props = new Properties()
// Load configuration details from the context configuration.
NLSongsContextListener.getResourceAsStream(
context.getInitParameter('context.config.file')).withStream { is ->
props.load(is) }
context.getInitParameter('context.config.file'))
.withStream { is -> props.load(is) }
// Load database configuration
Properties dataSourceProps = new Properties()
String dbConfigFile = context.getInitParameter('datasource.config.file')
if (dbConfigFile) {
NLSongsContextListener.getResourceAsStream(dbConfigFile)
.withStream { is -> dataSourceProps.load(is) } }
// Load database configuration from environment variables (may
// override settings in file).
System.properties.keySet().findAll { it.startsWith('DB_') }.each { key ->
dataSourceProps["dataSource.${key.substring(3)}"] = System.properties[key] }
log.debug("Database configuration: {}", dataSourceProps)
// Create the pooled data source
HikariConfig hcfg = new HikariConfig(
context.getInitParameter('datasource.config.file'))
HikariConfig hcfg = new HikariConfig(dataSourceProps)
HikariDataSource hds = new HikariDataSource(hcfg)

View File

@ -22,7 +22,7 @@ if (!service) { response.sendError(response.SC_NOT_FOUND); return }
<meta name="referrer" content="origin">
<link rel="shortcut icon" href="../images/favicon.ico">
<title><%= service.@date.toString("yyyy-MM-dd")
<title><%= service.localDate.toString("yyyy-MM-dd")
%> (<%= service.serviceType.displayName %>) - New Life Songs Database</title>
<script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<!--<script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js"></script>-->
@ -38,7 +38,7 @@ if (!service) { response.sendError(response.SC_NOT_FOUND); return }
<body>
<header>
<h1><a href="../">New Life Songs</a></h1>
<h2 class=service-desc><%= service.@date.toString("yyyy-MM-dd") %>: (<%=
<h2 class=service-desc><%= service.localDate.toString("yyyy-MM-dd") %>: (<%=
service.description ?: service.serviceType.displayName %>)</h2>
<nav><ul>

View File

@ -44,7 +44,7 @@ songsDB = NLSongsContext.songsDB
<tbody>
<% songsDB.findAllServices().sort { it.date }.reverse().each { service -> %>
<tr><td class=date><a href="../service/<%= service.id %>"><%=
service.@date.toString("yyyy-MM-dd") %></a></td>
service.localDate.toString("yyyy-MM-dd") %></a></td>
<td class=service-type><%= service.description ?:
service.serviceType.displayName %></td></tr><% } %>
</tbody>

View File

@ -67,7 +67,7 @@ if (!song) { response.sendError(response.SC_NOT_FOUND); return }
sort { it.svc.date }.each { row -> %>
<tr><td class=actions><a href='<%= NLSongsContext.makeUrl(row.svc, song) %>'><i class="fa fa-download"></i></a></td>
<td class=performance-date><a href='../service/<%= row.svc.id %>'><%=
row.svc.@date.toString("yyyy-MM-dd") %></a></td>
row.svc.localDate.toString("yyyy-MM-dd") %></a></td>
<td class=service-type><%= row.svc.serviceType.displayName %></td>
<td class=not-small><%= row.perf.leader ?: "" %></td>
<td class=not-small><%= row.perf.pianist ?: "" %></td>

View File

@ -1,6 +1,5 @@
package com.jdbernard.nlsongs.rest
import com.jdbernard.net.HttpContext
import org.junit.Test
import org.junit.AfterClass
import org.junit.BeforeClass

View File

@ -1,6 +1,6 @@
#
#Tue Jul 21 19:08:16 CDT 2015
#Sat Dec 17 21:52:48 CST 2016
major=2
version.release=true
minor=4
build=6
minor=5
build=2