Wednesday, June 14, 2017

Jekyll Pages List

Getting a list of pages in a Jekyll site is easy, but paring that down to just the top-level files and the index pages is tricky.

{% for page in site.pages
  %}{% assign url = page.url | slice: 1, 100
  %}{% assign last_char = page.url | slice: -1
  %}{% if url contains "/" and last_char != "/" %}{% assign subpage = true %}{% else %}{% assign subpage = false %}{% endif
  %}{% unless subpage == true or url == "" or url == "feed.xml"
  %}
* [{{ page.title }}]({{ page.url | relativeurl }})  {% endunless
%}{% endfor %}

Wednesday, May 24, 2017

File timestamp reset

I had a bunch of old MS Word docs that I wanted to convert to PDFs. I did it in LibreOffice, but the new PDFs were all new - I wanted them to have the same timestamps as the Word docs.

Also, just opening the Word docs in LibreOffice updated their modification times. So what I wanted to do was get the original creation time for each Word doc, and use that to set the creation and modification times for both the Word doc and its corresponding PDF file.

This does that:

IFS=     ; for x in *.doc ; do y=${x%.doc}.pdf ; d=`stat -c %W $x` ; touch -d @$d $x $y ; done

The character after IFS= is a tab, which you can insert by typing ctrl-v TAB.

Friday, June 12, 2015

CORS in Jetty & Jersey

To enable cross-origin requests in a self-contained Jetty jar file with Jersey REST services (to allow calls from Swagger-UI). Create a CORSResponseFilter class:
public class CORSResponseFilter implements ContainerResponseFilter {

    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
            throws IOException {

        MultivaluedMap headers = responseContext.getHeaders();

        headers.add("Access-Control-Allow-Origin", "*");
        //headers.add("Access-Control-Allow-Origin", "http://podcastpedia.org"); //allows CORS requests only coming from podcastpedia.org
        headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        headers.add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, X-Codingpedia");
    }

}
And reference it in your main App class:
public class App {
    public static void main(String[] args) throws Exception {
        URI baseUri = UriBuilder.fromUri("http://localhost/").port(8080).build();
        ResourceConfig config = new ResourceConfig(API.class);
        config.register(CORSResponseFilter.class);
        Server jettyServer = JettyHttpContainerFactory.createServer(baseUri, config);

        try {
            jettyServer.start();
            jettyServer.join();
        } finally {
            jettyServer.destroy();
        }
    }
}

Tuesday, May 12, 2015

Script Directory in Bash

Different ways for a Bash script to get the directory it's in. Some work better than others.

To set up the demo environment:

mkdir -p ~/tmp/dir_demo
cd ~/tmp
ln -s dir_demo/ alt_dir_demo
cd alt_dir_demo

# save the following script as dir_demo.sh

ln -s dir_demo.sh alt_demo.sh
. alt_demo.sh 
# $0 only works if this script is invoked directly as an executable,
# not sourced with `. dir_demo.sh`
echo "\$0='$0'"

# BASH_SOURCE is an array, but it only seems to have one element
echo "BASH_SOURCE='$BASH_SOURCE'"
echo "BASH_SOURCE[0]='${BASH_SOURCE[0]}'"

# Symlinked directories will be preserved
DIR_CD="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "DIR_CD='$DIR_CD'"

# Resolves symlinks to canonical path
DIR_READLINK=$(dirname "`readlink -f "${BASH_SOURCE[0]}"`")
echo "DIR_READLINK='$DIR_READLINK'"

# Resolves script to canonical path and name
READLINK_PATH=`readlink -f "${BASH_SOURCE[0]}"`
echo "READLINK_PATH='$READLINK_PATH'"

Thursday, April 30, 2015

Jetty missing NonBlockingThread

Got this error trying to start up a Jetty server:
2015-04-30 08:57:35.111:WARN:oejuc.AbstractLifeCycle:main: FAILED org.eclipse.jetty.server.ServerConnector$ServerConnectorManager@5a24ad9b: java.lang.NoClassDefFoundError: org/eclipse/jetty/util/thread/NonBlockingThread
The fix was to add a Maven dependency for jetty-util. Apparently, jetty-server doesn't include it as a dependency; it just fails at runtime if it's not there.

Java version incompatibility

Got this error message when I posted a JSON message to a little REST server I'm starting:
java.lang.UnsupportedClassVersionError: org/json/JSONObject : Unsupported major.minor version 52.0
It's because the newest version of the org.json library only works with Java 8 and I'm on Java 7. Why it doesn't detect this at compile time, I don't know.
Fix was to roll back from version 20141113 to 20140107.

Saturday, August 16, 2014

Allowing PUT requests for CGI scripts in Apache

Create an .htaccess file in your top-level CGI directory containing

<Limit GET PUT POST OPTIONS>
    Require all granted
</Limit>

You can also add DELETE if you want that too.