diff --git a/config/vufind/HierarchyDefault.ini b/config/vufind/HierarchyDefault.ini
index 833131f7c55fec5079cfa762341505fa603c9365..8969aa60f3c44196074e0ca460e2be7cc32aa904 100644
--- a/config/vufind/HierarchyDefault.ini
+++ b/config/vufind/HierarchyDefault.ini
@@ -4,7 +4,7 @@ show = true
 ; The source of the hierarchy data -- may be Solr or XMLFile
 treeSource = Solr
 ; When using Solr as a treeSource, this value determines how long tree data is
-; cached (in seconds) -- default 12h
+; cached (in seconds, or -1 to never expire) -- default 12h
 solrCacheTime = 43200
 ; When using XMLFile as a treeSource, this value specifies where tree data is found
 ;XMLFileDir = /usr/local/vufind/hierarchy_xml
diff --git a/config/vufind/HierarchyFlat.ini b/config/vufind/HierarchyFlat.ini
index e7696bcc02aa40e99e814f05469b1f47a61ee3d5..1d1ece1d1dc59fd7cf941e869d182b3f2d54be69 100644
--- a/config/vufind/HierarchyFlat.ini
+++ b/config/vufind/HierarchyFlat.ini
@@ -4,7 +4,7 @@ show = false
 ; The source of the hierarchy data -- may be Solr or XMLFile
 ;treeSource = Solr
 ; When using Solr as a treeSource, this value determines how long tree data is
-; cached (in seconds) -- default 12h
+; cached (in seconds, or -1 to never expire) -- default 12h
 ;solrCacheTime = 0
 ; When using XMLFile as a treeSource, this value specifies where tree data is found
 ;XMLFileDir = /usr/local/vufind/hierarchy_xml
diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php
index f8861c76ae9b2f9aceff6d2b245842c1c2366ac5..d1161d76573f8ec338fe50b3f659b871818d0790 100644
--- a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php
@@ -113,10 +113,11 @@ abstract class AbstractBase implements \Zend\Log\LoggerAwareInterface
      * Get XML for the specified hierarchy ID.
      *
      * @param string $id Hierarchy ID.
+     * @param array  $options Additional options for XML generation.
      *
      * @return string
      */
-    abstract public function getXML($id);
+    abstract public function getXML($id, $options = array());
 
     /**
      * Does this data source support the specified hierarchy ID?
diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
index ce9bccc7bac334fe8cc2b89b56054f4c71f664b7..62552371d951ea7d61a1349a3a209220b15f2b33 100644
--- a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
+++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
@@ -71,23 +71,24 @@ class Solr extends AbstractBase
      *
      * Build the XML file from the Solr fields
      *
-     * TODO: this should return false if it fails.
-     *
-     * @param string $id Hierarchy ID.
+     * @param string $id      Hierarchy ID.
+     * @param array  $options Additional options for XML generation.  (Currently one
+     * option is supported: 'refresh' may be set to true to bypass caching).
      *
      * @return string
      */
-    public function getXML($id)
+    public function getXML($id, $options = array())
     {
         $top = $this->db->getRecord($id);
         $cacheFile = (null !== $this->cacheDir)
             ? $this->cacheDir . '/hierarchyTree_' . urlencode($id) . '.xml'
             : false;
 
+        $useCache = isset($options['refresh']) ? !$options['refresh'] : true;
         $cacheTime = $this->getHierarchyDriver()->getTreeCacheTime();
 
-        if ($cacheFile && file_exists($cacheFile)
-            && filemtime($cacheFile) > (time() - $cacheTime)
+        if ($useCache && file_exists($cacheFile)
+            && ($cacheTime < 0 || filemtime($cacheFile) > (time() - $cacheTime))
         ) {
             $this->debug("Using cached data from $cacheFile");
             $xml = file_get_contents($cacheFile);
diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php
index 1d883899f47f9cec8dd31434df345d942b92d63d..9879919cc8779358e5d65dce73b36dd2213538c0 100644
--- a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php
+++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php
@@ -78,10 +78,11 @@ class XMLFile extends AbstractBase
      * Get XML for the specified hierarchy ID.
      *
      * @param string $id Hierarchy ID.
+     * @param array  $options Additional options for XML generation (unused here).
      *
      * @return string
      */
-    public function getXML($id)
+    public function getXML($id, $options = array())
     {
         return file_get_contents($this->getFilename($id));
     }
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php b/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php
index 85d7b7a2d1ff0d9df631f4656abc6af8542f57ce..875cb9366cf29f926731248c3d703412f1c60f2d 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php
@@ -117,6 +117,16 @@ class AbstractBase extends AbstractActionController
         return $this->getServiceLocator()->get('VuFind\ILSConnection');
     }
 
+    /**
+     * Get the search manager.
+     *
+     * @return \VuFind\Search\Manager
+     */
+    public function getSearchManager()
+    {
+        return $this->getServiceLocator()->get('SearchManager');
+    }
+
     /**
      * Get a database table object.
      *
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
index ddee7c9adf46233a17b5c5aad5c7107d563d53e5..2454c1fc3a25019f2cd813bc053055b6c6504126 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
@@ -385,4 +385,25 @@ class UtilController extends AbstractBase
         }
         return $this->getSuccessResponse();
     }
+
+    /**
+     * Tool to auto-fill hierarchy cache.
+     *
+     * @return \Zend\Console\Response
+     */
+    public function createhierarchytreesAction()
+    {
+        $solr = $this->getSearchManager()->setSearchClassId('Solr')->getResults();
+        $hierarchies = $solr->getFullFieldFacets(array('hierarchy_top_id'));
+        foreach ($hierarchies['hierarchy_top_id']['data']['list'] as $hierarchy) {
+            Console::writeLine("Building tree for {$hierarchy['value']}...");
+            $driver = $solr->getRecord($hierarchy['value']);
+            if ($driver->getHierarchyType()) {
+                // Only do this if the record is actually a hierarchy type record
+                $driver->getHierarchyDriver()->getTreeSource()
+                    ->getXML($hierarchy['value'], array('refresh' => true));
+            }
+        }
+        return $this->getSuccessResponse();
+    }
 }
diff --git a/util/createHierarchyTrees.php b/util/createHierarchyTrees.php
new file mode 100644
index 0000000000000000000000000000000000000000..01486fe67da8f6fc87fd9b292bde1331a343116f
--- /dev/null
+++ b/util/createHierarchyTrees.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Create all the hierarchy files which are used for looking up hierarchichal trees.
+ * This script will search the Solr index and create the files needed so they don't
+ * need to be built at runtime. If this script is run after every index, the caching
+ * time for hierarchy trees can be set to -1 so that trees are always assumed to be
+ * up to date.
+ *
+ * -!!!!-This script is specifically for trees built for JSTree from Solr.-!!!!-
+ *
+ * PHP version 5
+ *
+ * Copyright (C) National Library of Ireland 2012.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Utilities
+ * @author   Lutz Biedinger <lutz.biedinger@gmail.com>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki Wiki
+ */
+
+// Load the Zend framework -- this will automatically trigger the appropriate
+// controller action based on directory and file names
+define('CLI_DIR', __DIR__);     // save directory name of current script
+require_once __DIR__ . '/../public/index.php';