Merge remote-tracking branch 'origin' into develop
This commit is contained in:
commit
08f583e280
110 changed files with 5057 additions and 1583 deletions
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/webapp/.build/
|
||||||
|
/.classpath
|
||||||
|
/.project
|
||||||
|
/.settings
|
||||||
|
/bin/
|
||||||
|
/webapp/config/deploy.properties
|
||||||
|
/webapp/config/build.properties
|
||||||
|
/webapp/config/runtime.properties
|
||||||
|
/webapp/config/debug.log4j.properties
|
||||||
|
.build
|
361
doc/install.html
361
doc/install.html
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Vitro Version 1.4 Installation Guide</title>
|
<title>Vitro Version 1.5.1 Installation Guide</title>
|
||||||
<link rel="stylesheet" href="./css/doc.css" media="screen">
|
<link rel="stylesheet" href="./css/doc.css" media="screen">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -12,9 +12,9 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Start of content -->
|
<!-- Start of content -->
|
||||||
<div id="wrapper-content" role="main">
|
<div id="wrapper-content" role="main">
|
||||||
<h1>Vitro Version 1.4 Installation Guide</h1>
|
<h1>Vitro Version 1.5. Installation Guide</h1>
|
||||||
<small>
|
<small>
|
||||||
November 15, 2011
|
January 6, 2013
|
||||||
</small>
|
</small>
|
||||||
<toc>
|
<toc>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<a href="#introduction">Introduction to the Vitro installation</a>
|
<a href="#introduction">Introduction to the Vitro installation</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#installation">Installation process for Version 1.4</a>
|
<a href="#installation">Installation process for Version 1.5.1</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</toc>
|
</toc>
|
||||||
|
@ -38,8 +38,13 @@
|
||||||
If you are upgrading a previous installation of Vitro,
|
If you are upgrading a previous installation of Vitro,
|
||||||
you may need to adjust your procedure accordingly.
|
you may need to adjust your procedure accordingly.
|
||||||
</p>
|
</p>
|
||||||
<br>
|
<p>
|
||||||
<hr><!-- Page break --><!-- Introduction to the Vitro installation --><h2 id="introduction">Introduction to the Vitro installation</h2>
|
Other servlet containers: If you want to use a servlet container
|
||||||
|
other than Tomcat, please consult <a href="other_servlet_containers.html">
|
||||||
|
instructions for other servlet containers</a> in this directory.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr><h2 id="introduction">Introduction to the Vitro installation</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Before beginning the installation,
|
Before beginning the installation,
|
||||||
|
@ -54,8 +59,8 @@
|
||||||
<p>
|
<p>
|
||||||
This is created when you checkout the Vitro source code
|
This is created when you checkout the Vitro source code
|
||||||
(see <a href="#checkout_code">installation step III</a>, below).
|
(see <a href="#checkout_code">installation step III</a>, below).
|
||||||
This is where you will create your deploy.properties file
|
This is where you will create your build.properties file
|
||||||
(see <a href="#deploy_properties">installation step V</a>, below),
|
(see <a href="#build_properties">installation step IV</a>, below),
|
||||||
and where you will make any modifications to the Vitro
|
and where you will make any modifications to the Vitro
|
||||||
theme or code. You can create this wherever you choose.
|
theme or code. You can create this wherever you choose.
|
||||||
</p>
|
</p>
|
||||||
|
@ -68,18 +73,20 @@
|
||||||
but you won’t need to look at it or change it. If you need to change
|
but you won’t need to look at it or change it. If you need to change
|
||||||
Vitro, make the changes in the distribution directory, and run the build
|
Vitro, make the changes in the distribution directory, and run the build
|
||||||
script again. Tell the build script where to find Tomcat by setting <code>tomcat.home</code>
|
script again. Tell the build script where to find Tomcat by setting <code>tomcat.home</code>
|
||||||
in the deploy.properties file (see <a href="#deploy_properties">installation step V</a>,
|
in the build.properties file (see <a href="#build_properties">installation step IV</a>,
|
||||||
below).
|
below).
|
||||||
</p>
|
</p>
|
||||||
<h4>The Vitro home directory</h4>
|
<h4>The Vitro home directory</h4>
|
||||||
<p>
|
<p>
|
||||||
Vitro will use this area to store some of the data it uses. Uploaded
|
This directory contains the runtime configuration properties for Vitro.
|
||||||
image files are stored here, and the search index is stored here also.
|
Vitro will also use this area to store some of the data it uses. Uploaded
|
||||||
|
image files are stored here, and the Solr home directory is stored here also.
|
||||||
You can create this wherever you choose. Tell Vitro where to find the
|
You can create this wherever you choose. Tell Vitro where to find the
|
||||||
home directory by setting <code>vitro.home.directory</code>
|
home directory by setting <code>vitro.home</code> in the
|
||||||
in the
|
build.properties file (see <a href="#build_properties">installation step IV</a>,
|
||||||
deploy.properties file (see <a href="#deploy_properties">installation step V</a>,
|
below). You must create this directory before starting Vitro,
|
||||||
below). You must create this directory before starting Vitro, and you
|
you must create the <code>runtime.properties</code> file in this directory
|
||||||
|
(see <a href="#runtime_properties">Step V</a>, below), and you
|
||||||
must ensure that Tomcat has permission to read and write to this
|
must ensure that Tomcat has permission to read and write to this
|
||||||
directory when it runs.
|
directory when it runs.
|
||||||
</p>
|
</p>
|
||||||
|
@ -176,7 +183,10 @@
|
||||||
<a href="#checkout_code">Check out the Vitro Source Code</a>
|
<a href="#checkout_code">Check out the Vitro Source Code</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#deploy_properties">Specify deployment properties</a>
|
<a href="#build_properties">Specify build properties</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#runtime_properties">Specify runtime properties</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#deploy">Compile and deploy</a>
|
<a href="#deploy">Compile and deploy</a>
|
||||||
|
@ -275,12 +285,91 @@
|
||||||
If you want the very latest Vitro source, you can use subversion to check it out from SourceForge:
|
If you want the very latest Vitro source, you can use subversion to check it out from SourceForge:
|
||||||
<pre> svn checkout svn://svn.code.sf.net/p/vivo/vitro/code/trunk</code> <em>[Vitro_distribution_dir]</em></pre>
|
<pre> svn checkout svn://svn.code.sf.net/p/vivo/vitro/code/trunk</code> <em>[Vitro_distribution_dir]</em></pre>
|
||||||
</p>
|
</p>
|
||||||
<h3 id="deploy_properties">IV. Specify deployment properties </h3>
|
|
||||||
|
<h3 id="build_properties">IV. Specify build properties </h3>
|
||||||
<p>
|
<p>
|
||||||
In the <code>webapp/config</code> directory of the Vitro distribution,
|
In the <code>webapp/config</code> directory of the Vitro distribution,
|
||||||
copy the file <code>example.deploy.properties</code>
|
copy the file <code>example.build.properties</code>
|
||||||
to a file named simply <code>deploy.properties</code>. This file sets
|
to a file named simply <code>build.properties</code>.
|
||||||
several properties used in compilation and deployment.
|
Edit the file to suit your installation, as described in the following table.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
These properties are used in compilation and deployment.
|
||||||
|
They will be incorporated into Vitro when it is compiled in
|
||||||
|
<a href="#deploy">Step VI</a>. If you want to change these properties at
|
||||||
|
a later date, you will need to stop Tomcat, repeat <a href="#deploy">Step VI</a>,
|
||||||
|
and restart Tomcat.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>Windows:</em>
|
||||||
|
For those installing on Windows operating
|
||||||
|
system, include the windows drive and use the forward slash "/" and not
|
||||||
|
the back slash "\" in the directory locations, e.g. <code>c:/tomcat</code>.
|
||||||
|
</p>
|
||||||
|
<table border='1' bordercolor="#CCCCCC" cellspacing="5">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
Directory where tomcat is installed.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row">
|
||||||
|
<td>
|
||||||
|
tomcat.home
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
/usr/local/tomcat
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
Name of your Vitro application.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row">
|
||||||
|
<td>
|
||||||
|
webapp.name
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
vitro
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
Directory where the Vitro application will store
|
||||||
|
the data that it creates. This includes uploaded files (usually images)
|
||||||
|
and the Solr search index. Be sure this directory exists and is
|
||||||
|
writable by the user who the Tomcat service is running as.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row">
|
||||||
|
<td>
|
||||||
|
vitro.home
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
/usr/local/vitro/home
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3 id="runtime_properties">V. Specify runtime properties </h3>
|
||||||
|
<p>
|
||||||
|
In <a href="#build_properties">Step IV</a>, you defined the location of the Vitro home directory,
|
||||||
|
by specifying <code>vitro.home</code> in the <code>build.properties</code> file.
|
||||||
|
Create that directory now.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In the <code>webapp/config</code> subdirectory of the Vitro distribution, you will find a file called
|
||||||
|
<code>example.runtime.properties</code>. Copy this to the Vitro home directory you have created,
|
||||||
|
renaming the copy to <code>runtime.properties</code>.
|
||||||
|
Edit the file to suit your installation, as described in the following table.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
These properties are loaded when Vitro starts up. If you want to change these
|
||||||
|
properties at a later date, you will need to restart Tomcat for them to take
|
||||||
|
effect. You will not need to repeat <a href="#deploy">Step VI</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<em>Windows:</em>
|
<em>Windows:</em>
|
||||||
|
@ -329,32 +418,6 @@
|
||||||
http://vitro.mydomain.edu/individual/
|
http://vitro.mydomain.edu/individual/
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
Directory where tomcat is installed.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd_row">
|
|
||||||
<td>
|
|
||||||
tomcat.home
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
/usr/local/tomcat
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
Name of your Vitro application.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd_row">
|
|
||||||
<td>
|
|
||||||
webapp.name
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
vitro
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
URL of Solr context used in local Vitro search.
|
URL of Solr context used in local Vitro search.
|
||||||
|
@ -372,53 +435,6 @@
|
||||||
http://localhost:8080/vitrosolr
|
http://localhost:8080/vitrosolr
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
Restricts access to the Solr search platform.
|
|
||||||
The value is a regular expression. When a request is
|
|
||||||
made to Solr, the IP address of the requestor must the expression,
|
|
||||||
or the request will be rejected.
|
|
||||||
<br>
|
|
||||||
Examples:<code>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
vitro.local.solr.ipaddress.mask = 127\.0\.0\.1
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
vitro.local.solr.ipaddress.mask =
|
|
||||||
127\.0\.0\.1|0:0:0:0:0:0:0:1
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
vitro.local.solr.ipaddress.mask = 169.254.*
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd_row">
|
|
||||||
<td>
|
|
||||||
vitro.local.solr.ipaddress.mask
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
127\.0\.0\.1|[0:]+:1
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
Directory where the Vitro application will store
|
|
||||||
the data that it creates. This includes uploaded files (usually images)
|
|
||||||
and the Solr search index. Be sure this directory exists and is
|
|
||||||
writable by the user who the Tomcat service is running as.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd_row">
|
|
||||||
<td>
|
|
||||||
vitro.home.directory
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
/usr/local/vitro/data
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
Specify an SMTP host that the application will
|
Specify an SMTP host that the application will
|
||||||
|
@ -635,13 +651,101 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
An absolute file path, pointing to the root directory of the Harvester utility.
|
Force VIVO to use a specific language or Locale instead of those
|
||||||
You must include the final slash.
|
specified by the browser.
|
||||||
|
This affects RDF data retrieved from the model, if RDFService.languageFilter is true.
|
||||||
|
This also affects the text of pages that have been modified to support multiple languages.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr class="odd_row">
|
||||||
|
<td>
|
||||||
|
languages.forceLocale
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
en_US
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
A list of supported languages or Locales that the user may choose to
|
||||||
|
use instead of the one specified by the browser. Selection images must
|
||||||
|
be available in the i18n/images directory of the theme.
|
||||||
|
This affects RDF data retrieved from the model, if RDFService.languageFilter is true.
|
||||||
|
This also affects the text of pages that have been modified to support multiple languages.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row">
|
||||||
|
<td>
|
||||||
|
languages.selectableLocales
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
en, es, fr_FR
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<b>For developers only.</b>
|
||||||
|
Defeat the Freemarker template cache, so each template
|
||||||
|
is read from disk on each request. This permits developers to immediately
|
||||||
|
see the effect of changes to the template. The default is <code>false</code>, which
|
||||||
|
means that a cached copy of each template will be used for 60 seconds
|
||||||
|
before the disk is checked for a new version.
|
||||||
|
<br/><b>Setting this option to "true" slows down Vitro performance.</b>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row">
|
||||||
|
<td>
|
||||||
|
developer.defeatFreemarkerCache
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
false
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<b>For developers only.</b>
|
||||||
|
Defeat the cache of language-specific text strings,
|
||||||
|
so the language file is read from disk on each request.
|
||||||
|
This permits developers to immediately
|
||||||
|
see the effect of changes to the text strings.
|
||||||
|
The default is <code>false</code>, which means that the language file is
|
||||||
|
read when VIVO starts up, or when a new theme is selected.
|
||||||
|
<br/><b>Setting this option to "true" slows down Vitro performance.</b>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row">
|
||||||
|
<td>
|
||||||
|
developer.defeatI18nCache = true
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
false
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<b>For developers only.</b>
|
||||||
|
Add starting and ending delimiters to each Freemarker template, so you can see
|
||||||
|
which template were invoked by viewing the generated HTML.
|
||||||
|
The default is <code>false</code>.
|
||||||
|
<br/><b>Setting this option to "true" slows down Vitro performance.</b>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row blue">
|
||||||
|
<td>
|
||||||
|
developer.insertFreemarkerDelimiters = true
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
false
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h3 id="deploy">V. Compile and deploy</h3>
|
<h3 id="deploy">VI. Compile and deploy</h3>
|
||||||
<p>
|
<p>
|
||||||
At the command line, change to the <code>webapp</code> directory inside the Vitro distribution
|
At the command line, change to the <code>webapp</code> directory inside the Vitro distribution
|
||||||
directory. Then type:
|
directory. Then type:
|
||||||
|
@ -650,7 +754,7 @@
|
||||||
<p>
|
<p>
|
||||||
to build Vitro and deploy to Tomcat's webapps directory.
|
to build Vitro and deploy to Tomcat's webapps directory.
|
||||||
</p>
|
</p>
|
||||||
<h3 id="tomcat_settings">VI. Configure Tomcat</h3>
|
<h3 id="tomcat_settings">VII. Configure Tomcat</h3>
|
||||||
<h4>Set JVM parameters</h4>
|
<h4>Set JVM parameters</h4>
|
||||||
<p>
|
<p>
|
||||||
Vitro may require more memory than that allocated to Tomcat by
|
Vitro may require more memory than that allocated to Tomcat by
|
||||||
|
@ -686,7 +790,7 @@
|
||||||
accepting percent-encoded UTF-8.
|
accepting percent-encoded UTF-8.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Edit Tomcat's conf/server.xml and add the following attribute to each of the
|
Edit Tomcat's <code>conf/server.xml</code> and add the following attribute to each of the
|
||||||
Connector elements: URIEncoding="UTF-8".
|
Connector elements: URIEncoding="UTF-8".
|
||||||
</p>
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
|
@ -699,6 +803,9 @@
|
||||||
</Server>
|
</Server>
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
|
Note: some versions of Tomcat already include this attribute as the default.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h4>Take care when creating Context elements</h4>
|
<h4>Take care when creating Context elements</h4>
|
||||||
<p>
|
<p>
|
||||||
Each of the webapps in the Vitro distribution (Vitro and Solr) includes a "context fragment" file,
|
Each of the webapps in the Vitro distribution (Vitro and Solr) includes a "context fragment" file,
|
||||||
|
@ -710,22 +817,35 @@
|
||||||
deployment parameters from the overridden context fragment.
|
deployment parameters from the overridden context fragment.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
See <a href="#tomcat_connector">Section X</a> below,
|
See <a href="#tomcat_connector">Section XI</a> below,
|
||||||
for an example of overriding the Vitro context fragment.
|
for an example of overriding the Vitro context fragment.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="start_tomcat">VII. Start Tomcat </h3>
|
<h3 id="start_tomcat">VIII. Start Tomcat </h3>
|
||||||
<p>
|
<p>
|
||||||
Most Tomcat installations can be started by running <code>startup.sh</code>
|
Most Tomcat installations can be started by running <code>startup.sh</code>
|
||||||
or <code>startup.bat</code>
|
or <code>startup.bat</code>
|
||||||
in Tomcat's bin directory. Point your
|
in Tomcat's bin directory. Point your
|
||||||
browser to "http://localhost:8080/vitro/" to test the application. If
|
browser to "http://localhost:8080/vitro/" to test the application.
|
||||||
Tomcat does not start up, or the Vitro application is not visible, check
|
</p>
|
||||||
the files in Tomcat's logs directory. Error messages are commonly found
|
<p>
|
||||||
|
On start up Vitro will run some diagnostic tests. If a
|
||||||
|
problem is detected, the normal Vitro pages will redirect
|
||||||
|
to a startup status page describing the problem. You
|
||||||
|
can stop tomcat, attempt to fix the problem and
|
||||||
|
proceeded from <a href="#deploy">Step VI</a>. The
|
||||||
|
startup status page may offer a continue link which
|
||||||
|
will allow you to use VIVO in spite of the problems.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If Tomcat does not start up, or the Vitro application is not visible, check
|
||||||
|
the files in Tomcat's <code>logs</code> directory. Error messages are commonly found
|
||||||
in <code>catalina.out</code>
|
in <code>catalina.out</code>
|
||||||
or <code>localhost.log</code>
|
or <code>localhost.log</code>
|
||||||
</p>
|
</p>
|
||||||
<h3 id="add_rdf">VIII. Log in and add RDF data </h3>
|
|
||||||
|
</p>
|
||||||
|
<h3 id="add_rdf">IX. Log in and add RDF data </h3>
|
||||||
<p>
|
<p>
|
||||||
If the startup was successful, you will see a welcome message
|
If the startup was successful, you will see a welcome message
|
||||||
informing you that you have successfully installed Vitro. Click the "Log
|
informing you that you have successfully installed Vitro. Click the "Log
|
||||||
|
@ -759,7 +879,7 @@
|
||||||
the page will show a simple index of the knowledge base.
|
the page will show a simple index of the knowledge base.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="contact_email">IX. Set the Contact Email Address (if using
|
<h3 id="contact_email">X. Set the Contact Email Address (if using
|
||||||
"Contact Us" form)</h3>
|
"Contact Us" form)</h3>
|
||||||
<p>
|
<p>
|
||||||
If you have configured your application to use the "Contact Us"
|
If you have configured your application to use the "Contact Us"
|
||||||
|
@ -781,7 +901,7 @@
|
||||||
provide an email address in this step, your users will receive a java
|
provide an email address in this step, your users will receive a java
|
||||||
error in the interface.
|
error in the interface.
|
||||||
</p>
|
</p>
|
||||||
<h3 id="tomcat_connector">X. Set up Apache Tomcat Connector </h3>
|
<h3 id="tomcat_connector">XI. Set up Apache Tomcat Connector </h3>
|
||||||
<p>
|
<p>
|
||||||
It is recommended that a Tomcat Connector such as mod_jk be used to
|
It is recommended that a Tomcat Connector such as mod_jk be used to
|
||||||
ensure that the site address does not include the port number (e.g.
|
ensure that the site address does not include the port number (e.g.
|
||||||
|
@ -832,16 +952,11 @@
|
||||||
cookies="true" >
|
cookies="true" >
|
||||||
|
|
||||||
<Manager pathname="" />
|
<Manager pathname="" />
|
||||||
|
|
||||||
<Environment type="java.lang.String" override="false"
|
|
||||||
name="path.configuration"
|
|
||||||
value="deploy.properties"
|
|
||||||
/>
|
|
||||||
</Context>
|
</Context>
|
||||||
|
|
||||||
...
|
...
|
||||||
</pre>
|
</pre>
|
||||||
<h3 id="external_auth">XI. Using an External Authentication System
|
<h3 id="external_auth">XII. Using an External Authentication System
|
||||||
with Vitro </h3>
|
with Vitro </h3>
|
||||||
<p>
|
<p>
|
||||||
</p>
|
</p>
|
||||||
|
@ -878,7 +993,7 @@
|
||||||
<h4>Configuring Vitro</h4>
|
<h4>Configuring Vitro</h4>
|
||||||
<p>
|
<p>
|
||||||
To enable external authentication, Vitro requires three values in
|
To enable external authentication, Vitro requires three values in
|
||||||
the <code>deploy.properties</code>
|
the <code>runtime.properties</code>
|
||||||
file.
|
file.
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -893,7 +1008,7 @@
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You need to tell Vitro the name of that HTTP header. Insert a
|
You need to tell Vitro the name of that HTTP header. Insert a
|
||||||
line like this in the deploy.properties file:
|
line like this in the runtime.properties file:
|
||||||
</p>
|
</p>
|
||||||
<pre>externalAuth.netIdHeaderName = [the header name]</pre>
|
<pre>externalAuth.netIdHeaderName = [the header name]</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -907,7 +1022,7 @@
|
||||||
the Vitro login form. You need to tell Vitro what text should appear in
|
the Vitro login form. You need to tell Vitro what text should appear in
|
||||||
that button.
|
that button.
|
||||||
<p>
|
<p>
|
||||||
Put a line like this in the deploy.properties file:
|
Put a line like this in the runtime.properties file:
|
||||||
externalAuth.buttonText = [the text for your login button] For example:
|
externalAuth.buttonText = [the text for your login button] For example:
|
||||||
</p>
|
</p>
|
||||||
<pre>externalAuth.buttonText = Log in using BearCat Shibboleth</pre>
|
<pre>externalAuth.buttonText = Log in using BearCat Shibboleth</pre>
|
||||||
|
@ -924,7 +1039,7 @@
|
||||||
data model for a person with a property that matches the User’s network
|
data model for a person with a property that matches the User’s network
|
||||||
ID (the value of the property must be either a String literal or an
|
ID (the value of the property must be either a String literal or an
|
||||||
untyped literal). You need to tell Vitro what property should be used
|
untyped literal). You need to tell Vitro what property should be used
|
||||||
for matching. Insert a line like this in the deploy.properties file:
|
for matching. Insert a line like this in the runtime.properties file:
|
||||||
</p>
|
</p>
|
||||||
<pre>selfEditing.idMatchingProperty = [the URI of the property]</pre>
|
<pre>selfEditing.idMatchingProperty = [the URI of the property]</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -933,40 +1048,38 @@
|
||||||
<pre>selfEditing.idMatchingProperty = http://vitro.mydomain.edu/ns#networkId</pre>
|
<pre>selfEditing.idMatchingProperty = http://vitro.mydomain.edu/ns#networkId</pre>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3 id="installation_check">XII. Was the installation successful? </h3>
|
<h3 id="installation_check">XIII. Was the installation successful? </h3>
|
||||||
<p>
|
<p>
|
||||||
If you have completed the previous steps, you have good indications
|
If you have completed the previous steps, you have good indications
|
||||||
that the installation was successful.
|
that the installation was successful.
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
Step VII showed that Tomcat recognized the webapp, and that the
|
Step VIII showed that Tomcat recognized the webapp, and that the
|
||||||
webapp was able to present the initial page.
|
webapp was able to present the initial page.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Step VIII verified that you can log in to the administrator
|
Step IX verified that you can log in to the administrator
|
||||||
account.
|
account.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Step VII also shows that the Vitro self-tests ran successfully.
|
Step VIII also shows that the Vitro self-tests ran successfully.
|
||||||
When Tomcat starts the Vitro webapp, it runs several tests.
|
When Tomcat starts the Vitro webapp, it runs several tests.
|
||||||
If any of these tests produce warnings or error message,
|
If any of these tests produce warnings or error message,
|
||||||
you would see them instead of the Vitro home page.
|
you would see them instead of the Vitro home page.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Among other things, the self-tests check
|
Among other things, the self-tests check
|
||||||
</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The Vitro home directory exists and Vitro can write to it.</li>
|
<li>The Vitro home directory exists and Vitro can write to it.</li>
|
||||||
<li>Vitro can connect to the database.</li>
|
<li>Vitro can connect to the database.</li>
|
||||||
<li>Vitro can connect to the Solr search application.</li>
|
<li>Vitro can connect to the Solr search application.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
|
||||||
If you saw the Vitro home page in Step VII, you know that your installation passed all of these tests.
|
If you saw the Vitro home page in Step VII, you know that your installation passed all of these tests.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="termsofuse">XIII. Review the Vitro Terms of Use</h3>
|
<h3 id="termsofuse">XIV. Review the Vitro Terms of Use</h3>
|
||||||
<p>
|
<p>
|
||||||
Vitro comes with a "Terms of Use" statement linked from the footer.
|
Vitro comes with a "Terms of Use" statement linked from the footer.
|
||||||
The "Site Name" you assign in the "Site Information" form under the <strong>Site Admin</strong>
|
The "Site Name" you assign in the "Site Information" form under the <strong>Site Admin</strong>
|
||||||
|
@ -992,7 +1105,7 @@
|
||||||
<div id="footer" role="contentinfo">
|
<div id="footer" role="contentinfo">
|
||||||
<p class="copyright">
|
<p class="copyright">
|
||||||
<small>
|
<small>
|
||||||
©2011 All Rights Reserved
|
©2013 All Rights Reserved
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,40 +30,53 @@ deploy - Configure the application and deploy directly into the Tomcat webapps
|
||||||
target: properties
|
target: properties
|
||||||
- - - - - - - - - - - - - - - - - -->
|
- - - - - - - - - - - - - - - - - -->
|
||||||
<target name="properties">
|
<target name="properties">
|
||||||
<property name="deploy.properties.file" location="../webapp/config/deploy.properties" />
|
<property name="build.properties.file" location="../webapp/config/build.properties" />
|
||||||
|
|
||||||
<fail message="You must create a "${deploy.properties.file}" file.">
|
<fail message="You must create a "${build.properties.file}" file.">
|
||||||
<condition>
|
<condition>
|
||||||
<not>
|
<not>
|
||||||
<available file="${deploy.properties.file}" />
|
<available file="${build.properties.file}" />
|
||||||
</not>
|
</not>
|
||||||
</condition>
|
</condition>
|
||||||
</fail>
|
</fail>
|
||||||
|
|
||||||
<property file="${deploy.properties.file}" />
|
<property file="${build.properties.file}" />
|
||||||
|
|
||||||
<fail unless="tomcat.home" message="${deploy.properties.file} must contain a value for tomcat.home" />
|
<fail unless="tomcat.home" message="${build.properties.file} must contain a value for tomcat.home" />
|
||||||
<fail unless="vitro.home.directory" message="${deploy.properties.file} must contain a value for vitro.home.directory" />
|
<fail unless="vitro.home" message="${build.properties.file} must contain a value for vitro.home" />
|
||||||
<fail unless="VitroConnection.DataSource.url" message="${deploy.properties.file} must contain a value for VitroConnection.DataSource.url" />
|
|
||||||
<fail unless="VitroConnection.DataSource.username" message="${deploy.properties.file} must contain a value for VitroConnection.DataSource.username" />
|
|
||||||
<fail unless="VitroConnection.DataSource.password" message="${deploy.properties.file} must contain a value for VitroConnection.DataSource.password" />
|
|
||||||
<fail unless="VitroConnection.DataSource.driver" message="${deploy.properties.file} must contain a value for VitroConnection.DataSource.driver" />
|
|
||||||
<fail unless="OpenSocial.shindigURL" message="${deploy.properties.file} must contain a value for OpenSocial.shindigURL" />
|
|
||||||
<fail unless="OpenSocial.tokenService" message="${deploy.properties.file} must contain a value for OpenSocial.tokenService" />
|
|
||||||
<fail unless="OpenSocial.tokenKeyFile" message="${deploy.properties.file} must contain a value for OpenSocial.tokenKeyFile" />
|
|
||||||
|
|
||||||
<fail message="The vitro.home.directory "${vitro.home.directory}" does not exist.">
|
<property name="runtime.properties.file" location="${vitro.home}/runtime.properties" />
|
||||||
|
|
||||||
|
<fail message="The runtime properties file "${runtime.properties.file}" does not exist.">
|
||||||
<condition>
|
<condition>
|
||||||
<not>
|
<not>
|
||||||
<available file="${vitro.home.directory}" />
|
<available file="${runtime.properties.file}" />
|
||||||
</not>
|
</not>
|
||||||
</condition>
|
</condition>
|
||||||
</fail>
|
</fail>
|
||||||
|
|
||||||
<fail message="The vitro.home.directory "${vitro.home.directory}" is not writable.">
|
<property file="${runtime.properties.file}" />
|
||||||
|
|
||||||
|
<fail unless="VitroConnection.DataSource.url" message="${runtime.properties.file} must contain a value for VitroConnection.DataSource.url" />
|
||||||
|
<fail unless="VitroConnection.DataSource.username" message="${runtime.properties.file} must contain a value for VitroConnection.DataSource.username" />
|
||||||
|
<fail unless="VitroConnection.DataSource.password" message="${runtime.properties.file} must contain a value for VitroConnection.DataSource.password" />
|
||||||
|
<fail unless="VitroConnection.DataSource.driver" message="${runtime.properties.file} must contain a value for VitroConnection.DataSource.driver" />
|
||||||
|
<fail unless="OpenSocial.shindigURL" message="${runtime.properties.file} must contain a value for OpenSocial.shindigURL" />
|
||||||
|
<fail unless="OpenSocial.tokenService" message="${runtime.properties.file} must contain a value for OpenSocial.tokenService" />
|
||||||
|
<fail unless="OpenSocial.tokenKeyFile" message="${runtime.properties.file} must contain a value for OpenSocial.tokenKeyFile" />
|
||||||
|
|
||||||
|
<fail message="The Vitro home directory "${vitro.home}" does not exist.">
|
||||||
<condition>
|
<condition>
|
||||||
<not>
|
<not>
|
||||||
<isfileselected file="${vitro.home.directory}">
|
<available file="${vitro.home}" />
|
||||||
|
</not>
|
||||||
|
</condition>
|
||||||
|
</fail>
|
||||||
|
|
||||||
|
<fail message="The Vitro home directory "${vitro.home}" is not writable.">
|
||||||
|
<condition>
|
||||||
|
<not>
|
||||||
|
<isfileselected file="${vitro.home}">
|
||||||
<writable />
|
<writable />
|
||||||
</isfileselected>
|
</isfileselected>
|
||||||
</not>
|
</not>
|
||||||
|
@ -83,7 +96,7 @@ deploy - Configure the application and deploy directly into the Tomcat webapps
|
||||||
<property name="build.shindig.dir" location="${build.dir}/shindig" />
|
<property name="build.shindig.dir" location="${build.dir}/shindig" />
|
||||||
|
|
||||||
<!-- deploy directories -->
|
<!-- deploy directories -->
|
||||||
<property name="shindig.home.dir" location="${vitro.home.directory}/shindig" />
|
<property name="shindig.home.dir" location="${vitro.home}/shindig" />
|
||||||
<property name="shindig.config.dir" location="${shindig.home.dir}/conf" />
|
<property name="shindig.config.dir" location="${shindig.home.dir}/conf" />
|
||||||
<property name="tomcat.webapps.dir" location="${tomcat.home}/webapps" />
|
<property name="tomcat.webapps.dir" location="${tomcat.home}/webapps" />
|
||||||
|
|
||||||
|
@ -145,5 +158,4 @@ deploy - Configure the application and deploy directly into the Tomcat webapps
|
||||||
<copy file="${shindig.war.original.file}" tofile="${shindig.war.deployed.file}" overwrite="true" />
|
<copy file="${shindig.war.original.file}" tofile="${shindig.war.deployed.file}" overwrite="true" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
Binary file not shown.
BIN
solr/apache-solr-3.6.2.war
Normal file
BIN
solr/apache-solr-3.6.2.war
Normal file
Binary file not shown.
|
@ -253,7 +253,7 @@
|
||||||
|
|
||||||
<!-- **************************** End Vitro Fields *************************** -->
|
<!-- **************************** End Vitro Fields *************************** -->
|
||||||
<!-- **************************** Dynamic Fields *************************** -->
|
<!-- **************************** Dynamic Fields *************************** -->
|
||||||
<dynamicField name="*_string" type="string" indexed="true" stored="true" />
|
<dynamicField name="*_string" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||||
<!-- **************************** End Dynamic Fields *************************** -->
|
<!-- **************************** End Dynamic Fields *************************** -->
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
<Context crossContext="true" override="true">
|
<Context crossContext="true" override="true">
|
||||||
|
|
||||||
<!-- For security, restrict access to clients on this machine
|
|
||||||
for IPv4 requests, localhost is 127.0.0.1
|
|
||||||
for IPv6 requests, localhost is 0:0:0:0:0:0:0:1 -->
|
|
||||||
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
|
|
||||||
allow="${vitro.local.solr.ipaddress.mask}"/>
|
|
||||||
|
|
||||||
<Environment
|
<Environment
|
||||||
type="java.lang.String"
|
type="java.lang.String"
|
||||||
name="solr/home"
|
name="solr/home"
|
||||||
|
|
493
webapp/build.xml
493
webapp/build.xml
|
@ -10,216 +10,226 @@
|
||||||
|
|
||||||
<project name="vitroCore" default="describe">
|
<project name="vitroCore" default="describe">
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - -
|
|
||||||
properties
|
|
||||||
- - - - - - - - - - - - - - - - -->
|
|
||||||
<dirname property="corebase.dir" file="${ant.file.vitroCore}" />
|
|
||||||
|
|
||||||
<!-- A product script will override appbase.dir, but not corebase.dir -->
|
<!-- A product script will override appbase.dir, but not corebase.dir -->
|
||||||
|
<dirname property="corebase.dir" file="${ant.file.vitroCore}" />
|
||||||
<property name="appbase.dir" location="${corebase.dir}" />
|
<property name="appbase.dir" location="${corebase.dir}" />
|
||||||
|
|
||||||
|
<property name="build.properties.file" location="config/build.properties" />
|
||||||
|
|
||||||
<property name="build.dir" location=".build" />
|
<property name="build.dir" location=".build" />
|
||||||
<property name="deploy.properties.file" location="config/deploy.properties" />
|
|
||||||
|
|
||||||
<property name="utilities.base.dir" location="${corebase.dir}/../utilities/buildutils" />
|
<property name="buildtools.dir" location="${corebase.dir}/../utilities/buildutils" />
|
||||||
<property name="utilities.source.dir" location="${utilities.base.dir}/src" />
|
<property name="buildtools.source.dir" location="${buildtools.dir}/src" />
|
||||||
<property name="utilities.lib.dir" location="${utilities.base.dir}/lib" />
|
<property name="buildtools.lib.dir" location="${buildtools.dir}/lib" />
|
||||||
|
<property name="buildtools.compiled.dir" location="${build.dir}/buildTools" />
|
||||||
|
|
||||||
<property name="war.dir" location="${build.dir}/war" />
|
<property name="main.build.dir" location="${build.dir}/main"/>
|
||||||
<property name="war.webinf.dir" location="${war.dir}/WEB-INF" />
|
<property name="main.webapp.dir" location="${main.build.dir}/webapp" />
|
||||||
<property name="war.classes.dir" location="${war.webinf.dir}/classes" />
|
<property name="main.webinf.dir" location="${main.webapp.dir}/WEB-INF" />
|
||||||
<property name="war.resources.dir" location="${war.webinf.dir}/resources" />
|
<property name="main.compiled.dir" location="${main.webinf.dir}/classes" />
|
||||||
<property name="revisionInfo.build.file" location="${war.resources.dir}/revisionInfo.txt" />
|
<property name="main.resources.dir" location="${main.webinf.dir}/resources" />
|
||||||
|
<property name="main.revisioninfo.file" location="${main.resources.dir}/revisionInfo.txt" />
|
||||||
|
|
||||||
<property name="test.classes.dir" location="${build.dir}/testClasses" />
|
<property name="unittests.compiled.dir" location="${main.build.dir}/testClasses" />
|
||||||
<property name="utility.classes.dir" location="${build.dir}/utilityClasses" />
|
|
||||||
|
<property name="solr.template.dir" location="${corebase.dir}/../solr" />
|
||||||
|
<property name="solr.template.context.file" location="${solr.template.dir}/template.context.xml" />
|
||||||
|
|
||||||
<property name="solr.build.dir" location="${build.dir}/solr" />
|
<property name="solr.build.dir" location="${build.dir}/solr" />
|
||||||
|
<property name="solr.webapp.dir" location="${solr.build.dir}/webapp" />
|
||||||
|
<property name="solr.homeimage.dir" location="${solr.build.dir}/homeimage" />
|
||||||
|
|
||||||
<property name="javac.deprecation" value="true" />
|
<property name="distribution.dir" location="${build.dir}/distribution" />
|
||||||
|
<property name="distribution.tar.gz.file" location="${build.dir}/distribution.tar.gz" />
|
||||||
|
|
||||||
|
<property name="option.javac.deprecation" value="true" />
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - -
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
paths: for compiling and running
|
target: buildProperties
|
||||||
- - - - - - - - - - - - - - - - - -->
|
- - - - - - - - - - - - - - - - - -->
|
||||||
<path id="compile.classpath">
|
<target name="buildProperties">
|
||||||
<fileset dir="${appbase.dir}/lib" includes="*.jar" />
|
<fail message="You must create a "${build.properties.file}" file.">
|
||||||
</path>
|
<condition>
|
||||||
|
<not>
|
||||||
|
<available file="${build.properties.file}" />
|
||||||
|
</not>
|
||||||
|
</condition>
|
||||||
|
</fail>
|
||||||
|
|
||||||
|
<property file="${build.properties.file}" />
|
||||||
|
|
||||||
|
<fail unless="webapp.name" message="${build.properties.file} must contain a value for webapp.name" />
|
||||||
|
<property name="solr.app.name" value="${webapp.name}solr" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
|
target: deployProperties
|
||||||
|
- - - - - - - - - - - - - - - - - -->
|
||||||
|
<target name="deployProperties" depends="buildProperties">
|
||||||
|
<fail unless="vitro.home" message="${build.properties.file} must contain a value for vitro.home" />
|
||||||
|
<fail unless="tomcat.home" message="${build.properties.file} must contain a value for tomcat.home" />
|
||||||
|
|
||||||
|
<property name="solr.home.dir" location="${vitro.home}/solr" />
|
||||||
|
|
||||||
|
<property name="tomcat.context.filename" value="META-INF/context.xml" />
|
||||||
|
<property name="main.tomcat.webapp.dir" value="${tomcat.home}/webapps/${webapp.name}" />
|
||||||
|
<property name="main.tomcat.context.file" value="${main.tomcat.webapp.dir}/${tomcat.context.filename}" />
|
||||||
|
<property name="solr.tomcat.webapp.dir" value="${tomcat.home}/webapps/${solr.app.name}" />
|
||||||
|
<property name="solr.tomcat.context.file" value="${solr.tomcat.webapp.dir}/${tomcat.context.filename}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
|
target: compileBuildtools
|
||||||
|
- - - - - - - - - - - - - - - - - -->
|
||||||
|
<target name="compileBuildtools">
|
||||||
<path id="utility.compile.classpath">
|
<path id="utility.compile.classpath">
|
||||||
<fileset dir="${utilities.lib.dir}" includes="*.jar" />
|
<fileset dir="${buildtools.lib.dir}" includes="*.jar" />
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<path id="utility.run.classpath">
|
<mkdir dir="${buildtools.compiled.dir}" />
|
||||||
<pathelement location="${utility.classes.dir}" />
|
<javac srcdir="${buildtools.source.dir}"
|
||||||
<path refid="utility.compile.classpath" />
|
destdir="${buildtools.compiled.dir}"
|
||||||
</path>
|
debug="true"
|
||||||
|
deprecation="${option.javac.deprecation}"
|
||||||
<path id="test.compile.classpath">
|
encoding="UTF8"
|
||||||
<pathelement location="${war.classes.dir}" />
|
includeantruntime="false"
|
||||||
<path refid="compile.classpath" />
|
optimize="false"
|
||||||
</path>
|
source="1.6">
|
||||||
|
|
||||||
<path id="test.run.classpath">
|
|
||||||
<pathelement location="${appbase.dir}/test" />
|
|
||||||
<pathelement location="${test.classes.dir}" />
|
|
||||||
<path refid="test.compile.classpath" />
|
|
||||||
<path refid="utility.run.classpath" />
|
|
||||||
</path>
|
|
||||||
|
|
||||||
<!-- =================================
|
|
||||||
target: describe
|
|
||||||
================================= -->
|
|
||||||
<target name="describe" description="--> Describe the targets (this is the default).">
|
|
||||||
<echo>
|
|
||||||
all - Runs "clean", then "deploy".
|
|
||||||
clean - Delete all artifacts so the next build will be from scratch.
|
|
||||||
compile - Compile the Java source files.
|
|
||||||
orng - Configure and deploy the ORNG Shindig application.
|
|
||||||
test - Compile and run the JUnit tests.
|
|
||||||
war - Create a WAR file to be deployed in a servlet container.
|
|
||||||
deploy - Deploy the application directly into the Tomcat webapps directory.
|
|
||||||
</echo>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- =================================
|
|
||||||
target: all
|
|
||||||
================================= -->
|
|
||||||
<target name="all" depends="clean, deploy" description="--> Run 'clean', then 'deploy'" />
|
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - -
|
|
||||||
target: properties
|
|
||||||
- - - - - - - - - - - - - - - - - -->
|
|
||||||
<target name="properties">
|
|
||||||
<fail message="You must create a "${deploy.properties.file}" file.">
|
|
||||||
<condition>
|
|
||||||
<not>
|
|
||||||
<available file="${deploy.properties.file}" />
|
|
||||||
</not>
|
|
||||||
</condition>
|
|
||||||
</fail>
|
|
||||||
|
|
||||||
<property file="${deploy.properties.file}" />
|
|
||||||
|
|
||||||
<fail unless="tomcat.home" message="${deploy.properties.file} must contain a value for tomcat.home" />
|
|
||||||
<fail unless="webapp.name" message="${deploy.properties.file} must contain a value for webapp.name" />
|
|
||||||
<fail unless="vitro.home.directory" message="${deploy.properties.file} must contain a value for vitro.home.directory" />
|
|
||||||
<fail unless="Vitro.defaultNamespace" message="${deploy.properties.file} must contain a value for Vitro.defaultNamespace" />
|
|
||||||
<fail unless="VitroConnection.DataSource.url" message="${deploy.properties.file} must contain a value for VitroConnection.DataSource.url" />
|
|
||||||
<fail unless="VitroConnection.DataSource.username" message="${deploy.properties.file} must contain a value for VitroConnection.DataSource.username" />
|
|
||||||
<fail unless="VitroConnection.DataSource.password" message="${deploy.properties.file} must contain a value for VitroConnection.DataSource.password" />
|
|
||||||
<fail unless="rootUser.emailAddress" message="${deploy.properties.file} must contain a value for rootUser.emailAddress" />
|
|
||||||
|
|
||||||
<fail message="The vitro.home.directory "${vitro.home.directory}" does not exist.">
|
|
||||||
<condition>
|
|
||||||
<not>
|
|
||||||
<available file="${vitro.home.directory}" />
|
|
||||||
</not>
|
|
||||||
</condition>
|
|
||||||
</fail>
|
|
||||||
|
|
||||||
<fail message="The vitro.home.directory "${vitro.home.directory}" is not writable.">
|
|
||||||
<condition>
|
|
||||||
<not>
|
|
||||||
<isfileselected file="${vitro.home.directory}">
|
|
||||||
<writable />
|
|
||||||
</isfileselected>
|
|
||||||
</not>
|
|
||||||
</condition>
|
|
||||||
</fail>
|
|
||||||
|
|
||||||
<property name="solr.home.dir" location="${vitro.home.directory}/solr" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- =================================
|
|
||||||
target: clean
|
|
||||||
================================= -->
|
|
||||||
<target name="clean" depends="properties" description="--> Delete all artifacts.">
|
|
||||||
<delete dir="${build.dir}" />
|
|
||||||
<delete dir="${solr.home.dir}" excludes="data/**/*" includeemptydirs="true" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - -
|
|
||||||
target: compileUtilities
|
|
||||||
- - - - - - - - - - - - - - - - - -->
|
|
||||||
<target name="compileUtilities">
|
|
||||||
<mkdir dir="${utility.classes.dir}" />
|
|
||||||
<javac srcdir="${utilities.source.dir}" destdir="${utility.classes.dir}" debug="true" deprecation="${javac.deprecation}" encoding="UTF8" includeantruntime="false" optimize="false" source="1.6">
|
|
||||||
<classpath refid="utility.compile.classpath" />
|
<classpath refid="utility.compile.classpath" />
|
||||||
</javac>
|
</javac>
|
||||||
|
|
||||||
|
<path id="utility.run.classpath">
|
||||||
|
<pathelement location="${buildtools.compiled.dir}" />
|
||||||
|
<path refid="utility.compile.classpath" />
|
||||||
|
</path>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - -
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
target: prepare
|
target: prepare
|
||||||
- - - - - - - - - - - - - - - - - -->
|
- - - - - - - - - - - - - - - - - -->
|
||||||
<target name="prepare" depends="properties, compileUtilities">
|
<target name="prepare">
|
||||||
<mkdir dir="${build.dir}" />
|
<mkdir dir="${build.dir}" />
|
||||||
<mkdir dir="${war.classes.dir}" />
|
</target>
|
||||||
<mkdir dir="${war.resources.dir}" />
|
|
||||||
<mkdir dir="${test.classes.dir}" />
|
|
||||||
|
|
||||||
<!-- copy all sorts of web stuff into the war directory. -->
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
<copy todir="${war.dir}">
|
target: prepareWebappDir
|
||||||
|
- - - - - - - - - - - - - - - - - -->
|
||||||
|
<target name="prepareWebappDir" depends="prepare">
|
||||||
|
<!-- copy all sorts of web stuff into the webapp directory. -->
|
||||||
|
<copy todir="${main.webapp.dir}">
|
||||||
<fileset dir="${appbase.dir}/web" />
|
<fileset dir="${appbase.dir}/web" />
|
||||||
<fileset dir="${appbase.dir}" includes="themes/**/*" />
|
<fileset dir="${appbase.dir}" includes="themes/**/*" />
|
||||||
</copy>
|
</copy>
|
||||||
|
|
||||||
<copy todir="${war.webinf.dir}">
|
<copy todir="${main.webinf.dir}">
|
||||||
<fileset dir="${appbase.dir}">
|
<fileset dir="${appbase.dir}">
|
||||||
<!-- copy the JARs into the war directory -->
|
<!-- copy the JARs into the war directory -->
|
||||||
<include name="lib/*" />
|
<include name="lib/*" />
|
||||||
<!-- these are already in Tomcat: we mustn't conflict. -->
|
<!-- these will be in the servlet container: we mustn't conflict. -->
|
||||||
<exclude name="lib/jsp-api.jar" />
|
<exclude name="lib/jsp-api.jar" />
|
||||||
<exclude name="lib/servlet-api.jar" />
|
<exclude name="lib/servlet-api.jar" />
|
||||||
</fileset>
|
</fileset>
|
||||||
</copy>
|
</copy>
|
||||||
|
|
||||||
<!-- use the production Log4J properties, unless a debug version exists. -->
|
<!-- use the production Log4J properties, unless a debug version exists. -->
|
||||||
<available file="${appbase.dir}/config/debug.log4j.properties" property="debug.log4j.exists" />
|
<condition property="log4j.properties.file" value="debug.log4j.properties" else="default.log4j.properties">
|
||||||
<copy tofile="${war.classes.dir}/log4j.properties" filtering="true" overwrite="true">
|
<available file="${appbase.dir}/config/debug.log4j.properties" />
|
||||||
<fileset dir="${appbase.dir}/config">
|
</condition>
|
||||||
<include name="default.log4j.properties" unless="debug.log4j.exists" />
|
<copy file="${appbase.dir}/config/${log4j.properties.file}"
|
||||||
<include name="debug.log4j.properties" if="debug.log4j.exists" />
|
tofile="${main.build.dir}/log4j.properties"
|
||||||
</fileset>
|
filtering="true"
|
||||||
|
overwrite="true">
|
||||||
<filterchain>
|
<filterchain>
|
||||||
<expandproperties />
|
<expandproperties />
|
||||||
</filterchain>
|
</filterchain>
|
||||||
</copy>
|
</copy>
|
||||||
|
<copy todir="${main.compiled.dir}">
|
||||||
<copy todir="${war.classes.dir}">
|
<fileset dir="${main.build.dir}">
|
||||||
<!-- copy the deploy.properties into the war directory -->
|
<filename name="log4j.properties"/>
|
||||||
<fileset file="${deploy.properties.file}" />
|
<different targetdir="${main.compiled.dir}" ignorefiletimes="true"/>
|
||||||
|
</fileset>
|
||||||
<!-- copy any xml files from source tree to the war directory -->
|
|
||||||
<fileset dir="${appbase.dir}/src" includes="**/*.xml" />
|
|
||||||
</copy>
|
</copy>
|
||||||
|
|
||||||
<!-- copy the context file into the war directory -->
|
<!-- Copy the build.properties file to the resources directory. -->
|
||||||
<copy file="${appbase.dir}/context.xml" tofile="${war.dir}/META-INF/context.xml" />
|
<copy todir="${main.resources.dir}" file="${build.properties.file}" />
|
||||||
|
|
||||||
|
<!-- If there is a runtime.properties file in the same directory as build.properties, copy that too. -->
|
||||||
|
<dirname file="${build.properties.file}" property="runtime.properties.dir"/>
|
||||||
|
<copy todir="${main.resources.dir}" >
|
||||||
|
<fileset dir="${runtime.properties.dir}" >
|
||||||
|
<filename name="runtime.properties" />
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
|
||||||
|
<!-- copy any xml files from source tree to the war directory -->
|
||||||
|
<copy todir="${main.compiled.dir}">
|
||||||
|
<fileset dir="${appbase.dir}/src" includes="**/*.xml" />
|
||||||
|
</copy>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- =================================
|
||||||
|
target: clean
|
||||||
|
================================= -->
|
||||||
|
<target name="clean" description="--> Delete all artifacts.">
|
||||||
|
<delete dir="${build.dir}" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- =================================
|
<!-- =================================
|
||||||
target: compile
|
target: compile
|
||||||
================================= -->
|
================================= -->
|
||||||
<target name="compile" depends="prepare" description="--> Compile Java sources">
|
<target name="compile" depends="prepareWebappDir" description="--> Compile Java sources">
|
||||||
|
<path id="main.compile.classpath">
|
||||||
|
<fileset dir="${appbase.dir}/lib" includes="*.jar" />
|
||||||
|
</path>
|
||||||
|
|
||||||
<!-- deletes all files that depend on changed .java files -->
|
<!-- deletes all files that depend on changed .java files -->
|
||||||
<depend srcdir="${appbase.dir}/src" destdir="${war.classes.dir}" closure="false" cache="${build.dir}/.depcache">
|
<depend srcdir="${appbase.dir}/src"
|
||||||
<classpath refid="compile.classpath" />
|
destdir="${main.compiled.dir}"
|
||||||
|
closure="false"
|
||||||
|
cache="${main.build.dir}/compileDependencyCache">
|
||||||
|
<classpath refid="main.compile.classpath" />
|
||||||
</depend>
|
</depend>
|
||||||
|
|
||||||
<javac srcdir="${appbase.dir}/src" destdir="${war.classes.dir}" debug="true" deprecation="${javac.deprecation}" encoding="UTF8" includeantruntime="false" optimize="true" source="1.6">
|
<javac srcdir="${appbase.dir}/src"
|
||||||
<classpath refid="compile.classpath" />
|
destdir="${main.compiled.dir}"
|
||||||
|
debug="true"
|
||||||
|
deprecation="${option.javac.deprecation}"
|
||||||
|
encoding="UTF8"
|
||||||
|
includeantruntime="false"
|
||||||
|
optimize="true"
|
||||||
|
source="1.6">
|
||||||
|
<classpath refid="main.compile.classpath" />
|
||||||
</javac>
|
</javac>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- =================================
|
<!-- =================================
|
||||||
target: test
|
target: test
|
||||||
================================= -->
|
================================= -->
|
||||||
<target name="test" depends="compile" unless="skiptests" description="--> Run JUnit tests">
|
<target name="test" depends="compile, compileBuildtools" unless="skiptests" description="--> Run JUnit tests">
|
||||||
<javac srcdir="${appbase.dir}/test" destdir="${test.classes.dir}" debug="true" deprecation="${javac.deprecation}" encoding="UTF8" includeantruntime="false" optimize="false" source="1.6">
|
<path id="test.compile.classpath">
|
||||||
|
<pathelement location="${main.compiled.dir}" />
|
||||||
|
<path refid="main.compile.classpath" />
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<mkdir dir="${unittests.compiled.dir}" />
|
||||||
|
<javac srcdir="${appbase.dir}/test"
|
||||||
|
destdir="${unittests.compiled.dir}"
|
||||||
|
debug="true"
|
||||||
|
deprecation="${option.javac.deprecation}"
|
||||||
|
encoding="UTF8"
|
||||||
|
includeantruntime="false"
|
||||||
|
optimize="false"
|
||||||
|
source="1.6">
|
||||||
<classpath refid="test.compile.classpath" />
|
<classpath refid="test.compile.classpath" />
|
||||||
</javac>
|
</javac>
|
||||||
|
|
||||||
|
<path id="test.run.classpath">
|
||||||
|
<pathelement location="${appbase.dir}/test" />
|
||||||
|
<pathelement location="${unittests.compiled.dir}" />
|
||||||
|
<path refid="test.compile.classpath" />
|
||||||
|
<path refid="utility.run.classpath" />
|
||||||
|
</path>
|
||||||
|
|
||||||
<java classname="edu.cornell.mannlib.vitro.utilities.testing.VitroTestRunner" fork="yes" failonerror="true">
|
<java classname="edu.cornell.mannlib.vitro.utilities.testing.VitroTestRunner" fork="yes" failonerror="true">
|
||||||
<classpath refid="test.run.classpath" />
|
<classpath refid="test.run.classpath" />
|
||||||
<arg file="${appbase.dir}/test" />
|
<arg file="${appbase.dir}/test" />
|
||||||
|
@ -227,112 +237,160 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
||||||
</java>
|
</java>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- =================================
|
|
||||||
target: jar
|
|
||||||
================================= -->
|
|
||||||
<target name="jar" depends="test" description="--> Compile the Java, and build a JAR file">
|
|
||||||
<jar basedir="${war.classes.dir}" destfile="${build.dir}/${ant.project.name}.jar" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- =================================
|
<!-- =================================
|
||||||
target: revisionInfo
|
target: revisionInfo
|
||||||
================================= -->
|
================================= -->
|
||||||
<target name="revisionInfo" depends="test" unless="skipinfo" description="--> Store revision info in build">
|
<target name="revisionInfo" depends="test" unless="skipinfo" description="--> Store revision info in build">
|
||||||
|
<mkdir dir="${main.resources.dir}" />
|
||||||
<tstamp>
|
<tstamp>
|
||||||
<format property="revisionInfo.timestamp" pattern="yyyy-MM-dd HH:mm:ss" />
|
<format property="revisionInfo.timestamp" pattern="yyyy-MM-dd HH:mm:ss" />
|
||||||
</tstamp>
|
</tstamp>
|
||||||
<echo file="${revisionInfo.build.file}">${revisionInfo.timestamp}
|
<echo file="${main.revisioninfo.file}">${revisionInfo.timestamp}
|
||||||
</echo>
|
</echo>
|
||||||
|
|
||||||
<addRevisionInfoLine productName="vitroCore" productCheckoutDir="${corebase.dir}/.." />
|
<addRevisionInfoLine productName="vitroCore" productCheckoutDir="${corebase.dir}/.." />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - -
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
target: prepareSolr
|
target: deployWebapp
|
||||||
- - - - - - - - - - - - - - - - - -->
|
- - - - - - - - - - - - - - - - - -->
|
||||||
<target name="prepareSolr" depends="properties" unless="skipsolr">
|
<target name="deployWebapp" depends="deployProperties, revisionInfo">
|
||||||
<mkdir dir="${solr.home.dir}" />
|
<mkdir dir="${main.tomcat.webapp.dir}" />
|
||||||
<mkdir dir="${solr.build.dir}" />
|
|
||||||
|
|
||||||
<property name="solr.distrib.dir" location="${corebase.dir}/../solr" />
|
<sync todir="${main.tomcat.webapp.dir}" includeemptydirs="true">
|
||||||
<property name="solr.home.template.dir" location="${solr.distrib.dir}/homeDirectoryTemplate" />
|
<fileset dir="${main.webapp.dir}" />
|
||||||
<property name="solr.context.template.file" location="${solr.distrib.dir}/template.context.xml" />
|
<preserveintarget>
|
||||||
<property name="solr.distrib.war" location="${solr.distrib.dir}/apache-solr-3.1.0.war" />
|
<include name="${tomcat.context.filename}"/>
|
||||||
|
</preserveintarget>
|
||||||
|
</sync>
|
||||||
|
|
||||||
<property name="solr.context.file" location="${solr.build.dir}/context.xml" />
|
<!-- Create the context XML with expanded properties. Store it in a temp file for now. -->
|
||||||
<property name="solr.context.temp.file" location="${solr.build.dir}/context.temp.xml" />
|
<copy tofile="${main.build.dir}/context.xml" filtering="true" overwrite="true">
|
||||||
<property name="solr.build.war" location="${solr.build.dir}/solr.war" />
|
<fileset file="${appbase.dir}/context.xml" />
|
||||||
|
|
||||||
<property name="solr.context.name" value="${webapp.name}solr" />
|
|
||||||
<property name="solr.deployed.war" value="${tomcat.home}/webapps/${solr.context.name}.war" />
|
|
||||||
|
|
||||||
<!-- if no mask is defined, leave Solr unsecured. -->
|
|
||||||
<property name="vitro.local.solr.ipaddress.mask" value=".*" />
|
|
||||||
|
|
||||||
<!-- Create and copy the example directory to the solr.home.dir directory. -->
|
|
||||||
<copy todir="${solr.home.dir}">
|
|
||||||
<fileset dir="${solr.home.template.dir}" includes="**/*" />
|
|
||||||
</copy>
|
|
||||||
|
|
||||||
<!-- Create the context configuration XML with expanded properties. Store it in a temp file for now. -->
|
|
||||||
<copy tofile="${solr.context.temp.file}" filtering="true" overwrite="true">
|
|
||||||
<fileset file="${solr.context.template.file}" />
|
|
||||||
<filterchain>
|
<filterchain>
|
||||||
<expandproperties />
|
<expandproperties />
|
||||||
</filterchain>
|
</filterchain>
|
||||||
</copy>
|
</copy>
|
||||||
|
|
||||||
<!-- If the WAR is up to date and the context file hasn't changed, we can skip the deploy. -->
|
<!-- Copy the new context XML only if it differs from the existing one. -->
|
||||||
<condition property="skipsolr">
|
<copy todir="${main.tomcat.webapp.dir}/META-INF">
|
||||||
<and>
|
<fileset dir="${main.build.dir}">
|
||||||
<uptodate targetfile="${solr.build.war}">
|
<filename name="context.xml"/>
|
||||||
<srcfiles file="${solr.distrib.war}" />
|
<different targetdir="${main.tomcat.webapp.dir}/META-INF" ignorefiletimes="true"/>
|
||||||
<srcfiles dir="${appbase.dir}/config/solr/" />
|
</fileset>
|
||||||
</uptodate>
|
</copy>
|
||||||
<filesmatch file1="${solr.context.temp.file}" file2="${solr.context.file}" />
|
</target>
|
||||||
<filesmatch file1="${solr.context.temp.file}" file2="${tomcat.home}/webapps/${solr.context.name}/META-INF/context.xml" />
|
|
||||||
</and>
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
</condition>
|
target: prepareSolr
|
||||||
|
- - - - - - - - - - - - - - - - - -->
|
||||||
|
<target name="prepareSolr" depends="prepare, buildProperties">
|
||||||
|
<!-- create an image of the Solr home directory -->
|
||||||
|
<copy todir="${solr.homeimage.dir}">
|
||||||
|
<fileset dir="${solr.template.dir}/homeDirectoryTemplate" />
|
||||||
|
</copy>
|
||||||
|
|
||||||
|
<!-- create an unpacked image of the Solr WAR, with our config options -->
|
||||||
|
<unwar src="${solr.template.dir}/apache-solr-3.6.2.war" dest="${solr.webapp.dir}" />
|
||||||
|
<copy todir="${solr.webapp.dir}/WEB-INF/classes">
|
||||||
|
<fileset dir="${appbase.dir}/config/solr/" />
|
||||||
|
</copy>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - -
|
<!-- - - - - - - - - - - - - - - - - -
|
||||||
target: deploySolr
|
target: deploySolr
|
||||||
- - - - - - - - - - - - - - - - - -->
|
- - - - - - - - - - - - - - - - - -->
|
||||||
<target name="deploySolr" depends="prepareSolr" unless="skipsolr">
|
<target name="deploySolr" depends="deployProperties, prepareSolr">
|
||||||
<!-- save the new context file, so we can compare against it next time. -->
|
<!-- Deploy to the Solr home directory. -->
|
||||||
<copy file="${solr.context.temp.file}" tofile="${solr.context.file}" />
|
<mkdir dir="${solr.home.dir}" />
|
||||||
|
<sync todir="${solr.home.dir}" includeemptydirs="true">
|
||||||
|
<fileset dir="${solr.homeimage.dir}" />
|
||||||
|
<preserveintarget>
|
||||||
|
<include name="data/**/*"/>
|
||||||
|
</preserveintarget>
|
||||||
|
</sync>
|
||||||
|
|
||||||
<war destfile="${solr.build.war}" needxmlfile="false">
|
<!-- Deploy to Tomcat. -->
|
||||||
<zipfileset src="${solr.distrib.war}" />
|
<mkdir dir="${solr.tomcat.webapp.dir}" />
|
||||||
<classes dir="${appbase.dir}/config/solr" />
|
<sync todir="${solr.tomcat.webapp.dir}" includeemptydirs="true">
|
||||||
<metainf file="${solr.context.file}" />
|
<fileset dir="${solr.webapp.dir}" />
|
||||||
</war>
|
<preserveintarget>
|
||||||
|
<include name="${tomcat.context.filename}"/>
|
||||||
|
</preserveintarget>
|
||||||
|
</sync>
|
||||||
|
|
||||||
<!-- deploy the new WAR -->
|
<!-- Create the context XML with expanded properties. Store it in a temp file for now. -->
|
||||||
<unwar src="${solr.build.war}" dest="${tomcat.home}/webapps/${solr.context.name}" />
|
<copy tofile="${solr.build.dir}/context.xml" filtering="true" overwrite="true">
|
||||||
|
<fileset file="${solr.template.context.file}" />
|
||||||
|
<filterchain>
|
||||||
|
<expandproperties />
|
||||||
|
</filterchain>
|
||||||
|
</copy>
|
||||||
|
|
||||||
|
<!-- Copy the new context XML only if it differs from the existing one. -->
|
||||||
|
<copy todir="${solr.tomcat.webapp.dir}/META-INF">
|
||||||
|
<fileset dir="${solr.build.dir}">
|
||||||
|
<filename name="context.xml"/>
|
||||||
|
<different targetdir="${solr.tomcat.webapp.dir}/META-INF" ignorefiletimes="true"/>
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- =================================
|
<!-- =================================
|
||||||
target: deploy
|
target: deploy
|
||||||
================================= -->
|
================================= -->
|
||||||
<target name="deploy" depends="revisionInfo, deploySolr" description="--> Build the app and install in Tomcat">
|
<target name="deploy"
|
||||||
<property name="webapp.deploy.home" value="${tomcat.home}/webapps/${webapp.name}" />
|
depends="deployWebapp, deploySolr"
|
||||||
|
description="--> Build the app and install in Tomcat">
|
||||||
<mkdir dir="${webapp.deploy.home}" />
|
|
||||||
|
|
||||||
<sync todir="${webapp.deploy.home}" includeemptydirs="true">
|
|
||||||
<fileset dir="${build.dir}/war" />
|
|
||||||
</sync>
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- =================================
|
<!-- =================================
|
||||||
target: war
|
target: all
|
||||||
================================= -->
|
================================= -->
|
||||||
<target name="war" depends="revisionInfo" description="--> Build the app and create a WAR file">
|
<target name="all" depends="clean, deploy" description="--> Run 'clean', then 'deploy'" />
|
||||||
<jar basedir="${build.dir}/war" destfile="${build.dir}/${webapp.name}.war" />
|
|
||||||
|
|
||||||
|
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
OUTSIDE THE MAIN BUILD SEQUENCE
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||||
|
|
||||||
|
<!-- =================================
|
||||||
|
target: distribute
|
||||||
|
================================= -->
|
||||||
|
<target name="distribute"
|
||||||
|
depends="revisionInfo, prepareSolr"
|
||||||
|
description="--> Build the app and create a distribution bundle">
|
||||||
|
<mkdir dir="${distribution.dir}" />
|
||||||
|
|
||||||
|
<jar basedir="${main.webapp.dir}" destfile="${distribution.dir}/${webapp.name}.war" />
|
||||||
|
<jar basedir="${solr.webapp.dir}" destfile="${distribution.dir}/${solr.app.name}.war" />
|
||||||
|
<tar basedir="${solr.homeimage.dir}" destfile="${distribution.dir}/solrhome.tar" />
|
||||||
|
|
||||||
|
<tar basedir="${distribution.dir}" destfile="${distribution.tar.gz.file}" compression="gzip" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<!-- =================================
|
||||||
|
target: describe
|
||||||
|
================================= -->
|
||||||
|
<target name="describe"
|
||||||
|
description="--> Describe the targets (this is the default).">
|
||||||
|
<echo>
|
||||||
|
all - Runs "clean", then "deploy".
|
||||||
|
clean - Delete all artifacts so the next build will be from scratch.
|
||||||
|
compile - Compile the Java source files.
|
||||||
|
orng - Configure and deploy the ORNG Shindig application.
|
||||||
|
test - Compile and run the JUnit tests.
|
||||||
|
distribute - Create WAR files to be deployed in a servlet container.
|
||||||
|
deploy - Deploy the application directly into the Tomcat webapps directory.
|
||||||
|
</echo>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- =================================
|
||||||
|
target: jar
|
||||||
|
================================= -->
|
||||||
|
<target name="jar" depends="test" description="--> Compile the Java, and build a JAR file">
|
||||||
|
<jar basedir="${main.compiled.dir}" destfile="${build.dir}/${ant.project.name}.jar" />
|
||||||
|
</target>
|
||||||
|
|
||||||
<!-- =================================
|
<!-- =================================
|
||||||
target: licenser
|
target: licenser
|
||||||
|
@ -348,7 +406,7 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
||||||
<!-- =================================
|
<!-- =================================
|
||||||
target: jarlist
|
target: jarlist
|
||||||
================================= -->
|
================================= -->
|
||||||
<target name="jarlist" depends="jar" description="Figure out what JARs are not needed">
|
<target name="jarlist" depends="compileBuildtools, jar" description="Figure out what JARs are not needed">
|
||||||
<java classname="edu.cornell.mannlib.vitro.utilities.jarlist.JarLister" fork="no" failonerror="true">
|
<java classname="edu.cornell.mannlib.vitro.utilities.jarlist.JarLister" fork="no" failonerror="true">
|
||||||
<classpath refid="utility.run.classpath" />
|
<classpath refid="utility.run.classpath" />
|
||||||
<arg value="${build.dir}/${ant.project.name}.jar" />
|
<arg value="${build.dir}/${ant.project.name}.jar" />
|
||||||
|
@ -393,13 +451,16 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
||||||
<attribute name="productName" />
|
<attribute name="productName" />
|
||||||
<attribute name="productCheckoutDir" />
|
<attribute name="productCheckoutDir" />
|
||||||
<sequential>
|
<sequential>
|
||||||
<java classname="edu.cornell.mannlib.vitro.utilities.revisioninfo.RevisionInfoBuilder" fork="no" failonerror="true">
|
<java classname="edu.cornell.mannlib.vitro.utilities.revisioninfo.RevisionInfoBuilder"
|
||||||
|
fork="no"
|
||||||
|
failonerror="true">
|
||||||
<classpath refid="utility.run.classpath" />
|
<classpath refid="utility.run.classpath" />
|
||||||
<arg value="@{productName}" />
|
<arg value="@{productName}" />
|
||||||
<arg file="@{productCheckoutDir}" />
|
<arg file="@{productCheckoutDir}" />
|
||||||
<arg file="${revisionInfo.build.file}" />
|
<arg file="${main.revisioninfo.file}" />
|
||||||
</java>
|
</java>
|
||||||
</sequential>
|
</sequential>
|
||||||
</macrodef>
|
</macrodef>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
29
webapp/config/example.build.properties
Normal file
29
webapp/config/example.build.properties
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Vitro build properties
|
||||||
|
#
|
||||||
|
# This file is provided as example.build.properties.
|
||||||
|
#
|
||||||
|
# Save a copy of this file as build.properties, and edit the properties as
|
||||||
|
# needed for your installation.
|
||||||
|
#
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# The base install directory for your Tomcat server. The Vitro application
|
||||||
|
# will be deployed in the /webapps directory below this base.
|
||||||
|
#
|
||||||
|
tomcat.home = /usr/local/tomcat
|
||||||
|
|
||||||
|
#
|
||||||
|
# The name of the Vitro application. This will be used as the name of the
|
||||||
|
# subdirectory within your Tomcat server's /webapps directory. It also appears
|
||||||
|
# in the URL for the application. For example, http://my.vitro.server/vitro
|
||||||
|
#
|
||||||
|
webapp.name = vitro
|
||||||
|
|
||||||
|
#
|
||||||
|
# The location where the Vitro application will store the data that it creates.
|
||||||
|
# This includes uploaded files (usually images) and the search index.
|
||||||
|
#
|
||||||
|
vitro.home = /usr/local/vitro/home
|
|
@ -1,11 +1,11 @@
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Vitro deployment properties
|
# Vitro runtime properties
|
||||||
#
|
#
|
||||||
# This file is provided as example.deploy.properties.
|
# This file is provided as example.runtime.properties.
|
||||||
#
|
#
|
||||||
# Save a copy of this file as deploy.properties, and edit the properties as
|
# Save a copy of this file as runtime.properties in your Vitro home directory,
|
||||||
# needed for your deployment.
|
# and edit the properties as needed for your installation.
|
||||||
#
|
#
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -22,19 +22,6 @@
|
||||||
#
|
#
|
||||||
Vitro.defaultNamespace = http://vivo.mydomain.edu/individual/
|
Vitro.defaultNamespace = http://vivo.mydomain.edu/individual/
|
||||||
|
|
||||||
#
|
|
||||||
# The base install directory for your Tomcat server. The Vitro application
|
|
||||||
# will be deployed in the /webapps directory below this base.
|
|
||||||
#
|
|
||||||
tomcat.home = /usr/local/tomcat
|
|
||||||
|
|
||||||
#
|
|
||||||
# The name of the Vitro application. This will be used as the name of the
|
|
||||||
# subdirectory within your Tomcat server's /webapps directory. It also appears
|
|
||||||
# in the URL for the application. For example, http://my.vitro.server/vitro
|
|
||||||
#
|
|
||||||
webapp.name = vitro
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# URL of Solr context used in local Vitro search. This will usually consist of:
|
# URL of Solr context used in local Vitro search. This will usually consist of:
|
||||||
# scheme + server_name + port + vitro_webapp_name + "solr"
|
# scheme + server_name + port + vitro_webapp_name + "solr"
|
||||||
|
@ -45,28 +32,6 @@ webapp.name = vitro
|
||||||
# vitro.local.solr.url = http://localhost:8080/vitrosolr
|
# vitro.local.solr.url = http://localhost:8080/vitrosolr
|
||||||
vitro.local.solr.url = http://localhost:8080/vitrosolr
|
vitro.local.solr.url = http://localhost:8080/vitrosolr
|
||||||
|
|
||||||
#
|
|
||||||
# Restricts access to the Solr search platform. The value is a regular expression.
|
|
||||||
# When a request is made to Solr, the IP address of the requestor must match the
|
|
||||||
# regular expression, or the request will be rejected.
|
|
||||||
#
|
|
||||||
# NOTE: don't leave a space on the end of the line, unless you want it to be
|
|
||||||
# part of the expression.
|
|
||||||
# Examples:
|
|
||||||
# vitro.local.solr.ipaddress.mask = 127\.0\.0\.1
|
|
||||||
# vitro.local.solr.ipaddress.mask = 127\.0\.0\.1|0:0:0:0:0:0:0:1
|
|
||||||
# vitro.local.solr.ipaddress.mask = 169\.254\..*
|
|
||||||
# If this line is removed, your Solr server will respond to requests from any
|
|
||||||
# location. This may be useful for experimenting but would likely be considered
|
|
||||||
# a security problem in a production environment.
|
|
||||||
vitro.local.solr.ipaddress.mask = 127\.0\.0\.1|[0:]+:1
|
|
||||||
|
|
||||||
#
|
|
||||||
# The location where the Vitro application will store the data that it creates.
|
|
||||||
# This includes uploaded files (usually images) and the search index.
|
|
||||||
#
|
|
||||||
vitro.home.directory = /usr/local/vitro/data
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Email parameters which VIVO can use to send mail. If these are left empty,
|
# Email parameters which VIVO can use to send mail. If these are left empty,
|
||||||
# the "Contact Us" form will be disabled and users will not be notified of
|
# the "Contact Us" form will be disabled and users will not be notified of
|
||||||
|
@ -154,3 +119,55 @@ proxy.eligibleTypeList = http://www.w3.org/2002/07/owl#Thing
|
||||||
# header supplied by the browser. Default is true if not set.
|
# header supplied by the browser. Default is true if not set.
|
||||||
#
|
#
|
||||||
RDFService.languageFilter = true
|
RDFService.languageFilter = true
|
||||||
|
|
||||||
|
#
|
||||||
|
# Force VIVO to use a specific language or Locale instead of those
|
||||||
|
# specified by the browser. This affects RDF data retrieved from the model,
|
||||||
|
# if RDFService.languageFilter is true. This also affects the text of pages
|
||||||
|
# that have been modified to support multiple languages.
|
||||||
|
#
|
||||||
|
# languages.forceLocale = en_US
|
||||||
|
|
||||||
|
#
|
||||||
|
# A list of supported languages or Locales that the user may choose to
|
||||||
|
# use instead of the one specified by the browser. Selection images must
|
||||||
|
# be available in the i18n/images directory of the theme. This affects
|
||||||
|
# RDF data retrieved from the model, if RDFService.languageFilter is true.
|
||||||
|
# This also affects the text of pages that have been modified to support
|
||||||
|
# multiple languages.
|
||||||
|
#
|
||||||
|
# This should not be used with languages.forceLocale, which will override it.
|
||||||
|
#
|
||||||
|
# languages.selectableLocales = en, es, fr
|
||||||
|
|
||||||
|
#
|
||||||
|
# For developers only: Setting this option to "true" slows down Vitro performance.
|
||||||
|
#
|
||||||
|
# Defeat the Freemarker template cache, so each template is read from disk
|
||||||
|
# on each request. This permits developers to immediately see the effect of
|
||||||
|
# changes to the template. The default is <code>false</code>, which means
|
||||||
|
# that a cached copy of each template will be used for 60 seconds before
|
||||||
|
# the disk is checked for a new version.
|
||||||
|
#
|
||||||
|
# developer.defeatFreemarkerCache = true
|
||||||
|
|
||||||
|
#
|
||||||
|
# For developers only: Setting this option to "true" slows down Vitro performance.
|
||||||
|
#
|
||||||
|
# Defeat the cache of language-specific text strings, so the language file
|
||||||
|
# is read from disk on each request. This permits developers to immediately
|
||||||
|
# see the effect of changes to the text strings. The default is
|
||||||
|
# <code>false</code>, which means that the language file is read when
|
||||||
|
# VIVO starts up, or when a new theme is selected.
|
||||||
|
#
|
||||||
|
# developer.defeatI18nCache = true
|
||||||
|
|
||||||
|
#
|
||||||
|
# For developers only: Setting this option to "true" slows down Vitro performance.
|
||||||
|
#
|
||||||
|
# Add starting and ending delimiters to each Freemarker template, so you can see
|
||||||
|
# which template were invoked by viewing the generated HTML. The default is
|
||||||
|
# <code>false</code>.
|
||||||
|
#
|
||||||
|
# developer.insertFreemarkerDelimiters = true
|
||||||
|
|
|
@ -165,6 +165,9 @@ webapp/web/js/raphael/*
|
||||||
# See /doc/3rd-party-licenses.txt for LICENSE file
|
# See /doc/3rd-party-licenses.txt for LICENSE file
|
||||||
webapp/web/js/sparql/prototype.js
|
webapp/web/js/sparql/prototype.js
|
||||||
|
|
||||||
|
# See /doc/3rd-party-licenses.txt for LICENSE file
|
||||||
|
webapp/web/js/amplify/amplify.store.min.js
|
||||||
|
|
||||||
# Apache Solr search platform. See /doc/3rd-party-licenses.txt for LICENSE file
|
# Apache Solr search platform. See /doc/3rd-party-licenses.txt for LICENSE file
|
||||||
solr/**/*
|
solr/**/*
|
||||||
solr/*
|
solr/*
|
||||||
|
|
|
@ -1,20 +1,5 @@
|
||||||
<Context>
|
<Context>
|
||||||
|
|
||||||
<!-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
<!-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
<!--
|
|
||||||
Vitro will interpret this as either a file path or a resource path. So,
|
|
||||||
if a simple resource path is used, such as "deploy.properties", Vitro
|
|
||||||
will find the file at:
|
|
||||||
${Tomcat}/webapps/vitro/WEB-INF/classes/deploy.properties
|
|
||||||
For an external file, specify a full file path, like
|
|
||||||
"/usr/local/vitro/deploy.properties".
|
|
||||||
-->
|
|
||||||
<Environment type="java.lang.String" override="false"
|
|
||||||
name="path.configuration"
|
|
||||||
value="deploy.properties"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Disable the attempt to persist sessions when Tomcat shuts down.
|
Disable the attempt to persist sessions when Tomcat shuts down.
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class RootUserPolicy implements PolicyIface {
|
||||||
PROPERTY_ROOT_USER_EMAIL);
|
PROPERTY_ROOT_USER_EMAIL);
|
||||||
if (email == null) {
|
if (email == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"deploy.properties must contain a value for '"
|
"runtime.properties must contain a value for '"
|
||||||
+ PROPERTY_ROOT_USER_EMAIL + "'");
|
+ PROPERTY_ROOT_USER_EMAIL + "'");
|
||||||
} else {
|
} else {
|
||||||
return email;
|
return email;
|
||||||
|
@ -177,7 +177,7 @@ public class RootUserPolicy implements PolicyIface {
|
||||||
|
|
||||||
private void complainAboutMultipleRootUsers() {
|
private void complainAboutMultipleRootUsers() {
|
||||||
for (String other : otherRootUsers) {
|
for (String other : otherRootUsers) {
|
||||||
ss.warning(this, "deploy.properties specifies '"
|
ss.warning(this, "runtime.properties specifies '"
|
||||||
+ configuredRootUser + "' as the value for '"
|
+ configuredRootUser + "' as the value for '"
|
||||||
+ PROPERTY_ROOT_USER_EMAIL
|
+ PROPERTY_ROOT_USER_EMAIL
|
||||||
+ "', but the system also contains this root user: "
|
+ "', but the system also contains this root user: "
|
||||||
|
@ -189,7 +189,7 @@ public class RootUserPolicy implements PolicyIface {
|
||||||
|
|
||||||
private void complainAboutWrongRootUsers() {
|
private void complainAboutWrongRootUsers() {
|
||||||
for (String other : otherRootUsers) {
|
for (String other : otherRootUsers) {
|
||||||
ss.warning(this, "deploy.properties specifies '"
|
ss.warning(this, "runtime.properties specifies '"
|
||||||
+ configuredRootUser + "' as the value for '"
|
+ configuredRootUser + "' as the value for '"
|
||||||
+ PROPERTY_ROOT_USER_EMAIL
|
+ PROPERTY_ROOT_USER_EMAIL
|
||||||
+ "', but the system contains this root user instead: "
|
+ "', but the system contains this root user instead: "
|
||||||
|
|
|
@ -49,15 +49,6 @@ public class ApplicationBean {
|
||||||
private String copyrightAnchor;
|
private String copyrightAnchor;
|
||||||
private String themeDir;
|
private String themeDir;
|
||||||
|
|
||||||
public static ApplicationBean getAppBean(ServletContext sc){
|
|
||||||
if( sc != null ){
|
|
||||||
Object obj = sc.getAttribute("applicationBean");
|
|
||||||
if( obj != null )
|
|
||||||
return (ApplicationBean)obj;
|
|
||||||
}
|
|
||||||
return new ApplicationBean();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String output = "Application Bean Contents:\n";
|
String output = "Application Bean Contents:\n";
|
||||||
output += " initialized from DB: [" + initialized + "]\n";
|
output += " initialized from DB: [" + initialized + "]\n";
|
||||||
|
|
|
@ -20,8 +20,8 @@ import org.apache.commons.logging.LogFactory;
|
||||||
* are attached to the servlet context.
|
* are attached to the servlet context.
|
||||||
*
|
*
|
||||||
* The customary behavior is for ConfigurationPropertiesSetup to create a
|
* The customary behavior is for ConfigurationPropertiesSetup to create a
|
||||||
* ConfigurationPropertiesImpl, which will parse the deploy.properties file for
|
* ConfigurationPropertiesImpl, which will obtain the properties from the
|
||||||
* these properties.
|
* build.properties file and the runtime.properties file.
|
||||||
*/
|
*/
|
||||||
public abstract class ConfigurationProperties {
|
public abstract class ConfigurationProperties {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
|
|
|
@ -9,13 +9,16 @@ import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The basic implementation of ConfigurationProperties. It loads the
|
* The basic implementation of ConfigurationProperties. It loads the
|
||||||
* configuration properties from a properties file and stores them in a map.
|
* configuration properties from a properties file and stores them in a map. It
|
||||||
|
* also permits the caller to supply a map of "preemptive" properties that will
|
||||||
|
* be included and will override any matching properties from the file.
|
||||||
*
|
*
|
||||||
* Leading and trailing white space are trimmed from the property values.
|
* Leading and trailing white space are trimmed from the property values.
|
||||||
*
|
*
|
||||||
|
@ -27,23 +30,25 @@ public class ConfigurationPropertiesImpl extends ConfigurationProperties {
|
||||||
|
|
||||||
private final Map<String, String> propertyMap;
|
private final Map<String, String> propertyMap;
|
||||||
|
|
||||||
public ConfigurationPropertiesImpl(InputStream stream) {
|
public ConfigurationPropertiesImpl(InputStream stream,
|
||||||
|
Map<String, String> preemptiveProperties) throws IOException {
|
||||||
Properties props = loadFromPropertiesFile(stream);
|
Properties props = loadFromPropertiesFile(stream);
|
||||||
Map<String, String> map = copyPropertiesToMap(props);
|
Map<String, String> map = copyPropertiesToMap(props);
|
||||||
trimWhiteSpaceFromValues(map);
|
|
||||||
this.propertyMap = Collections.unmodifiableMap(map);
|
|
||||||
|
|
||||||
|
if (preemptiveProperties != null) {
|
||||||
|
map.putAll(preemptiveProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
trimWhiteSpaceFromValues(map);
|
||||||
|
|
||||||
|
this.propertyMap = Collections.unmodifiableMap(map);
|
||||||
log.debug("Configuration properties are: " + map);
|
log.debug("Configuration properties are: " + map);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Properties loadFromPropertiesFile(InputStream stream) {
|
private Properties loadFromPropertiesFile(InputStream stream)
|
||||||
|
throws IOException {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
try {
|
|
||||||
props.load(stream);
|
props.load(stream);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Failed to parse the configuration properties file.", e);
|
|
||||||
}
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +89,8 @@ public class ConfigurationPropertiesImpl extends ConfigurationProperties {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ConfigurationPropertiesImpl[propertyMap=" + propertyMap + "]";
|
return "ConfigurationPropertiesImpl[propertyMap="
|
||||||
|
+ new TreeMap<String, String>(propertyMap) + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,13 @@ package edu.cornell.mannlib.vitro.webapp.config;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.naming.Context;
|
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
@ -21,61 +23,45 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the configuration properties from a file and stores them in the servlet
|
* Locates the runtime configuration properties and stores them in the servlet
|
||||||
* context.
|
* context.
|
||||||
*
|
*
|
||||||
* This must be invoked before any listener that requires configuration
|
* This must be invoked before any listener that requires configuration
|
||||||
* properties.
|
* properties.
|
||||||
*
|
*
|
||||||
* The path to the file can be specified by an Environment name in the Context,
|
* The properties file must be called 'runtime.properties' in the Vitro home
|
||||||
* like this:
|
* directory. The path to the Vitro home directory can be specifed by an JNDI
|
||||||
|
* value, or by a System property, or by a property in
|
||||||
|
* WEB-INF/resources/build.properties, in that order. If the Vitro home
|
||||||
|
* directory is specified in more than one way, a warning is issued and the
|
||||||
|
* first value is used.
|
||||||
*
|
*
|
||||||
* <pre>
|
* If the Vitro home directory cannot be located, or if it does not contain a
|
||||||
|
* file called 'runtime.properties', or if the file cannot be loaded, a fatal
|
||||||
|
* error is registered to abort the startup.
|
||||||
*
|
*
|
||||||
* <Context override="true">
|
* The ConfigurationProperties bean is created from the key/value pairs found in
|
||||||
* <Environment name="path.configuration"
|
* 'runtime.properties', and is stored in the servlet context. The value that
|
||||||
* value="/wherever/the/file/lives/deploy.properties"
|
* was determined for 'vitro.home' is also included in the bean.
|
||||||
* type="java.lang.String"
|
|
||||||
* override="false" />
|
|
||||||
* </Context>
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* We look in this environment variable to find the path to the properties file.
|
|
||||||
* If there is no such environment variable, the default path is used.
|
|
||||||
*
|
|
||||||
* Once the path has been determined, we will use it to look for a resource in
|
|
||||||
* the classpath. So if the path is "deploy.properties", it might be found in
|
|
||||||
* "tomcat/webapps/vivo/WEB-INF/classes/deploy.properties". Of course, it might
|
|
||||||
* also be found in any other portion of the classpath as well.
|
|
||||||
*
|
|
||||||
* If we can't find the resource in the classpath, we will use it to look for an
|
|
||||||
* external file. So, one might reasonably set this value to something like
|
|
||||||
* "/usr/local/vitro/stuff/my.deploy.properties".
|
|
||||||
*
|
|
||||||
* If neither a resource nor an external file can be found, we throw an
|
|
||||||
* exception and set AbortStartup.
|
|
||||||
*/
|
*/
|
||||||
public class ConfigurationPropertiesSetup implements ServletContextListener {
|
public class ConfigurationPropertiesSetup implements ServletContextListener {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
.getLog(ConfigurationPropertiesSetup.class);
|
.getLog(ConfigurationPropertiesSetup.class);
|
||||||
|
|
||||||
/**
|
/** JNDI path that defines the Vitro home directory */
|
||||||
* The JNDI naming context where Tomcat stores environment attributes.
|
private static final String VHD_JNDI_PATH = "java:comp/env/vitro/home";
|
||||||
*/
|
|
||||||
static final String JNDI_BASE = "java:comp/env";
|
|
||||||
|
|
||||||
/**
|
/** System property that defines the Vitro home directory */
|
||||||
* The name of the JNDI environment mapping for the path to the
|
private static final String VHD_SYSTEM_PROPERTY = "vitro.home";
|
||||||
* configuration file (or resource).
|
|
||||||
*/
|
|
||||||
static final String PATH_CONFIGURATION = "path.configuration";
|
|
||||||
|
|
||||||
/**
|
/** build.properties property that defines the Vitro home directory */
|
||||||
* If we don't find the path to the config properties from a JNDI mapping,
|
private static final String VHD_BUILD_PROPERTY = "vitro.home";
|
||||||
* use this. Not final, so we can jigger it for unit tests.
|
|
||||||
*/
|
/** Configuration property to store the Vitro home directory */
|
||||||
private static String DEFAULT_CONFIG_PATH = "deploy.properties";
|
private static final String VHD_CONFIGURATION_PROPERTY = "vitro.home";
|
||||||
|
|
||||||
|
/** Name of the file that contains runtime properties. */
|
||||||
|
private static final String FILE_RUNTIME_PROPERTIES = "runtime.properties";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextInitialized(ServletContextEvent sce) {
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
@ -85,12 +71,18 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
|
||||||
try {
|
try {
|
||||||
InputStream stream = null;
|
InputStream stream = null;
|
||||||
try {
|
try {
|
||||||
stream = locatePropertiesFile();
|
File vitroHomeDir = locateVitroHomeDirectory(ctx, ss);
|
||||||
|
|
||||||
|
File runtimePropertiesFile = locateRuntimePropertiesFile(
|
||||||
|
vitroHomeDir, ss);
|
||||||
|
stream = new FileInputStream(runtimePropertiesFile);
|
||||||
|
|
||||||
|
Map<String, String> preempts = createPreemptiveProperties(
|
||||||
|
VHD_CONFIGURATION_PROPERTY, vitroHomeDir);
|
||||||
ConfigurationPropertiesImpl bean = new ConfigurationPropertiesImpl(
|
ConfigurationPropertiesImpl bean = new ConfigurationPropertiesImpl(
|
||||||
stream);
|
stream, preempts);
|
||||||
ConfigurationProperties.setBean(ctx, bean);
|
|
||||||
|
|
||||||
|
ConfigurationProperties.setBean(ctx, bean);
|
||||||
ss.info(this, "Loaded " + bean.getPropertyMap().size()
|
ss.info(this, "Loaded " + bean.getPropertyMap().size()
|
||||||
+ " properties.");
|
+ " properties.");
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -102,81 +94,171 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
ss.fatal(this, e.getMessage(), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e, e);
|
|
||||||
ss.fatal(this, e.getMessage(), e);
|
ss.fatal(this, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream locatePropertiesFile() {
|
|
||||||
String path = determinePathToProperties();
|
|
||||||
log.debug("Configuration properties path is '" + path + "'");
|
|
||||||
|
|
||||||
if (resourceExists(path)) {
|
|
||||||
log.debug("Found configuration properties as a resource.");
|
|
||||||
return getResourceStream(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (externalFileExists(path)) {
|
|
||||||
log.debug("Found configuration properties as an external file.");
|
|
||||||
return getExternalFileStream(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException("Can't find the properties file at '"
|
|
||||||
+ path + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we can't find it with JNDI, use the default.
|
* Look in the JDNI environment, the system properties, and the
|
||||||
|
* build.properties file.
|
||||||
|
*
|
||||||
|
* If we don't find it, fail. If we find it more than once, warn and use the
|
||||||
|
* first one.
|
||||||
|
*
|
||||||
|
* Confirm that it is an existing, readable directory.
|
||||||
*/
|
*/
|
||||||
private String determinePathToProperties() {
|
private File locateVitroHomeDirectory(ServletContext ctx, StartupStatus ss) {
|
||||||
|
Map<String, String> whereWasIt = new LinkedHashMap<String, String>();
|
||||||
|
getVhdFromJndi(whereWasIt);
|
||||||
|
getVhdFromSystemProperties(whereWasIt);
|
||||||
|
getVhdFromBuildProperties(ctx, whereWasIt);
|
||||||
|
|
||||||
|
if (whereWasIt.isEmpty()) {
|
||||||
|
String message = String.format("Can't find a value "
|
||||||
|
+ "for the Vitro home directory. "
|
||||||
|
+ "Looked in JNDI environment at '%s'. "
|
||||||
|
+ "Looked for a system property named '%s'. "
|
||||||
|
+ "Looked in 'WEB-INF/resources/build.properties' "
|
||||||
|
+ "for '%s'.", VHD_JNDI_PATH, VHD_SYSTEM_PROPERTY,
|
||||||
|
VHD_BUILD_PROPERTY);
|
||||||
|
throw new IllegalStateException(message);
|
||||||
|
} else if (whereWasIt.size() > 1) {
|
||||||
|
String message = String.format("Found multiple values for the "
|
||||||
|
+ "Vitro home directory: " + whereWasIt.keySet());
|
||||||
|
ss.warning(this, message);
|
||||||
|
}
|
||||||
|
String message = whereWasIt.keySet().iterator().next();
|
||||||
|
String vhdPath = whereWasIt.values().iterator().next();
|
||||||
|
|
||||||
|
ss.info(this, message);
|
||||||
|
|
||||||
|
File vhd = new File(vhdPath);
|
||||||
|
if (!vhd.exists()) {
|
||||||
|
throw new IllegalStateException("Vitro home directory '" + vhdPath
|
||||||
|
+ "' does not exist.");
|
||||||
|
}
|
||||||
|
if (!vhd.isDirectory()) {
|
||||||
|
throw new IllegalStateException("Vitro home directory '" + vhdPath
|
||||||
|
+ "' is not a directory.");
|
||||||
|
}
|
||||||
|
if (!vhd.canRead()) {
|
||||||
|
throw new IllegalStateException("Vitro home directory '" + vhdPath
|
||||||
|
+ "' cannot be read.");
|
||||||
|
}
|
||||||
|
if (!vhd.canWrite()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Can't write to Vitro home directory: '" + vhdPath + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return vhd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getVhdFromJndi(Map<String, String> whereWasIt) {
|
||||||
try {
|
try {
|
||||||
Context envCtx = (Context) new InitialContext().lookup(JNDI_BASE);
|
String vhdPath = (String) new InitialContext()
|
||||||
if (envCtx == null) {
|
.lookup(VHD_JNDI_PATH);
|
||||||
log.debug("JNDI Lookup on '" + JNDI_BASE + "' failed.");
|
|
||||||
return DEFAULT_CONFIG_PATH;
|
if (vhdPath == null) {
|
||||||
|
log.debug("Didn't find a JNDI value at '" + VHD_JNDI_PATH
|
||||||
|
+ "'.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String configPath = (String) envCtx.lookup(PATH_CONFIGURATION);
|
log.debug("'" + VHD_JNDI_PATH + "' as specified by JNDI: "
|
||||||
if (configPath == null) {
|
+ vhdPath);
|
||||||
log.debug("JNDI Lookup on '" + PATH_CONFIGURATION + "' failed.");
|
String message = String.format(
|
||||||
return DEFAULT_CONFIG_PATH;
|
"JNDI environment '%s' was set to '%s'", VHD_JNDI_PATH,
|
||||||
}
|
vhdPath);
|
||||||
|
whereWasIt.put(message, vhdPath);
|
||||||
log.debug("deploy.property as specified by JNDI: " + configPath);
|
|
||||||
return configPath;
|
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
log.warn("JNDI lookup failed. "
|
log.debug("JNDI lookup failed. " + e);
|
||||||
+ "Using default path for config properties.", e);
|
|
||||||
return DEFAULT_CONFIG_PATH;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean resourceExists(String path) {
|
private void getVhdFromSystemProperties(Map<String, String> whereWasIt) {
|
||||||
return getResourceStream(path) != null;
|
String vhdPath = System.getProperty(VHD_SYSTEM_PROPERTY);
|
||||||
|
|
||||||
|
if (vhdPath == null) {
|
||||||
|
log.debug("Didn't find a system property value at '"
|
||||||
|
+ VHD_SYSTEM_PROPERTY + "'.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream getResourceStream(String path) {
|
log.debug("'" + VHD_SYSTEM_PROPERTY
|
||||||
return getClass().getClassLoader().getResourceAsStream(path);
|
+ "' as specified by system property: " + vhdPath);
|
||||||
|
String message = String.format("System property '%s' was set to '%s'",
|
||||||
|
VHD_SYSTEM_PROPERTY, vhdPath);
|
||||||
|
whereWasIt.put(message, vhdPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean externalFileExists(String path) {
|
private void getVhdFromBuildProperties(ServletContext ctx,
|
||||||
File file = new File(path);
|
Map<String, String> whereWasIt) {
|
||||||
return file.isFile();
|
String resourcePath = "/WEB-INF/resources/build.properties";
|
||||||
}
|
|
||||||
|
|
||||||
private InputStream getExternalFileStream(String path) {
|
|
||||||
InputStream stream = null;
|
InputStream stream = null;
|
||||||
File file = new File(path);
|
|
||||||
if (file.isFile()) {
|
|
||||||
try {
|
try {
|
||||||
stream = new FileInputStream(file);
|
stream = ctx.getResourceAsStream(resourcePath);
|
||||||
} catch (FileNotFoundException e) {
|
if (stream == null) {
|
||||||
// testing file.isFile() should have prevented this
|
log.debug("Didn't find a resource at '" + resourcePath + "'.");
|
||||||
log.error(e, e);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.load(stream);
|
||||||
|
String vhdPath = props.getProperty(VHD_BUILD_PROPERTY);
|
||||||
|
if (vhdPath == null) {
|
||||||
|
log.debug("'" + resourcePath + "' didn't contain a value for '"
|
||||||
|
+ VHD_BUILD_PROPERTY + "'.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("'" + VHD_BUILD_PROPERTY
|
||||||
|
+ "' as specified by build.properties: " + vhdPath);
|
||||||
|
String message = String.format(
|
||||||
|
"In resource '%s', '%s' was set to '%s'.", resourcePath,
|
||||||
|
VHD_BUILD_PROPERTY, vhdPath);
|
||||||
|
whereWasIt.put(message, vhdPath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Failed to load from '" + resourcePath + "'.", e);
|
||||||
|
} finally {
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stream;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File locateRuntimePropertiesFile(File vitroHomeDir, StartupStatus ss) {
|
||||||
|
File rpf = new File(vitroHomeDir, FILE_RUNTIME_PROPERTIES);
|
||||||
|
|
||||||
|
if (!rpf.exists()) {
|
||||||
|
throw new IllegalStateException("Did not find '"
|
||||||
|
+ FILE_RUNTIME_PROPERTIES + "' in vitro home directory '"
|
||||||
|
+ vitroHomeDir + "'");
|
||||||
|
}
|
||||||
|
if (!rpf.isFile()) {
|
||||||
|
throw new IllegalStateException("'" + rpf.getPath()
|
||||||
|
+ "' is not a file.");
|
||||||
|
}
|
||||||
|
if (!rpf.canRead()) {
|
||||||
|
throw new IllegalStateException("Cannot read '" + rpf.getPath()
|
||||||
|
+ "'.");
|
||||||
|
}
|
||||||
|
ss.info(this, "Loading runtime properties from '" + rpf.getPath() + "'");
|
||||||
|
return rpf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> createPreemptiveProperties(
|
||||||
|
String propertyVitroHome, File vitroHomeDir) {
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
map.put(propertyVitroHome, vitroHomeDir.getAbsolutePath());
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class ConfigurationPropertiesSmokeTests implements
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
.getLog(ConfigurationPropertiesSmokeTests.class);
|
.getLog(ConfigurationPropertiesSmokeTests.class);
|
||||||
|
|
||||||
private static final String PROPERTY_HOME_DIRECTORY = "vitro.home.directory";
|
private static final String PROPERTY_HOME_DIRECTORY = "vitro.home";
|
||||||
private static final String PROPERTY_DB_URL = "VitroConnection.DataSource.url";
|
private static final String PROPERTY_DB_URL = "VitroConnection.DataSource.url";
|
||||||
private static final String PROPERTY_DB_USERNAME = "VitroConnection.DataSource.username";
|
private static final String PROPERTY_DB_USERNAME = "VitroConnection.DataSource.username";
|
||||||
private static final String PROPERTY_DB_PASSWORD = "VitroConnection.DataSource.password";
|
private static final String PROPERTY_DB_PASSWORD = "VitroConnection.DataSource.password";
|
||||||
|
@ -61,7 +61,7 @@ public class ConfigurationPropertiesSmokeTests implements
|
||||||
ConfigurationProperties props, StartupStatus ss) {
|
ConfigurationProperties props, StartupStatus ss) {
|
||||||
String homeDirectoryPath = props.getProperty(PROPERTY_HOME_DIRECTORY);
|
String homeDirectoryPath = props.getProperty(PROPERTY_HOME_DIRECTORY);
|
||||||
if (homeDirectoryPath == null || homeDirectoryPath.isEmpty()) {
|
if (homeDirectoryPath == null || homeDirectoryPath.isEmpty()) {
|
||||||
ss.fatal(this, "deploy.properties does not contain a value for '"
|
ss.fatal(this, "Can't find a value for the home directory: '"
|
||||||
+ PROPERTY_HOME_DIRECTORY + "'");
|
+ PROPERTY_HOME_DIRECTORY + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -97,19 +97,19 @@ public class ConfigurationPropertiesSmokeTests implements
|
||||||
ConfigurationProperties props, StartupStatus ss) {
|
ConfigurationProperties props, StartupStatus ss) {
|
||||||
String url = props.getProperty(PROPERTY_DB_URL);
|
String url = props.getProperty(PROPERTY_DB_URL);
|
||||||
if (url == null || url.isEmpty()) {
|
if (url == null || url.isEmpty()) {
|
||||||
ss.fatal(this, "deploy.properties does not contain a value for '"
|
ss.fatal(this, "runtime.properties does not contain a value for '"
|
||||||
+ PROPERTY_DB_URL + "'");
|
+ PROPERTY_DB_URL + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String username = props.getProperty(PROPERTY_DB_USERNAME);
|
String username = props.getProperty(PROPERTY_DB_USERNAME);
|
||||||
if (username == null || username.isEmpty()) {
|
if (username == null || username.isEmpty()) {
|
||||||
ss.fatal(this, "deploy.properties does not contain a value for '"
|
ss.fatal(this, "runtime.properties does not contain a value for '"
|
||||||
+ PROPERTY_DB_USERNAME + "'");
|
+ PROPERTY_DB_USERNAME + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String password = props.getProperty(PROPERTY_DB_PASSWORD);
|
String password = props.getProperty(PROPERTY_DB_PASSWORD);
|
||||||
if (password == null || password.isEmpty()) {
|
if (password == null || password.isEmpty()) {
|
||||||
ss.fatal(this, "deploy.properties does not contain a value for '"
|
ss.fatal(this, "runtime.properties does not contain a value for '"
|
||||||
+ PROPERTY_DB_PASSWORD + "'");
|
+ PROPERTY_DB_PASSWORD + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ public class ConfigurationPropertiesSmokeTests implements
|
||||||
ConfigurationProperties props, StartupStatus ss) {
|
ConfigurationProperties props, StartupStatus ss) {
|
||||||
String ns = props.getProperty(PROPERTY_DEFAULT_NAMESPACE);
|
String ns = props.getProperty(PROPERTY_DEFAULT_NAMESPACE);
|
||||||
if (ns == null || ns.isEmpty()) {
|
if (ns == null || ns.isEmpty()) {
|
||||||
ss.fatal(this, "deploy.properties does not contain a value for '"
|
ss.fatal(this, "runtime.properties does not contain a value for '"
|
||||||
+ PROPERTY_DEFAULT_NAMESPACE + "'");
|
+ PROPERTY_DEFAULT_NAMESPACE + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,6 @@ import edu.cornell.mannlib.vitro.webapp.web.ContentType;
|
||||||
public class OntologyController extends VitroHttpServlet{
|
public class OntologyController extends VitroHttpServlet{
|
||||||
private static final Log log = LogFactory.getLog(OntologyController.class.getName());
|
private static final Log log = LogFactory.getLog(OntologyController.class.getName());
|
||||||
|
|
||||||
private String default_jsp = Controllers.BASIC_JSP;
|
|
||||||
private ApplicationBean appBean;
|
|
||||||
|
|
||||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws ServletException,IOException{
|
throws ServletException,IOException{
|
||||||
doGet(request, response);
|
doGet(request, response);
|
||||||
|
@ -242,7 +239,7 @@ public class OntologyController extends VitroHttpServlet{
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
VitroRequest vreq = new VitroRequest(req);
|
VitroRequest vreq = new VitroRequest(req);
|
||||||
|
|
||||||
ApplicationBean appBean = ApplicationBean.getAppBean(getServletContext());
|
ApplicationBean appBean = vreq.getAppBean();
|
||||||
|
|
||||||
//set title before we do the highlighting so we don't get markup in it.
|
//set title before we do the highlighting so we don't get markup in it.
|
||||||
req.setAttribute("title","not found");
|
req.setAttribute("title","not found");
|
||||||
|
|
|
@ -283,12 +283,8 @@ public class VitroRequest extends HttpServletRequestWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationBean getAppBean(){
|
public ApplicationBean getAppBean(){
|
||||||
//return (ApplicationBean) getAttribute("appBean");
|
|
||||||
return getWebappDaoFactory().getApplicationDao().getApplicationBean();
|
return getWebappDaoFactory().getApplicationDao().getApplicationBean();
|
||||||
}
|
}
|
||||||
public void setAppBean(ApplicationBean ab){
|
|
||||||
setAttribute("appBean",ab);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,7 +7,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
@ -31,7 +30,7 @@ public class StartupStatusController extends FreemarkerHttpServlet {
|
||||||
body.put("title", "Startup Status");
|
body.put("title", "Startup Status");
|
||||||
body.put("status", StartupStatus.getBean(getServletContext()));
|
body.put("status", StartupStatus.getBean(getServletContext()));
|
||||||
body.put("contextPath", getContextPath());
|
body.put("contextPath", getContextPath());
|
||||||
body.put("applicationName", getApplicationName());
|
body.put("applicationName", getApplicationName(vreq));
|
||||||
|
|
||||||
return new TemplateResponseValues("startupStatus-display.ftl", body);
|
return new TemplateResponseValues("startupStatus-display.ftl", body);
|
||||||
}
|
}
|
||||||
|
@ -45,11 +44,10 @@ public class StartupStatusController extends FreemarkerHttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getApplicationName() {
|
private Object getApplicationName(VitroRequest vreq) {
|
||||||
String name = "";
|
String name = "";
|
||||||
try {
|
try {
|
||||||
ApplicationBean app = ApplicationBean.getAppBean(getServletContext());
|
name = vreq.getAppBean().getApplicationName();
|
||||||
name = app.getApplicationName();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// deal with problems below
|
// deal with problems below
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class ExternalAuthHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (externalAuthServerUrl == null) {
|
if (externalAuthServerUrl == null) {
|
||||||
log.debug("deploy.properties doesn't contain a value for '"
|
log.debug("runtime.properties doesn't contain a value for '"
|
||||||
+ PROPERTY_EXTERNAL_AUTH_SERVER_URL
|
+ PROPERTY_EXTERNAL_AUTH_SERVER_URL
|
||||||
+ "' -- sending directly to '" + returnUrl + "'");
|
+ "' -- sending directly to '" + returnUrl + "'");
|
||||||
return returnUrl;
|
return returnUrl;
|
||||||
|
@ -142,7 +142,7 @@ public class ExternalAuthHelper {
|
||||||
|
|
||||||
if (externalAuthHeaderName == null) {
|
if (externalAuthHeaderName == null) {
|
||||||
log.error("User asked for external authentication, "
|
log.error("User asked for external authentication, "
|
||||||
+ "but deploy.properties doesn't contain a value for '"
|
+ "but runtime.properties doesn't contain a value for '"
|
||||||
+ PROPERTY_EXTERNAL_AUTH_ID_HEADER + "'");
|
+ PROPERTY_EXTERNAL_AUTH_ID_HEADER + "'");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
|
||||||
* the header will contain the name of the user who just logged in.
|
* the header will contain the name of the user who just logged in.
|
||||||
*
|
*
|
||||||
* Deal with these possibilities:
|
* Deal with these possibilities:
|
||||||
* - The header name was not configured in deploy.properties. Complain.
|
* - The header name was not configured in runtime.properties. Complain.
|
||||||
* - No username: the login failed. Complain
|
* - No username: the login failed. Complain
|
||||||
* - User corresponds to a User acocunt. Record the login.
|
* - User corresponds to a User acocunt. Record the login.
|
||||||
* - User corresponds to an Individual (self-editor).
|
* - User corresponds to an Individual (self-editor).
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
||||||
private final static String TEMPLATE_ERROR = "contactForm-error.ftl";
|
private final static String TEMPLATE_ERROR = "contactForm-error.ftl";
|
||||||
private final static String TEMPLATE_FORM = "contactForm-form.ftl";
|
private final static String TEMPLATE_FORM = "contactForm-form.ftl";
|
||||||
|
|
||||||
private static final String PROPERTY_VITRO_HOME_DIR = "vitro.home.directory";
|
private static final String PROPERTY_VITRO_HOME_DIR = "vitro.home";
|
||||||
private static final String EMAIL_JOURNAL_FILE_DIR = "emailJournal";
|
private static final String EMAIL_JOURNAL_FILE_DIR = "emailJournal";
|
||||||
private static final String EMAIL_JOURNAL_FILE_NAME = "contactFormEmails.html";
|
private static final String EMAIL_JOURNAL_FILE_NAME = "contactFormEmails.html";
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import freemarker.cache.TemplateLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a TemplateLoader, so each time a template is read, delimiters will be
|
||||||
|
* inserted at the beginning and end. This makes it easier for a developer can
|
||||||
|
* see what lines of HTML come from which templates.
|
||||||
|
*
|
||||||
|
* TemplateLoader returns a token object when finding a template, and then
|
||||||
|
* recognizes that object when it is used as an argument to getLastModified() or
|
||||||
|
* getReader(). In order to keep track of the template name, we wrap the token
|
||||||
|
* object and the name in a token of our own.
|
||||||
|
*
|
||||||
|
* Taking the easy way out and reading in the entire template into a string.
|
||||||
|
* This limits the template size to less than 2^31 characters (~2 GBytes). That
|
||||||
|
* seems adequate.
|
||||||
|
*/
|
||||||
|
public class DelimitingTemplateLoader implements TemplateLoader {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(DelimitingTemplateLoader.class);
|
||||||
|
|
||||||
|
private final TemplateLoader innerLoader;
|
||||||
|
|
||||||
|
public DelimitingTemplateLoader(TemplateLoader innerLoader) {
|
||||||
|
this.innerLoader = innerLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object findTemplateSource(String name) throws IOException {
|
||||||
|
Object innerTS = innerLoader.findTemplateSource(name);
|
||||||
|
if (innerTS == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return new DelimitingTemplateSource(name, innerTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLastModified(Object templateSource) {
|
||||||
|
DelimitingTemplateSource dts = (DelimitingTemplateSource) templateSource;
|
||||||
|
return innerLoader.getLastModified(dts.ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reader getReader(Object templateSource, String encoding)
|
||||||
|
throws IOException {
|
||||||
|
DelimitingTemplateSource dts = (DelimitingTemplateSource) templateSource;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("<!-- FM_BEGIN ").append(dts.name).append(" -->");
|
||||||
|
sb.append(readTemplateSource(encoding, dts.ts));
|
||||||
|
sb.append("<!-- FM_END ").append(dts.name).append(" -->\n");
|
||||||
|
return new StringReader(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder readTemplateSource(String encoding, Object ts)
|
||||||
|
throws IOException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
Reader reader = innerLoader.getReader(ts, encoding);
|
||||||
|
char[] buffer = new char[8192];
|
||||||
|
int howmany;
|
||||||
|
while (-1 != (howmany = reader.read(buffer))) {
|
||||||
|
sb.append(buffer, 0, howmany);
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeTemplateSource(Object templateSource) throws IOException {
|
||||||
|
DelimitingTemplateSource dts = (DelimitingTemplateSource) templateSource;
|
||||||
|
innerLoader.closeTemplateSource(dts.ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Helper classes
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data object, wrapping the template name and the templateSource object
|
||||||
|
* from the inner TemplateLoader.
|
||||||
|
*/
|
||||||
|
private static class DelimitingTemplateSource {
|
||||||
|
public final String name;
|
||||||
|
public final Object ts;
|
||||||
|
|
||||||
|
public DelimitingTemplateSource(String name, Object ts) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name may not be null.");
|
||||||
|
}
|
||||||
|
if (ts == null) {
|
||||||
|
throw new NullPointerException("ts may not be null.");
|
||||||
|
}
|
||||||
|
this.name = name;
|
||||||
|
this.ts = ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return name.hashCode() ^ ts.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!o.getClass().equals(this.getClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DelimitingTemplateSource that = (DelimitingTemplateSource) o;
|
||||||
|
return this.name.equals(that.name) && this.ts.equals(that.ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,14 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -17,8 +21,12 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||||
import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean;
|
import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
|
||||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants;
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.i18n.freemarker.I18nMethodModel;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.web.directives.IndividualShortViewDirective;
|
import edu.cornell.mannlib.vitro.webapp.web.directives.IndividualShortViewDirective;
|
||||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod;
|
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod;
|
||||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualPlaceholderImageUrlMethod;
|
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualPlaceholderImageUrlMethod;
|
||||||
|
@ -27,29 +35,37 @@ import freemarker.cache.ClassTemplateLoader;
|
||||||
import freemarker.cache.FileTemplateLoader;
|
import freemarker.cache.FileTemplateLoader;
|
||||||
import freemarker.cache.MultiTemplateLoader;
|
import freemarker.cache.MultiTemplateLoader;
|
||||||
import freemarker.cache.TemplateLoader;
|
import freemarker.cache.TemplateLoader;
|
||||||
|
import freemarker.core.Environment;
|
||||||
import freemarker.ext.beans.BeansWrapper;
|
import freemarker.ext.beans.BeansWrapper;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
import freemarker.template.DefaultObjectWrapper;
|
import freemarker.template.DefaultObjectWrapper;
|
||||||
|
import freemarker.template.ObjectWrapper;
|
||||||
|
import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
import freemarker.template.TemplateModelException;
|
import freemarker.template.TemplateModelException;
|
||||||
|
import freemarker.template.utility.DeepUnwrap;
|
||||||
|
|
||||||
public class FreemarkerConfiguration extends Configuration {
|
public class FreemarkerConfiguration extends Configuration {
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(FreemarkerConfiguration.class);
|
private static final Log log = LogFactory.getLog(FreemarkerConfiguration.class);
|
||||||
|
|
||||||
|
private static final String PROPERTY_DEVELOPER_DEFEAT_CACHE = "developer.defeatFreemarkerCache";
|
||||||
|
private static final String PROPERTY_DEVELOPER_INSERT_DELIMITERS = "developer.insertFreemarkerDelimiters";
|
||||||
|
|
||||||
private final String themeDir;
|
private final String themeDir;
|
||||||
private final ServletContext context;
|
private final ServletContext context;
|
||||||
private final ApplicationBean appBean;
|
private final ApplicationBean appBean;
|
||||||
|
private final ConfigurationProperties props;
|
||||||
|
|
||||||
FreemarkerConfiguration(String themeDir, ApplicationBean appBean, ServletContext context) {
|
FreemarkerConfiguration(String themeDir, ApplicationBean appBean, ServletContext context) {
|
||||||
|
|
||||||
this.themeDir = themeDir;
|
this.themeDir = themeDir;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.appBean = appBean;
|
this.appBean = appBean;
|
||||||
|
this.props = ConfigurationProperties.getBean(context);
|
||||||
|
|
||||||
String buildEnv = ConfigurationProperties.getBean(context).getProperty("Environment.build");
|
String flag = props.getProperty(PROPERTY_DEVELOPER_DEFEAT_CACHE, "false");
|
||||||
log.debug("Current build environment: " + buildEnv);
|
if (Boolean.valueOf(flag.trim())) {
|
||||||
if ("development".equals(buildEnv)) { // Set Environment.build = development in deploy.properties
|
|
||||||
log.debug("Disabling Freemarker template caching in development build.");
|
log.debug("Disabling Freemarker template caching in development build.");
|
||||||
setTemplateUpdateDelay(0); // no template caching in development
|
setTemplateUpdateDelay(0); // no template caching in development
|
||||||
} else {
|
} else {
|
||||||
|
@ -164,6 +180,7 @@ public class FreemarkerConfiguration extends Configuration {
|
||||||
map.put("profileUrl", new IndividualProfileUrlMethod());
|
map.put("profileUrl", new IndividualProfileUrlMethod());
|
||||||
map.put("localName", new IndividualLocalNameMethod());
|
map.put("localName", new IndividualLocalNameMethod());
|
||||||
map.put("placeholderImageUrl", new IndividualPlaceholderImageUrlMethod());
|
map.put("placeholderImageUrl", new IndividualPlaceholderImageUrlMethod());
|
||||||
|
map.put("i18n", new I18nMethodModel());
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +213,110 @@ public class FreemarkerConfiguration extends Configuration {
|
||||||
log.error("Error creating template loaders");
|
log.error("Error creating template loaders");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the ability to add delimiters to the templates, based on
|
||||||
|
// settings.
|
||||||
|
if (Boolean.valueOf(props.getProperty(PROPERTY_DEVELOPER_INSERT_DELIMITERS))) {
|
||||||
|
return new DelimitingTemplateLoader(mtl);
|
||||||
|
} else {
|
||||||
return mtl;
|
return mtl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override getTemplate(), so we can apply DataGetters to all included
|
||||||
|
* templates.
|
||||||
|
*
|
||||||
|
* This won't work for top-level Templates, since the Environment hasn't
|
||||||
|
* been created yet. When TemplateProcessingHelper creates the Environment,
|
||||||
|
* it must call retrieveAndRunDataGetters() for the top-level Template.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Template getTemplate(String name, Locale locale, String encoding,
|
||||||
|
boolean parse) throws IOException {
|
||||||
|
Template template = super.getTemplate(name, locale, encoding, parse);
|
||||||
|
|
||||||
|
if (template == null) {
|
||||||
|
log.debug("Template '" + name + "' not found for locale '" + locale + "'.");
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
Environment env = getEnvironment();
|
||||||
|
if (env == null) {
|
||||||
|
log.debug("Not fetching data getters for template '" + template.getName() + "'. No environment.");
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
retrieveAndRunDataGetters(env, template.getName());
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the DataGetters for this template, and apply them to the Freemarker
|
||||||
|
* environment.
|
||||||
|
*/
|
||||||
|
public static void retrieveAndRunDataGetters(Environment env, String templateName) {
|
||||||
|
HttpServletRequest req = (HttpServletRequest) env.getCustomAttribute("request");
|
||||||
|
VitroRequest vreq = new VitroRequest(req);
|
||||||
|
|
||||||
|
if (dataGettersAlreadyApplied(env, templateName)) {
|
||||||
|
log.debug("DataGetters for '" + templateName+"' have already been applied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<DataGetter> dgList = DataGetterUtils.getDataGettersForTemplate(
|
||||||
|
vreq, vreq.getDisplayModel(), templateName);
|
||||||
|
log.debug("Retrieved " + dgList.size() + " data getters for template '" + templateName + "'");
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> dataMap = (Map<String, Object>) DeepUnwrap.permissiveUnwrap(env.getDataModel());
|
||||||
|
for (DataGetter dg : dgList) {
|
||||||
|
applyDataGetter(dg, env, dataMap);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Have the DataGetters for this template already been applied to this environment?
|
||||||
|
* If not, record that they are being applied now.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static boolean dataGettersAlreadyApplied(Environment env, String templateName) {
|
||||||
|
Set<String> names;
|
||||||
|
Object o = env.getCustomAttribute("dataGettersApplied");
|
||||||
|
if (o instanceof Set) {
|
||||||
|
names = (Set<String>) o;
|
||||||
|
} else {
|
||||||
|
names = new HashSet<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean added = names.add(templateName);
|
||||||
|
if (added) {
|
||||||
|
env.setCustomAttribute("dataGettersApplied", names);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data from a DataGetter, and store it in global variables in the
|
||||||
|
* Freemarker environment.
|
||||||
|
*/
|
||||||
|
private static void applyDataGetter(DataGetter dg, Environment env,
|
||||||
|
Map<String, Object> dataMap) throws TemplateModelException {
|
||||||
|
Map<String, Object> moreData = dg.getData(dataMap);
|
||||||
|
ObjectWrapper wrapper = env.getObjectWrapper();
|
||||||
|
if (moreData != null) {
|
||||||
|
for (String key : moreData.keySet()) {
|
||||||
|
Object value = moreData.get(key);
|
||||||
|
env.setGlobalVariable(key, wrapper.wrap(value));
|
||||||
|
log.debug("Stored in environment: '" + key + "' = '" + value + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,12 +51,20 @@ public class TemplateProcessingHelper {
|
||||||
env.setCustomAttribute("request", request);
|
env.setCustomAttribute("request", request);
|
||||||
env.setCustomAttribute("context", context);
|
env.setCustomAttribute("context", context);
|
||||||
|
|
||||||
|
// Set the Locale from the request into the environment, so date builtins will be
|
||||||
|
// Locale-dependent
|
||||||
|
env.setLocale(request.getLocale());
|
||||||
|
|
||||||
// Define a setup template to be included by every page template
|
// Define a setup template to be included by every page template
|
||||||
String templateType = (String) map.get("templateType");
|
String templateType = (String) map.get("templateType");
|
||||||
if (FreemarkerHttpServlet.PAGE_TEMPLATE_TYPE.equals(templateType)) {
|
if (FreemarkerHttpServlet.PAGE_TEMPLATE_TYPE.equals(templateType)) {
|
||||||
env.include(getTemplate("pageSetup.ftl"));
|
env.include(getTemplate("pageSetup.ftl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply any data-getters that are associated with this template.
|
||||||
|
FreemarkerConfiguration.retrieveAndRunDataGetters(env, template.getName());
|
||||||
|
|
||||||
|
// Now process it.
|
||||||
env.process();
|
env.process();
|
||||||
} catch (TemplateException e) {
|
} catch (TemplateException e) {
|
||||||
throw new TemplateProcessingException("TemplateException creating processing environment", e);
|
throw new TemplateProcessingException("TemplateException creating processing environment", e);
|
||||||
|
|
|
@ -5,7 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.HashMap;
|
//import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ public class UrlBuilder {
|
||||||
return getUrl(Route.LOGOUT);
|
return getUrl(Route.LOGOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ParamMap extends HashMap<String, String> {
|
public static class ParamMap extends LinkedHashMap<String, String> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public ParamMap() { }
|
public ParamMap() { }
|
||||||
|
@ -276,7 +277,7 @@ public class UrlBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profileUrl != null) {
|
if (profileUrl != null) {
|
||||||
HashMap<String, String> specialParams = getModelParams(vreq);
|
LinkedHashMap<String, String> specialParams = getModelParams(vreq);
|
||||||
if(specialParams.size() != 0) {
|
if(specialParams.size() != 0) {
|
||||||
profileUrl = addParams(profileUrl, new ParamMap(specialParams));
|
profileUrl = addParams(profileUrl, new ParamMap(specialParams));
|
||||||
}
|
}
|
||||||
|
@ -325,9 +326,9 @@ public class UrlBuilder {
|
||||||
|
|
||||||
//To be used in different property templates so placing method for reuse here
|
//To be used in different property templates so placing method for reuse here
|
||||||
//Check if special params included, specifically for menu management and other models
|
//Check if special params included, specifically for menu management and other models
|
||||||
public static HashMap<String,String> getModelParams(VitroRequest vreq) {
|
public static LinkedHashMap<String,String> getModelParams(VitroRequest vreq) {
|
||||||
|
|
||||||
HashMap<String,String> specialParams = new HashMap<String, String>();
|
LinkedHashMap<String,String> specialParams = new LinkedHashMap<String, String>();
|
||||||
if(vreq != null) {
|
if(vreq != null) {
|
||||||
//this parameter is sufficient to switch to menu model
|
//this parameter is sufficient to switch to menu model
|
||||||
String useMenuModelParam = vreq.getParameter(DisplayVocabulary.SWITCH_TO_DISPLAY_MODEL);
|
String useMenuModelParam = vreq.getParameter(DisplayVocabulary.SWITCH_TO_DISPLAY_MODEL);
|
||||||
|
|
|
@ -201,7 +201,7 @@ public class JSONReconcileServlet extends VitroHttpServlet {
|
||||||
viewJson.put("url", urlBuf.toString() + "/individual?uri={{id}}");
|
viewJson.put("url", urlBuf.toString() + "/individual?uri={{id}}");
|
||||||
json.put("view", viewJson);
|
json.put("view", viewJson);
|
||||||
|
|
||||||
// parse defaultTypeList from deploy.properties
|
// parse defaultTypeList from runtime.properties
|
||||||
if (defaultTypeList != null) {
|
if (defaultTypeList != null) {
|
||||||
String[] splitList = defaultTypeList.split(";");
|
String[] splitList = defaultTypeList.split(";");
|
||||||
String[][] idNameArray = new String[splitList.length][splitList.length];
|
String[][] idNameArray = new String[splitList.length][splitList.length];
|
||||||
|
|
|
@ -15,12 +15,6 @@ public interface IndividualRequestAnalysisContext {
|
||||||
*/
|
*/
|
||||||
String getDefaultNamespace();
|
String getDefaultNamespace();
|
||||||
|
|
||||||
/**
|
|
||||||
* Is there a namespace for this prefix? If not, return an empty string, but
|
|
||||||
* never null.
|
|
||||||
*/
|
|
||||||
String getNamespaceForPrefix(String prefix);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the IndividualDao to get this individual.
|
* Use the IndividualDao to get this individual.
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,8 +15,6 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
|
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.NamespaceMapper;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.NamespaceMapperFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement all of the fiddly-bits that we need for analyzing the request for
|
* Implement all of the fiddly-bits that we need for analyzing the request for
|
||||||
|
@ -45,25 +43,6 @@ public class IndividualRequestAnalysisContextImpl implements
|
||||||
return wadf.getDefaultNamespace();
|
return wadf.getDefaultNamespace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNamespaceForPrefix(String prefix) {
|
|
||||||
if (prefix == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
NamespaceMapper namespaceMapper = NamespaceMapperFactory
|
|
||||||
.getNamespaceMapper(ctx);
|
|
||||||
if (namespaceMapper == null) {
|
|
||||||
log.warn("No NamespaceMapper in ServletContext. Request URL was '"
|
|
||||||
+ vreq.getRequestURL() + "'");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
String ns = namespaceMapper.getNamespaceForPrefix(prefix);
|
|
||||||
|
|
||||||
return (ns == null) ? "" : ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Individual getIndividualByURI(String individualUri) {
|
public Individual getIndividualByURI(String individualUri) {
|
||||||
if (individualUri == null) {
|
if (individualUri == null) {
|
||||||
|
|
|
@ -30,7 +30,6 @@ public class IndividualRequestAnalyzer {
|
||||||
private static Pattern RDF_REQUEST = Pattern.compile("^/individual/([^/]+)/\\1\\.(rdf|n3|ttl)$");
|
private static Pattern RDF_REQUEST = Pattern.compile("^/individual/([^/]+)/\\1\\.(rdf|n3|ttl)$");
|
||||||
private static Pattern HTML_REQUEST = Pattern.compile("^/display/([^/]+)$");
|
private static Pattern HTML_REQUEST = Pattern.compile("^/display/([^/]+)$");
|
||||||
private static Pattern LINKED_DATA_URL = Pattern.compile("^/individual/([^/]+)$");
|
private static Pattern LINKED_DATA_URL = Pattern.compile("^/individual/([^/]+)$");
|
||||||
private static Pattern NS_PREFIX_URL = Pattern.compile("^/individual/([^/]*)/([^/]+)$");
|
|
||||||
|
|
||||||
private final VitroRequest vreq;
|
private final VitroRequest vreq;
|
||||||
private final IndividualRequestAnalysisContext analysisContext;
|
private final IndividualRequestAnalysisContext analysisContext;
|
||||||
|
@ -164,7 +163,6 @@ public class IndividualRequestAnalyzer {
|
||||||
* /individual/localname/localname.rdf
|
* /individual/localname/localname.rdf
|
||||||
* /individual/localname/localname.n3
|
* /individual/localname/localname.n3
|
||||||
* /individual/localname/localname.ttl
|
* /individual/localname/localname.ttl
|
||||||
* /individual/nsprefix/localname
|
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @return null on failure.
|
* @return null on failure.
|
||||||
|
@ -202,14 +200,6 @@ public class IndividualRequestAnalyzer {
|
||||||
return getIndividualByLocalname(rdfMatch.group(1));
|
return getIndividualByLocalname(rdfMatch.group(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the URL look like a namespace prefix followed by a local
|
|
||||||
// name?
|
|
||||||
Matcher prefix_match = NS_PREFIX_URL.matcher(url);
|
|
||||||
if (prefix_match.matches() && prefix_match.groupCount() == 2) {
|
|
||||||
return getIndividualByPrefixAndLocalname(prefix_match.group(1),
|
|
||||||
prefix_match.group(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Couldn't match it to anything.
|
// Couldn't match it to anything.
|
||||||
return null;
|
return null;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -299,12 +289,6 @@ public class IndividualRequestAnalyzer {
|
||||||
return getIndividualByUri(uri);
|
return getIndividualByUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Individual getIndividualByPrefixAndLocalname(String prefix,
|
|
||||||
String localName) {
|
|
||||||
String ns = analysisContext.getNamespaceForPrefix(prefix);
|
|
||||||
return getIndividualByUri(ns + localName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Individual getIndividualByNetId(String netId) {
|
private Individual getIndividualByNetId(String netId) {
|
||||||
return analysisContext.getIndividualByNetId(netId);
|
return analysisContext.getIndividualByNetId(netId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ class IndividualResponseBuilder {
|
||||||
body.put("relatedSubject", getRelatedSubject());
|
body.put("relatedSubject", getRelatedSubject());
|
||||||
body.put("namespaces", namespaces);
|
body.put("namespaces", namespaces);
|
||||||
body.put("temporalVisualizationEnabled", getTemporalVisualizationFlag());
|
body.put("temporalVisualizationEnabled", getTemporalVisualizationFlag());
|
||||||
|
body.put("profilePageTypesEnabled", getprofilePageTypesFlag());
|
||||||
body.put("verbosePropertySwitch", getVerbosePropertyValues());
|
body.put("verbosePropertySwitch", getVerbosePropertyValues());
|
||||||
|
|
||||||
//Execute data getters that might apply to this individual, e.g. because of the class of the individual
|
//Execute data getters that might apply to this individual, e.g. because of the class of the individual
|
||||||
|
@ -91,6 +92,13 @@ class IndividualResponseBuilder {
|
||||||
log.error("Data retrieval for individual lead to error", ex);
|
log.error("Data retrieval for individual lead to error", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for quick profile view - users can toggle between the quick and the full views,
|
||||||
|
// so the "destination" let's us know which view they are targeting. On normal
|
||||||
|
// page request, this string is empty and the default template is loaded.
|
||||||
|
String targetedView = "";
|
||||||
|
targetedView = vreq.getParameter("destination");
|
||||||
|
body.put("targetedView", targetedView);
|
||||||
|
|
||||||
//Individual template model
|
//Individual template model
|
||||||
IndividualTemplateModel itm = getIndividualTemplateModel(individual);
|
IndividualTemplateModel itm = getIndividualTemplateModel(individual);
|
||||||
/* We need to expose non-getters in displaying the individual's property list,
|
/* We need to expose non-getters in displaying the individual's property list,
|
||||||
|
@ -100,6 +108,7 @@ class IndividualResponseBuilder {
|
||||||
*/
|
*/
|
||||||
// body.put("individual", wrap(itm, BeansWrapper.EXPOSE_SAFE));
|
// body.put("individual", wrap(itm, BeansWrapper.EXPOSE_SAFE));
|
||||||
body.put("labelCount", getLabelCount(itm.getUri(), vreq));
|
body.put("labelCount", getLabelCount(itm.getUri(), vreq));
|
||||||
|
body.put("profileType", getProfileType(itm.getUri(), vreq));
|
||||||
body.put("individual", wrap(itm, new ReadOnlyBeansWrapper()));
|
body.put("individual", wrap(itm, new ReadOnlyBeansWrapper()));
|
||||||
|
|
||||||
body.put("headContent", getRdfLinkTag(itm));
|
body.put("headContent", getRdfLinkTag(itm));
|
||||||
|
@ -169,6 +178,12 @@ class IndividualResponseBuilder {
|
||||||
return "enabled".equals(property);
|
return "enabled".equals(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean getprofilePageTypesFlag() {
|
||||||
|
String property = ConfigurationProperties.getBean(vreq).getProperty(
|
||||||
|
"MultiViews.profilePageTypes");
|
||||||
|
return "enabled".equals(property);
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, Object> getVerbosePropertyValues() {
|
private Map<String, Object> getVerbosePropertyValues() {
|
||||||
Map<String, Object> map = null;
|
Map<String, Object> map = null;
|
||||||
|
|
||||||
|
@ -275,4 +290,29 @@ class IndividualResponseBuilder {
|
||||||
}
|
}
|
||||||
return theCount;
|
return theCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String PROFILE_TYPE_QUERY = ""
|
||||||
|
+ "PREFIX display: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#> \n"
|
||||||
|
+ "SELECT ?profile WHERE { \n"
|
||||||
|
+ " ?subject display:hasDefaultProfilePageType ?profile \n"
|
||||||
|
+ "}" ;
|
||||||
|
|
||||||
|
private static String getProfileType(String subjectUri, VitroRequest vreq) {
|
||||||
|
String queryStr = QueryUtils.subUriForQueryVar(PROFILE_TYPE_QUERY, "subject", subjectUri);
|
||||||
|
log.debug("queryStr = " + queryStr);
|
||||||
|
String profileType = "none";
|
||||||
|
try {
|
||||||
|
ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
|
||||||
|
if (results.hasNext()) {
|
||||||
|
QuerySolution soln = results.nextSolution();
|
||||||
|
String profileStr = soln.get("profile").toString();
|
||||||
|
if ( profileStr.length() > 0 ) {
|
||||||
|
profileType = profileStr.substring(profileStr.indexOf("#")+1,profileStr.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e, e);
|
||||||
|
}
|
||||||
|
return profileType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.json;
|
package edu.cornell.mannlib.vitro.webapp.controller.json;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -24,7 +26,7 @@ import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.Individual
|
||||||
* Does a Solr search for individuals, and uses the short view to render each of
|
* Does a Solr search for individuals, and uses the short view to render each of
|
||||||
* the results.
|
* the results.
|
||||||
*/
|
*/
|
||||||
public class GetRenderedSolrIndividualsByVClass extends JsonObjectProducer {
|
public class GetRenderedSolrIndividualsByVClass extends GetSolrIndividualsByVClasses {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
.getLog(GetRenderedSolrIndividualsByVClass.class);
|
.getLog(GetRenderedSolrIndividualsByVClass.class);
|
||||||
|
|
||||||
|
@ -33,22 +35,35 @@ public class GetRenderedSolrIndividualsByVClass extends JsonObjectProducer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for individuals by VClass. The class URI and the paging
|
* Search for individuals by VClass or VClasses in the case of multiple parameters. The class URI(s) and the paging
|
||||||
* information are in the request parameters.
|
* information are in the request parameters.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected JSONObject process() throws Exception {
|
protected JSONObject process() throws Exception {
|
||||||
JSONObject rObj = null;
|
JSONObject rObj = null;
|
||||||
VClass vclass = getVclassParameter(vreq);
|
|
||||||
String vclassId = vclass.getURI();
|
|
||||||
|
|
||||||
|
//This gets the first vclass value and sets that as display type
|
||||||
|
List<String> vclassIds = super.getVclassIds(vreq);
|
||||||
|
String vclassId = null;
|
||||||
|
if(vclassIds.size() > 1) {
|
||||||
|
//This ensures the second class instead of the first
|
||||||
|
//This is a temporary fix in cases where institutional internal classes are being sent in
|
||||||
|
//and thus the second class is the actual class with display information associated
|
||||||
|
vclassId = vclassIds.get(1);
|
||||||
|
} else {
|
||||||
|
vclassId = vclassIds.get(0);
|
||||||
|
}
|
||||||
vreq.setAttribute("displayType", vclassId);
|
vreq.setAttribute("displayType", vclassId);
|
||||||
rObj = JsonServlet.getSolrIndividualsByVClass(vclassId, vreq, ctx);
|
|
||||||
addShortViewRenderings(rObj);
|
|
||||||
|
|
||||||
|
//This will get all the solr individuals by VClass (if one value) or the intersection
|
||||||
|
//i.e. individuals that have all the types for the different vclasses entered
|
||||||
|
rObj = super.process();
|
||||||
|
addShortViewRenderings(rObj);
|
||||||
return rObj;
|
return rObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Get
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look through the return object. For each individual, render the short
|
* Look through the return object. For each individual, render the short
|
||||||
* view and insert the resulting HTML into the object.
|
* view and insert the resulting HTML into the object.
|
||||||
|
|
|
@ -1,197 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.login;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.edit.Authenticate;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.State;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A temporary means of displaying the Login templates within the SiteAdmin
|
|
||||||
* form.
|
|
||||||
*
|
|
||||||
* This class contains stuff that I swiped from {@link Authenticate}. The base
|
|
||||||
* class, {@link LoginTemplateHelperBase}, contains stuff that I swiped from
|
|
||||||
* {@link FreemarkerHttpServlet}.
|
|
||||||
*/
|
|
||||||
public class LoginTemplateHelper extends LoginTemplateHelperBase {
|
|
||||||
private static final Log log = LogFactory.getLog(LoginTemplateHelper.class);
|
|
||||||
|
|
||||||
/** If they are logging in, show them this form. */
|
|
||||||
public static final String TEMPLATE_LOGIN = "login-form.ftl";
|
|
||||||
|
|
||||||
/** If they are changing their password on first login, show them this form. */
|
|
||||||
public static final String TEMPLATE_FORCE_PASSWORD_CHANGE = "login-forcedPasswordChange.ftl";
|
|
||||||
|
|
||||||
/** Show error message */
|
|
||||||
public static final String TEMPLATE_SERVER_ERROR = Template.ERROR_MESSAGE.toString();
|
|
||||||
|
|
||||||
public static final String BODY_LOGIN_NAME = "loginName";
|
|
||||||
public static final String BODY_FORM_ACTION = "formAction";
|
|
||||||
public static final String BODY_INFO_MESSAGE = "infoMessage";
|
|
||||||
public static final String BODY_ERROR_MESSAGE = "errorMessage";
|
|
||||||
public static final String BODY_CANCEL_URL = "cancelUrl";
|
|
||||||
|
|
||||||
public LoginTemplateHelper(HttpServletRequest req) {
|
|
||||||
super(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Version for JSP page */
|
|
||||||
public String showLoginPage(HttpServletRequest request) {
|
|
||||||
VitroRequest vreq = new VitroRequest(request);
|
|
||||||
try {
|
|
||||||
State state = getCurrentLoginState(vreq);
|
|
||||||
log.debug("State on exit: " + state);
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case LOGGED_IN:
|
|
||||||
return "";
|
|
||||||
case FORCED_PASSWORD_CHANGE:
|
|
||||||
return doTemplate(vreq, showPasswordChangeScreen(vreq));
|
|
||||||
default:
|
|
||||||
return doTemplate(vreq, showLoginScreen(vreq));
|
|
||||||
}
|
|
||||||
} catch (TemplateProcessingException e) {
|
|
||||||
log.error(e.getMessage(), e);
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e, e);
|
|
||||||
try {
|
|
||||||
return doTemplate(vreq, showError(e));
|
|
||||||
} catch (TemplateProcessingException e1) {
|
|
||||||
log.error(e1.getMessage(), e1);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Version for Freemarker page */
|
|
||||||
public TemplateResponseValues showLoginPanel(VitroRequest vreq) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
State state = getCurrentLoginState(vreq);
|
|
||||||
log.debug("State on exit: " + state);
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
// RY Why does this case exist? We don't call this method if a user is logged in.
|
|
||||||
case LOGGED_IN:
|
|
||||||
return null;
|
|
||||||
case FORCED_PASSWORD_CHANGE:
|
|
||||||
// return doTemplate(vreq, showPasswordChangeScreen(vreq), body, config);
|
|
||||||
return showPasswordChangeScreen(vreq);
|
|
||||||
default:
|
|
||||||
// return doTemplate(vreq, showLoginScreen(vreq), body, config);
|
|
||||||
return showLoginScreen(vreq);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e, e);
|
|
||||||
return showError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User is just starting the login process. Be sure that we have a
|
|
||||||
* {@link LoginProcessBean} with the correct status. Show them the login
|
|
||||||
* screen.
|
|
||||||
*/
|
|
||||||
private TemplateResponseValues showLoginScreen(VitroRequest vreq)
|
|
||||||
throws IOException {
|
|
||||||
LoginProcessBean bean = LoginProcessBean.getBean(vreq);
|
|
||||||
bean.setState(State.LOGGING_IN);
|
|
||||||
log.trace("Going to login screen: " + bean);
|
|
||||||
|
|
||||||
TemplateResponseValues trv = new TemplateResponseValues(TEMPLATE_LOGIN);
|
|
||||||
trv.put(BODY_FORM_ACTION, getAuthenticateUrl(vreq));
|
|
||||||
trv.put(BODY_LOGIN_NAME, bean.getUsername());
|
|
||||||
|
|
||||||
String infoMessage = bean.getInfoMessageAndClear();
|
|
||||||
if (!infoMessage.isEmpty()) {
|
|
||||||
trv.put(BODY_INFO_MESSAGE, infoMessage);
|
|
||||||
}
|
|
||||||
String errorMessage = bean.getErrorMessageAndClear();
|
|
||||||
if (!errorMessage.isEmpty()) {
|
|
||||||
trv.put(BODY_ERROR_MESSAGE, errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return trv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has given the correct password, but now they are required to
|
|
||||||
* change it (unless they cancel out).
|
|
||||||
*/
|
|
||||||
private TemplateResponseValues showPasswordChangeScreen(VitroRequest vreq) {
|
|
||||||
LoginProcessBean bean = LoginProcessBean.getBean(vreq);
|
|
||||||
bean.setState(State.FORCED_PASSWORD_CHANGE);
|
|
||||||
log.trace("Going to password change screen: " + bean);
|
|
||||||
|
|
||||||
TemplateResponseValues trv = new TemplateResponseValues(
|
|
||||||
TEMPLATE_FORCE_PASSWORD_CHANGE);
|
|
||||||
trv.put(BODY_FORM_ACTION, getAuthenticateUrl(vreq));
|
|
||||||
trv.put(BODY_CANCEL_URL, getCancelUrl(vreq));
|
|
||||||
|
|
||||||
String errorMessage = bean.getErrorMessageAndClear();
|
|
||||||
if (!errorMessage.isEmpty()) {
|
|
||||||
trv.put(BODY_ERROR_MESSAGE, errorMessage);
|
|
||||||
}
|
|
||||||
return trv;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TemplateResponseValues showError(Exception e) {
|
|
||||||
TemplateResponseValues trv = new TemplateResponseValues(
|
|
||||||
TEMPLATE_SERVER_ERROR);
|
|
||||||
trv.put(BODY_ERROR_MESSAGE, "Internal server error:<br /> " + e);
|
|
||||||
return trv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We processed a response, and want to show a template. Version for JSP
|
|
||||||
* page.
|
|
||||||
*/
|
|
||||||
private String doTemplate(VitroRequest vreq, TemplateResponseValues values) throws TemplateProcessingException {
|
|
||||||
// Set it up like FreeMarkerHttpServlet.doGet() would do.
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.putAll(getPageTemplateValues(vreq));
|
|
||||||
map.putAll(values.getMap());
|
|
||||||
|
|
||||||
return processTemplateToString(values.getTemplateName(), map, vreq);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Where are we in the process? Logged in? Not? Somewhere in between?
|
|
||||||
*/
|
|
||||||
private State getCurrentLoginState(HttpServletRequest request) {
|
|
||||||
if (LoginStatusBean.getBean(request).isLoggedIn()) {
|
|
||||||
return State.LOGGED_IN;
|
|
||||||
} else {
|
|
||||||
return LoginProcessBean.getBean(request).getState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** What's the URL for this servlet? */
|
|
||||||
private String getAuthenticateUrl(HttpServletRequest request) {
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
String urlParams = "?login=block";
|
|
||||||
return contextPath + "/authenticate" + urlParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** What's the URL for this servlet, with the cancel parameter added? */
|
|
||||||
private String getCancelUrl(HttpServletRequest request) {
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
String urlParams = "?login=block&cancel=true";
|
|
||||||
return contextPath + "/authenticate" + urlParams;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.login;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A temporary means of displaying the Login templates within the SiteAdmin
|
|
||||||
* form.
|
|
||||||
*
|
|
||||||
* The constructor insures that the ServletContext is set.
|
|
||||||
*/
|
|
||||||
public class LoginTemplateHelperBase extends FreemarkerHttpServlet {
|
|
||||||
private final ServletContext servletContext;
|
|
||||||
|
|
||||||
LoginTemplateHelperBase(HttpServletRequest req) {
|
|
||||||
this.servletContext = req.getSession().getServletContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServletContext getServletContext() {
|
|
||||||
return servletContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -438,13 +438,17 @@ public class IndividualDaoSDB extends IndividualDaoJena {
|
||||||
final List<String> list =
|
final List<String> list =
|
||||||
new LinkedList<String>();
|
new LinkedList<String>();
|
||||||
|
|
||||||
// get all labeled resources from any non-tbox and non-metadata graphs.
|
// get all labeled resources from any non-tbox and non-metadata graphs,
|
||||||
|
// as well as the unnamed graph (first pattern below)
|
||||||
String query = "SELECT DISTINCT ?ind WHERE { \n" +
|
String query = "SELECT DISTINCT ?ind WHERE { \n" +
|
||||||
|
" { ?ind <" + RDFS.label.getURI() + "> ?label } " +
|
||||||
|
" UNION { " +
|
||||||
" GRAPH ?g { ?ind <" + RDFS.label.getURI() +
|
" GRAPH ?g { ?ind <" + RDFS.label.getURI() +
|
||||||
"> ?label } \n" +
|
"> ?label } \n" +
|
||||||
" FILTER (?g != <" + JenaDataSourceSetupBase
|
" FILTER (?g != <" + JenaDataSourceSetupBase
|
||||||
.JENA_APPLICATION_METADATA_MODEL + "> " +
|
.JENA_APPLICATION_METADATA_MODEL + "> " +
|
||||||
" && !regex(str(?g),\"tbox\")) \n " +
|
" && !regex(str(?g),\"tbox\")) \n " +
|
||||||
|
" } " +
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
Query q = QueryFactory.create(query);
|
Query q = QueryFactory.create(query);
|
||||||
|
|
|
@ -848,13 +848,18 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
||||||
String getTypes =
|
String getTypes =
|
||||||
"CONSTRUCT{ <" + this.individualURI + "> <" + RDF.type +
|
"CONSTRUCT{ <" + this.individualURI + "> <" + RDF.type +
|
||||||
"> ?types }\n" +
|
"> ?types }\n" +
|
||||||
"WHERE{ GRAPH ?g"
|
"WHERE{ { GRAPH ?g"
|
||||||
+ " { <" + this.individualURI +"> <" +RDF.type+ "> ?types } \n"
|
+ " { <" + this.individualURI +"> <" +RDF.type+ "> ?types } \n"
|
||||||
+ WebappDaoFactorySDB.getFilterBlock(
|
+ WebappDaoFactorySDB.getFilterBlock(
|
||||||
graphVars, (direct
|
graphVars, (direct
|
||||||
? WebappDaoFactorySDB.SDBDatasetMode
|
? WebappDaoFactorySDB.SDBDatasetMode
|
||||||
.ASSERTIONS_ONLY
|
.ASSERTIONS_ONLY
|
||||||
: datasetMode))
|
: datasetMode))
|
||||||
|
+ "} \n"
|
||||||
|
// GRAPH-less pattern to support retrieving inferred types
|
||||||
|
// from the unnamed base graph, as in Sesame and OWLIM
|
||||||
|
+ ((datasetMode.equals(WebappDaoFactorySDB.SDBDatasetMode.ASSERTIONS_ONLY))
|
||||||
|
? "" : "UNION { <" + this.individualURI +"> <" +RDF.type+ "> ?types }" )
|
||||||
+ "} \n";
|
+ "} \n";
|
||||||
RDFService service = webappDaoFactory.getRDFService();
|
RDFService service = webappDaoFactory.getRDFService();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -139,10 +139,8 @@ public class VClassDaoSDB extends VClassDaoJena {
|
||||||
try {
|
try {
|
||||||
String queryText =
|
String queryText =
|
||||||
"SELECT COUNT( DISTINCT ?instance ) WHERE { \n" +
|
"SELECT COUNT( DISTINCT ?instance ) WHERE { \n" +
|
||||||
" GRAPH <urn:x-arq:UnionGraph> { \n" +
|
|
||||||
" ?class <"+VitroVocabulary.IN_CLASSGROUP+"> <"+vcg.getURI() +"> .\n" +
|
" ?class <"+VitroVocabulary.IN_CLASSGROUP+"> <"+vcg.getURI() +"> .\n" +
|
||||||
" ?instance a ?class . \n" +
|
" ?instance a ?class . \n" +
|
||||||
" } \n" +
|
|
||||||
"} \n" ;
|
"} \n" ;
|
||||||
|
|
||||||
Query countQuery = QueryFactory.create(queryText, Syntax.syntaxARQ);
|
Query countQuery = QueryFactory.create(queryText, Syntax.syntaxARQ);
|
||||||
|
|
|
@ -66,16 +66,29 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
|
||||||
|
|
||||||
Individual subject = wDaoFact.getIndividualDao().getIndividualByURI(subjectUri);
|
Individual subject = wDaoFact.getIndividualDao().getIndividualByURI(subjectUri);
|
||||||
ObjectProperty objProp = wDaoFact.getObjectPropertyDao().getObjectPropertyByURI(predicateUri);
|
ObjectProperty objProp = wDaoFact.getObjectPropertyDao().getObjectPropertyByURI(predicateUri);
|
||||||
List<VClass> vclasses = wDaoFact.getVClassDao().getVClassesForProperty(subject.getVClassURI(), predicateUri);
|
//get all vclasses applicable to the individual subject
|
||||||
|
List<VClass> subjectVClasses = subject.getVClasses();
|
||||||
|
//using hashset to prevent duplicates
|
||||||
|
HashSet<String> vclassesURIs = new HashSet<String>();
|
||||||
|
//Get the range vclasses applicable for the property and each vclass for the subject
|
||||||
|
for(VClass subjectVClass: subjectVClasses) {
|
||||||
|
List<VClass> vclasses = wDaoFact.getVClassDao().getVClassesForProperty(subjectVClass.getURI(), predicateUri);
|
||||||
|
//add range vclass to hash
|
||||||
|
if(vclasses != null) {
|
||||||
|
for(VClass v: vclasses) {
|
||||||
|
vclassesURIs.add(v.getURI());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (vclasses == null || vclasses.size() == 0) {
|
if (vclassesURIs.size() == 0) {
|
||||||
return optionsMap;
|
return optionsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Individual> individuals = new ArrayList<Individual>();
|
List<Individual> individuals = new ArrayList<Individual>();
|
||||||
HashSet<String> uriSet = new HashSet<String>();
|
HashSet<String> uriSet = new HashSet<String>();
|
||||||
for (VClass vclass : vclasses) {
|
for (String vclassURI: vclassesURIs) {
|
||||||
List<Individual> inds = wDaoFact.getIndividualDao().getIndividualsByVClassURI(vclass.getURI(), -1, -1);
|
List<Individual> inds = wDaoFact.getIndividualDao().getIndividualsByVClassURI(vclassURI, -1, -1);
|
||||||
for (Individual ind : inds) {
|
for (Individual ind : inds) {
|
||||||
if (!uriSet.contains(ind.getURI())) {
|
if (!uriSet.contains(ind.getURI())) {
|
||||||
uriSet.add(ind.getURI());
|
uriSet.add(ind.getURI());
|
||||||
|
@ -88,7 +101,7 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
|
||||||
|
|
||||||
individuals = removeIndividualsAlreadyInRange(
|
individuals = removeIndividualsAlreadyInRange(
|
||||||
individuals, stmts, predicateUri, objectUri);
|
individuals, stmts, predicateUri, objectUri);
|
||||||
// Collections.sort(individuals,new compareIndividualsByName());
|
// Collections.sort(individuals,new compareIndividualsByName());a
|
||||||
|
|
||||||
for (Individual ind : individuals) {
|
for (Individual ind : individuals) {
|
||||||
String uri = ind.getURI();
|
String uri = ind.getURI();
|
||||||
|
|
|
@ -39,7 +39,17 @@ public class DateTimeIntervalFormGenerator extends
|
||||||
public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq,
|
public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq,
|
||||||
HttpSession session) {
|
HttpSession session) {
|
||||||
EditConfigurationVTwo conf = new EditConfigurationVTwo();
|
EditConfigurationVTwo conf = new EditConfigurationVTwo();
|
||||||
|
this.setupEditConfiguration(conf, vreq, session);
|
||||||
|
//Prepare
|
||||||
|
prepare(vreq, conf);
|
||||||
|
return conf;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Enables refactoring by other generators, as this code can be used to partially setup an
|
||||||
|
//edit configuration object which can then be extended - prepare can then be called independently
|
||||||
|
//enabling sparql queries to be evaluated using the final edit configuration object
|
||||||
|
public void setupEditConfiguration(EditConfigurationVTwo conf, VitroRequest vreq, HttpSession session) {
|
||||||
initBasics(conf, vreq);
|
initBasics(conf, vreq);
|
||||||
initPropertyParameters(vreq, session, conf);
|
initPropertyParameters(vreq, session, conf);
|
||||||
initObjectPropForm(conf, vreq);
|
initObjectPropForm(conf, vreq);
|
||||||
|
@ -48,11 +58,11 @@ public class DateTimeIntervalFormGenerator extends
|
||||||
|
|
||||||
conf.setVarNameForSubject("subject");
|
conf.setVarNameForSubject("subject");
|
||||||
conf.setVarNameForPredicate("toDateTimeInterval");
|
conf.setVarNameForPredicate("toDateTimeInterval");
|
||||||
conf.setVarNameForObject("intervalNode");
|
conf.setVarNameForObject(getNodeVar());
|
||||||
|
|
||||||
conf.setN3Optional(Arrays.asList(n3ForStart, n3ForEnd));
|
conf.setN3Optional(n3ForStart, n3ForEnd);
|
||||||
|
|
||||||
conf.addNewResource("intervalNode", DEFAULT_NS_FOR_NEW_RESOURCE);
|
conf.addNewResource(getNodeVar(), DEFAULT_NS_FOR_NEW_RESOURCE);
|
||||||
conf.addNewResource("startNode", DEFAULT_NS_FOR_NEW_RESOURCE);
|
conf.addNewResource("startNode", DEFAULT_NS_FOR_NEW_RESOURCE);
|
||||||
conf.addNewResource("endNode", DEFAULT_NS_FOR_NEW_RESOURCE);
|
conf.addNewResource("endNode", DEFAULT_NS_FOR_NEW_RESOURCE);
|
||||||
|
|
||||||
|
@ -61,7 +71,7 @@ public class DateTimeIntervalFormGenerator extends
|
||||||
conf.addSparqlForExistingLiteral(
|
conf.addSparqlForExistingLiteral(
|
||||||
"endField-value", existingEndDateQuery);
|
"endField-value", existingEndDateQuery);
|
||||||
conf.addSparqlForExistingUris(
|
conf.addSparqlForExistingUris(
|
||||||
"intervalNode", existingIntervalNodeQuery);
|
getNodeVar(), existingIntervalNodeQuery);
|
||||||
conf.addSparqlForExistingUris("startNode", existingStartNodeQuery);
|
conf.addSparqlForExistingUris("startNode", existingStartNodeQuery);
|
||||||
conf.addSparqlForExistingUris("endNode", existingEndNodeQuery);
|
conf.addSparqlForExistingUris("endNode", existingEndNodeQuery);
|
||||||
conf.addSparqlForExistingUris(
|
conf.addSparqlForExistingUris(
|
||||||
|
@ -85,79 +95,87 @@ public class DateTimeIntervalFormGenerator extends
|
||||||
conf.addValidator(new DateTimeIntervalValidationVTwo("startField","endField"));
|
conf.addValidator(new DateTimeIntervalValidationVTwo("startField","endField"));
|
||||||
//Adding additional data, specifically edit mode
|
//Adding additional data, specifically edit mode
|
||||||
addFormSpecificData(conf, vreq);
|
addFormSpecificData(conf, vreq);
|
||||||
//Prepare
|
|
||||||
prepare(vreq, conf);
|
|
||||||
return conf;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final static String n3ForStart =
|
final String n3ForStart =
|
||||||
"?subject <" + toDateTimeInterval + "> ?intervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> " + getNodeN3Var() + " . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToStart + "> ?startNode . \n" +
|
getNodeN3Var() + " <" + intervalToStart + "> ?startNode . \n" +
|
||||||
"?startNode a <" + dateTimeValueType + "> . \n" +
|
"?startNode a <" + dateTimeValueType + "> . \n" +
|
||||||
"?startNode <" + dateTimeValue + "> ?startField-value . \n" +
|
"?startNode <" + dateTimeValue + "> ?startField-value . \n" +
|
||||||
"?startNode <" + dateTimePrecision + "> ?startField-precision . \n";
|
"?startNode <" + dateTimePrecision + "> ?startField-precision . \n";
|
||||||
|
|
||||||
final static String n3ForEnd =
|
final String n3ForEnd =
|
||||||
"?subject <" + toDateTimeInterval + "> ?intervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> " + getNodeN3Var() + " . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToEnd + "> ?endNode . \n" +
|
getNodeN3Var() + " <" + intervalToEnd + "> ?endNode . \n" +
|
||||||
"?endNode a <" + dateTimeValueType + "> . \n" +
|
"?endNode a <" + dateTimeValueType + "> . \n" +
|
||||||
"?endNode <" + dateTimeValue + "> ?endField-value . \n" +
|
"?endNode <" + dateTimeValue + "> ?endField-value . \n" +
|
||||||
"?endNode <" + dateTimePrecision + "> ?endField-precision .";
|
"?endNode <" + dateTimePrecision + "> ?endField-precision .";
|
||||||
|
|
||||||
final static String existingStartDateQuery =
|
final String existingStartDateQuery =
|
||||||
"SELECT ?existingDateStart WHERE { \n" +
|
"SELECT ?existingDateStart WHERE { \n" +
|
||||||
"?subject <" + toDateTimeInterval + "> ?existingIntervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> ?existingIntervalNode . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToStart + "> ?startNode . \n" +
|
getNodeN3Var() + " <" + intervalToStart + "> ?startNode . \n" +
|
||||||
"?startNode a <" + dateTimeValueType + "> . \n" +
|
"?startNode a <" + dateTimeValueType + "> . \n" +
|
||||||
"?startNode <" + dateTimeValue + "> ?existingDateStart }";
|
"?startNode <" + dateTimeValue + "> ?existingDateStart }";
|
||||||
|
|
||||||
final static String existingEndDateQuery =
|
final String existingEndDateQuery =
|
||||||
"SELECT ?existingEndDate WHERE { \n" +
|
"SELECT ?existingEndDate WHERE { \n" +
|
||||||
"?subject <" + toDateTimeInterval + "> ?existingIntervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> ?existingIntervalNode . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToEnd + "> ?endNode . \n" +
|
getNodeN3Var() + " <" + intervalToEnd + "> ?endNode . \n" +
|
||||||
"?endNode a <" + dateTimeValueType + "> . \n " +
|
"?endNode a <" + dateTimeValueType + "> . \n " +
|
||||||
"?endNode <" + dateTimeValue + "> ?existingEndDate . }";
|
"?endNode <" + dateTimeValue + "> ?existingEndDate . }";
|
||||||
|
|
||||||
final static String existingIntervalNodeQuery =
|
final String existingIntervalNodeQuery =
|
||||||
"SELECT ?existingIntervalNode WHERE { \n" +
|
"SELECT ?existingIntervalNode WHERE { \n" +
|
||||||
"?subject <" + toDateTimeInterval + "> ?existingIntervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> ?existingIntervalNode . \n" +
|
||||||
"?existingIntervalNode a <" + intervalType + "> . }";
|
"?existingIntervalNode a <" + intervalType + "> . }";
|
||||||
|
|
||||||
final static String existingStartNodeQuery =
|
final String existingStartNodeQuery =
|
||||||
"SELECT ?existingStartNode WHERE { \n" +
|
"SELECT ?existingStartNode WHERE { \n" +
|
||||||
"?subject <" + toDateTimeInterval + "> ?existingIntervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> ?existingIntervalNode . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToStart + "> ?existingStartNode . \n" +
|
getNodeN3Var() + " <" + intervalToStart + "> ?existingStartNode . \n" +
|
||||||
"?existingStartNode a <" + dateTimeValueType + "> .} ";
|
"?existingStartNode a <" + dateTimeValueType + "> .} ";
|
||||||
|
|
||||||
final static String existingEndNodeQuery =
|
final String existingEndNodeQuery =
|
||||||
"SELECT ?existingEndNode WHERE { \n" +
|
"SELECT ?existingEndNode WHERE { \n" +
|
||||||
"?subject <" + toDateTimeInterval + "> ?existingIntervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> ?existingIntervalNode . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToEnd + "> ?existingEndNode . \n" +
|
getNodeN3Var() + " <" + intervalToEnd + "> ?existingEndNode . \n" +
|
||||||
"?existingEndNode a <" + dateTimeValueType + "> .} ";
|
"?existingEndNode a <" + dateTimeValueType + "> .} ";
|
||||||
|
|
||||||
final static String existingStartPrecisionQuery =
|
final String existingStartPrecisionQuery =
|
||||||
"SELECT ?existingStartPrecision WHERE { \n" +
|
"SELECT ?existingStartPrecision WHERE { \n" +
|
||||||
"?subject <" + toDateTimeInterval + "> ?existingIntervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> ?existingIntervalNode . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToStart + "> ?startNode . \n" +
|
getNodeN3Var() + " <" + intervalToStart + "> ?startNode . \n" +
|
||||||
"?startNode a <" + dateTimeValueType + "> . \n" +
|
"?startNode a <" + dateTimeValueType + "> . \n" +
|
||||||
"?startNode <" + dateTimePrecision + "> ?existingStartPrecision . }";
|
"?startNode <" + dateTimePrecision + "> ?existingStartPrecision . }";
|
||||||
|
|
||||||
final static String existingEndPrecisionQuery =
|
final String existingEndPrecisionQuery =
|
||||||
"SELECT ?existingEndPrecision WHERE { \n" +
|
"SELECT ?existingEndPrecision WHERE { \n" +
|
||||||
"?subject <" + toDateTimeInterval + "> ?existingIntervalNode . \n" +
|
"?subject <" + getToDateTimeIntervalPredicate() + "> ?existingIntervalNode . \n" +
|
||||||
"?intervalNode a <" + intervalType + "> . \n" +
|
getNodeN3Var() + " a <" + intervalType + "> . \n" +
|
||||||
"?intervalNode <" + intervalToEnd + "> ?endNode . \n" +
|
getNodeN3Var() + " <" + intervalToEnd + "> ?endNode . \n" +
|
||||||
"?endNode a <" + dateTimeValueType + "> . \n" +
|
"?endNode a <" + dateTimeValueType + "> . \n" +
|
||||||
"?endNode <" + dateTimePrecision + "> ?existingEndPrecision . }";
|
"?endNode <" + dateTimePrecision + "> ?existingEndPrecision . }";
|
||||||
|
|
||||||
|
public String getToDateTimeIntervalPredicate() {
|
||||||
|
return toDateTimeInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeVar() {
|
||||||
|
return "intervalNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeN3Var() {
|
||||||
|
return "?" + getNodeVar();
|
||||||
|
}
|
||||||
|
|
||||||
//Adding form specific data such as edit mode
|
//Adding form specific data such as edit mode
|
||||||
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
|
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
|
||||||
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();
|
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class DateTimeValueFormGenerator extends BaseEditConfigurationGenerator
|
||||||
implements EditConfigurationGenerator {
|
implements EditConfigurationGenerator {
|
||||||
|
|
||||||
final static String vivoCore = "http://vivoweb.org/ontology/core#";
|
final static String vivoCore = "http://vivoweb.org/ontology/core#";
|
||||||
final static String toDateTimeValue = vivoCore + "dateTimeValue";
|
final String toDateTimeValue = vivoCore + "dateTimeValue";
|
||||||
final static String valueType = vivoCore + "DateTimeValue";
|
final static String valueType = vivoCore + "DateTimeValue";
|
||||||
final static String dateTimeValue = vivoCore + "dateTime";
|
final static String dateTimeValue = vivoCore + "dateTime";
|
||||||
final static String dateTimePrecision = vivoCore + "dateTimePrecision";
|
final static String dateTimePrecision = vivoCore + "dateTimePrecision";
|
||||||
|
@ -41,23 +41,23 @@ public class DateTimeValueFormGenerator extends BaseEditConfigurationGenerator
|
||||||
initPropertyParameters(vreq, session, conf);
|
initPropertyParameters(vreq, session, conf);
|
||||||
initObjectPropForm(conf, vreq);
|
initObjectPropForm(conf, vreq);
|
||||||
|
|
||||||
conf.setTemplate("dateTimeValueForm.ftl");
|
conf.setTemplate(this.getTemplate());
|
||||||
|
|
||||||
conf.setVarNameForSubject("subject");
|
conf.setVarNameForSubject("subject");
|
||||||
conf.setVarNameForPredicate("toDateTimeValue");
|
conf.setVarNameForPredicate("toDateTimeValue");
|
||||||
conf.setVarNameForObject("valueNode");
|
conf.setVarNameForObject("valueNode");
|
||||||
|
|
||||||
conf.setN3Optional(Arrays.asList(n3ForValue));
|
conf.setN3Optional(Arrays.asList(getN3ForValue()));
|
||||||
|
|
||||||
conf.addNewResource("valueNode", DEFAULT_NS_FOR_NEW_RESOURCE);
|
conf.addNewResource("valueNode", DEFAULT_NS_FOR_NEW_RESOURCE);
|
||||||
|
|
||||||
conf.addSparqlForExistingLiteral(
|
conf.addSparqlForExistingLiteral(
|
||||||
"dateTimeField-value", existingDateTimeValueQuery);
|
"dateTimeField-value", getExistingDateTimeValueQuery());
|
||||||
conf.addSparqlForExistingUris(
|
conf.addSparqlForExistingUris(
|
||||||
"dateTimeField-precision", existingPrecisionQuery);
|
"dateTimeField-precision", getExistingPrecisionQuery());
|
||||||
conf.addSparqlForExistingUris("valueNode", existingNodeQuery);
|
conf.addSparqlForExistingUris("valueNode", getExistingNodeQuery());
|
||||||
|
|
||||||
FieldVTwo dateTimeField = new FieldVTwo().setName("dateTimeField");
|
FieldVTwo dateTimeField = new FieldVTwo().setName(this.getDateTimeFieldName());
|
||||||
dateTimeField.setEditElement(new DateTimeWithPrecisionVTwo(dateTimeField,
|
dateTimeField.setEditElement(new DateTimeWithPrecisionVTwo(dateTimeField,
|
||||||
VitroVocabulary.Precision.SECOND.uri(),
|
VitroVocabulary.Precision.SECOND.uri(),
|
||||||
VitroVocabulary.Precision.NONE.uri()));
|
VitroVocabulary.Precision.NONE.uri()));
|
||||||
|
@ -71,30 +71,57 @@ public class DateTimeValueFormGenerator extends BaseEditConfigurationGenerator
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
final static String n3ForValue =
|
|
||||||
"?subject <" + toDateTimeValue + "> ?valueNode . \n" +
|
//Writing these as methods instead of static strings allows the method getToDateTimeValuePredicate
|
||||||
|
//to be called after the class has been initialized - this is important for subclasses of this generator
|
||||||
|
//that rely on vreq for predicate
|
||||||
|
protected String getN3ForValue() {
|
||||||
|
return "?subject <" + this.getToDateTimeValuePredicate() + "> ?valueNode . \n" +
|
||||||
"?valueNode a <" + valueType + "> . \n" +
|
"?valueNode a <" + valueType + "> . \n" +
|
||||||
"?valueNode <" + dateTimeValue + "> ?dateTimeField-value . \n" +
|
"?valueNode <" + dateTimeValue + "> ?dateTimeField-value . \n" +
|
||||||
"?valueNode <" + dateTimePrecision + "> ?dateTimeField-precision .";
|
"?valueNode <" + dateTimePrecision + "> ?dateTimeField-precision .";
|
||||||
|
}
|
||||||
|
|
||||||
final static String existingDateTimeValueQuery =
|
protected String getExistingDateTimeValueQuery () {
|
||||||
"SELECT ?existingDateTimeValue WHERE { \n" +
|
return "SELECT ?existingDateTimeValue WHERE { \n" +
|
||||||
"?subject <" + toDateTimeValue + "> ?existingValueNode . \n" +
|
"?subject <" + this.getToDateTimeValuePredicate() + "> ?existingValueNode . \n" +
|
||||||
"?existingValueNode a <" + valueType + "> . \n" +
|
"?existingValueNode a <" + valueType + "> . \n" +
|
||||||
"?existingValueNode <" + dateTimeValue + "> ?existingDateTimeValue }";
|
"?existingValueNode <" + dateTimeValue + "> ?existingDateTimeValue }";
|
||||||
|
}
|
||||||
|
|
||||||
final static String existingPrecisionQuery =
|
protected String getExistingPrecisionQuery() {
|
||||||
"SELECT ?existingPrecision WHERE { \n" +
|
return "SELECT ?existingPrecision WHERE { \n" +
|
||||||
"?subject <" + toDateTimeValue + "> ?existingValueNode . \n" +
|
"?subject <" + this.getToDateTimeValuePredicate() + "> ?existingValueNode . \n" +
|
||||||
"?existingValueNode a <" + valueType + "> . \n" +
|
"?existingValueNode a <" + valueType + "> . \n" +
|
||||||
"?existingValueNode <" + dateTimePrecision + "> ?existingPrecision }";
|
"?existingValueNode <" + dateTimePrecision + "> ?existingPrecision }";
|
||||||
|
}
|
||||||
final static String existingNodeQuery =
|
protected String getExistingNodeQuery() {
|
||||||
"SELECT ?existingNode WHERE { \n" +
|
return "SELECT ?existingNode WHERE { \n" +
|
||||||
"?subject <" + toDateTimeValue + "> ?existingNode . \n" +
|
"?subject <" + this.getToDateTimeValuePredicate() + "> ?existingNode . \n" +
|
||||||
"?existingNode a <" + valueType + "> }";
|
"?existingNode a <" + valueType + "> }";
|
||||||
|
|
||||||
|
}
|
||||||
|
public static String getNodeVar() {
|
||||||
|
return "valueNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getNodeN3Var() {
|
||||||
|
return "?" + getNodeVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
//isolating the predicate in this fashion allows this class to be subclassed for other date time value
|
||||||
|
//properties
|
||||||
|
protected String getToDateTimeValuePredicate() {
|
||||||
|
return this.toDateTimeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDateTimeFieldName() {
|
||||||
|
return "dateTimeField";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getTemplate() {
|
||||||
|
return "dateTimeValueForm.ftl";
|
||||||
|
}
|
||||||
//Adding form specific data such as edit mode
|
//Adding form specific data such as edit mode
|
||||||
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
|
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
|
||||||
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();
|
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();
|
||||||
|
|
|
@ -7,6 +7,7 @@ import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -105,11 +106,19 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
|
||||||
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
|
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
|
||||||
WebappDaoFactory wDaoFact = vreq.getWebappDaoFactory();
|
WebappDaoFactory wDaoFact = vreq.getWebappDaoFactory();
|
||||||
List<String> types = new ArrayList<String>();
|
List<String> types = new ArrayList<String>();
|
||||||
List <VClass> vclasses = new ArrayList<VClass>();
|
//Get all vclasses applicable to subject
|
||||||
vclasses = wDaoFact.getVClassDao().getVClassesForProperty(subject.getVClassURI(),predicateUri);
|
List<VClass> vClasses = subject.getVClasses();
|
||||||
for(VClass v: vclasses) {
|
HashSet<String> typesHash = new HashSet<String>();
|
||||||
types.add(v.getURI());
|
for(VClass vclass: vClasses) {
|
||||||
|
List<VClass> rangeVclasses = wDaoFact.getVClassDao().getVClassesForProperty(vclass.getURI(),predicateUri);
|
||||||
|
if(rangeVclasses != null) {
|
||||||
|
for(VClass range: rangeVclasses) {
|
||||||
|
//a hash will keep a unique list of types and so prevent duplicates
|
||||||
|
typesHash.add(range.getURI());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
types.addAll(typesHash);
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
|
||||||
|
|
||||||
|
//For use with classes that explicitly modify configurations through AJAX requests
|
||||||
|
public interface EditConfigurationAJAXGenerator {
|
||||||
|
public void modifyEditConfiguration( EditConfigurationVTwo config, VitroRequest vreq ) throws Exception;
|
||||||
|
}
|
|
@ -128,10 +128,11 @@ public class ProcessSparqlDataGetterN3 extends ProcessDataGetterAbstract {
|
||||||
|
|
||||||
existingLiteralValues.put(this.getVarName("query", counter),
|
existingLiteralValues.put(this.getVarName("query", counter),
|
||||||
new ArrayList<Literal>(Arrays.asList(queryLiteral)));
|
new ArrayList<Literal>(Arrays.asList(queryLiteral)));
|
||||||
|
//Query model is optional
|
||||||
|
if(queryModelResource != null && queryModelResource.getURI() != null) {
|
||||||
existingUriValues.put(this.getVarName("queryModel", counter),
|
existingUriValues.put(this.getVarName("queryModel", counter),
|
||||||
new ArrayList<String>(Arrays.asList(queryModelResource.getURI())));
|
new ArrayList<String>(Arrays.asList(queryModelResource.getURI())));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.controller;
|
||||||
|
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils.getPredicateUri;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.Property;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.DirectRedirectResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.json.GetDataForPage;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.json.GetEntitiesByVClass;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.json.GetEntitiesByVClassContinuation;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.json.GetRenderedSolrIndividualsByVClass;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.json.GetSolrIndividualsByVClass;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.json.GetSolrIndividualsByVClasses;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.json.GetVClassesForVClassGroup;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditSubmissionUtils;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmission;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.EditConfigurationAJAXGenerator;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.EditConfigurationGenerator;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.utils.log.LogUtils;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.edit.EditConfigurationTemplateModel;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.edit.MultiValueEditSubmissionTemplateModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This servlet is intended to handle all requests to create a form for use
|
||||||
|
* by the N3 editing system. It will examine the request parameters, determine
|
||||||
|
* which form to use, execute a EditConfiguration setup, and evaluate the
|
||||||
|
* view indicated by the EditConfiguration.
|
||||||
|
*
|
||||||
|
* Do not add code to this class to achieve some behavior in a
|
||||||
|
* form. Try adding the behavior logic to the code that generates the
|
||||||
|
* EditConfiguration for the form.
|
||||||
|
*/
|
||||||
|
public class EditRequestAJAXController extends VitroHttpServlet {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public static Log log = LogFactory.getLog(EditRequestDispatchController.class);
|
||||||
|
|
||||||
|
|
||||||
|
protected Actions requiredActions(VitroRequest vreq) {
|
||||||
|
return SimplePermission.DO_FRONT_END_EDITING.ACTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
super.doPost(req, resp);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
super.doGet(req, resp);
|
||||||
|
log.debug(LogUtils.formatRequestProperties(log, "debug", req));
|
||||||
|
|
||||||
|
VitroRequest vreq = new VitroRequest(req);
|
||||||
|
try {
|
||||||
|
//Get edit configuration object based on editk key in request
|
||||||
|
EditConfigurationVTwo config = getEditConfiguration(vreq);
|
||||||
|
//Get the generator name also from the request parameter
|
||||||
|
String generatorName = vreq.getParameter("generator");
|
||||||
|
String javaGeneratorName = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators." + generatorName;
|
||||||
|
//TODO: Add this method to generators, but for now constructing a new class of generator specifically for AJAX requests
|
||||||
|
EditConfigurationAJAXGenerator generator = getAJAXGenerator(javaGeneratorName, vreq, vreq.getSession());
|
||||||
|
//run the modification
|
||||||
|
generator.modifyEditConfiguration(config, vreq);
|
||||||
|
} catch(Exception ex) {
|
||||||
|
log.error("An error occurred in retrieving configuration and/or generator ", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EditConfigurationVTwo getEditConfiguration(VitroRequest vreq) {
|
||||||
|
|
||||||
|
EditConfigurationVTwo config = EditConfigurationVTwo.getConfigFromSession(vreq.getSession(), vreq);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EditConfigurationAJAXGenerator getAJAXGenerator(
|
||||||
|
String editConfGeneratorName, VitroRequest vreq, HttpSession session) throws Exception {
|
||||||
|
|
||||||
|
EditConfigurationAJAXGenerator EditConfigurationVTwoGenerator = null;
|
||||||
|
|
||||||
|
Object object = null;
|
||||||
|
try {
|
||||||
|
Class classDefinition = Class.forName(editConfGeneratorName);
|
||||||
|
object = classDefinition.newInstance();
|
||||||
|
EditConfigurationVTwoGenerator = (EditConfigurationAJAXGenerator) object;
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
System.out.println(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
System.out.println(e);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(EditConfigurationVTwoGenerator == null){
|
||||||
|
throw new Error("Could not find EditConfigurationVTwoGenerator " + editConfGeneratorName);
|
||||||
|
} else {
|
||||||
|
return EditConfigurationVTwoGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -155,13 +155,26 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
|
||||||
private EditConfigurationVTwo setupEditConfiguration(String editConfGeneratorName,
|
private EditConfigurationVTwo setupEditConfiguration(String editConfGeneratorName,
|
||||||
VitroRequest vreq) throws Exception {
|
VitroRequest vreq) throws Exception {
|
||||||
HttpSession session = vreq.getSession();
|
HttpSession session = vreq.getSession();
|
||||||
EditConfigurationVTwo editConfig =
|
//Originally, this code called makeEditConfiguration before checking for/setting the edit key
|
||||||
makeEditConfigurationVTwo( editConfGeneratorName, vreq, session);
|
//which meant that in the case of page reload on an error, you would recreate an edit configuration
|
||||||
|
//using the generator
|
||||||
|
//Given recent updates enabling modification of edit configuration dynamically through AJAX,
|
||||||
|
//we will first check whether the edit key exists and if there is already an edit configuration
|
||||||
|
//in the session - and then will utilize the edit configuration that already exists
|
||||||
//edit key is set here, NOT in the generator class
|
//edit key is set here, NOT in the generator class
|
||||||
|
EditConfigurationVTwo editConfig = null;
|
||||||
|
EditConfigurationVTwo existingConfig = EditConfigurationVTwo.getConfigFromSession(session, vreq);
|
||||||
|
if(existingConfig != null) {
|
||||||
|
editConfig = existingConfig;
|
||||||
|
} else {
|
||||||
|
editConfig =
|
||||||
|
makeEditConfigurationVTwo( editConfGeneratorName, vreq, session);
|
||||||
|
}
|
||||||
|
|
||||||
String editKey = EditConfigurationUtils.getEditKey(vreq);
|
String editKey = EditConfigurationUtils.getEditKey(vreq);
|
||||||
editConfig.setEditKey(editKey);
|
editConfig.setEditKey(editKey);
|
||||||
|
|
||||||
|
|
||||||
//put edit configuration in session so it can be accessed on form submit.
|
//put edit configuration in session so it can be accessed on form submit.
|
||||||
EditConfigurationVTwo.putConfigInSession(editConfig, session);
|
EditConfigurationVTwo.putConfigInSession(editConfig, session);
|
||||||
return editConfig;
|
return editConfig;
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class FileStorageSetup implements ServletContextListener {
|
||||||
* {@link ConfigurationProperties} for the vivo home directory. The file
|
* {@link ConfigurationProperties} for the vivo home directory. The file
|
||||||
* storage base directory is in a subdirectory below this one.
|
* storage base directory is in a subdirectory below this one.
|
||||||
*/
|
*/
|
||||||
public static final String PROPERTY_VITRO_HOME_DIR = "vitro.home.directory";
|
public static final String PROPERTY_VITRO_HOME_DIR = "vitro.home";
|
||||||
public static final String FILE_STORAGE_SUBDIRECTORY = "uploads";
|
public static final String FILE_STORAGE_SUBDIRECTORY = "uploads";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -94,6 +94,10 @@ public class FileServingServlet extends VitroHttpServlet {
|
||||||
String actualFilename = findAndValidateFilename(fileInfo, path);
|
String actualFilename = findAndValidateFilename(fileInfo, path);
|
||||||
|
|
||||||
in = openImageInputStream(fileInfo, actualFilename);
|
in = openImageInputStream(fileInfo, actualFilename);
|
||||||
|
} catch (FileServingException e) {
|
||||||
|
log.info("Failed to serve the file at '" + path + "' -- " + e.getMessage());
|
||||||
|
in = openMissingLinkImage(request);
|
||||||
|
mimeType = "image/png";
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Failed to serve the file at '" + path + "' -- " + e.getMessage());
|
log.warn("Failed to serve the file at '" + path + "' -- " + e.getMessage());
|
||||||
in = openMissingLinkImage(request);
|
in = openMissingLinkImage(request);
|
||||||
|
|
|
@ -21,6 +21,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||||
import freemarker.cache.WebappTemplateLoader;
|
import freemarker.cache.WebappTemplateLoader;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
|
@ -67,9 +69,10 @@ public class StartupStatusDisplayFilter implements Filter {
|
||||||
statusAlreadyDisplayed = true;
|
statusAlreadyDisplayed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayStartupStatus(ServletRequest req, ServletResponse resp) throws IOException,
|
private void displayStartupStatus(ServletRequest req, ServletResponse resp)
|
||||||
ServletException {
|
throws IOException, ServletException {
|
||||||
HttpServletResponse hResp = (HttpServletResponse) resp;
|
HttpServletResponse hresp = (HttpServletResponse) resp;
|
||||||
|
HttpServletRequest hreq = (HttpServletRequest) req;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<String, Object> bodyMap = new HashMap<String, Object>();
|
Map<String, Object> bodyMap = new HashMap<String, Object>();
|
||||||
|
@ -78,25 +81,24 @@ public class StartupStatusDisplayFilter implements Filter {
|
||||||
bodyMap.put("contextPath", getContextPath());
|
bodyMap.put("contextPath", getContextPath());
|
||||||
bodyMap.put("applicationName", getApplicationName());
|
bodyMap.put("applicationName", getApplicationName());
|
||||||
|
|
||||||
HttpServletRequest httpreq = (HttpServletRequest) req;
|
|
||||||
String url = "";
|
String url = "";
|
||||||
|
|
||||||
String path = httpreq.getRequestURI();
|
String path = hreq.getRequestURI();
|
||||||
if( path != null ){
|
if (path != null) {
|
||||||
url = path;
|
url = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
String query = httpreq.getQueryString();
|
String query = hreq.getQueryString();
|
||||||
if( !StringUtils.isEmpty( query )){
|
if (!StringUtils.isEmpty(query)) {
|
||||||
url = url + "?" + query;
|
url = url + "?" + query;
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyMap.put("url", url );
|
bodyMap.put("url", url);
|
||||||
|
|
||||||
hResp.setContentType("text/html;charset=UTF-8");
|
hresp.setContentType("text/html;charset=UTF-8");
|
||||||
hResp.setStatus(SC_INTERNAL_SERVER_ERROR);
|
hresp.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||||
Template tpl = loadFreemarkerTemplate();
|
Template tpl = loadFreemarkerTemplate();
|
||||||
tpl.process(bodyMap, hResp.getWriter());
|
tpl.process(bodyMap, hresp.getWriter());
|
||||||
} catch (TemplateException e) {
|
} catch (TemplateException e) {
|
||||||
throw new ServletException("Problem with Freemarker Template", e);
|
throw new ServletException("Problem with Freemarker Template", e);
|
||||||
}
|
}
|
||||||
|
@ -114,7 +116,9 @@ public class StartupStatusDisplayFilter implements Filter {
|
||||||
private Object getApplicationName() {
|
private Object getApplicationName() {
|
||||||
String name = "";
|
String name = "";
|
||||||
try {
|
try {
|
||||||
ApplicationBean app = ApplicationBean.getAppBean(ctx);
|
WebappDaoFactory wadf = (WebappDaoFactory) ctx
|
||||||
|
.getAttribute("webappDaoFactory");
|
||||||
|
ApplicationBean app = wadf.getApplicationDao().getApplicationBean();
|
||||||
name = app.getApplicationName();
|
name = app.getApplicationName();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// deal with problems below
|
// deal with problems below
|
||||||
|
|
|
@ -38,7 +38,6 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
@ -82,19 +81,10 @@ public class VitroRequestPrep implements Filter {
|
||||||
};
|
};
|
||||||
|
|
||||||
private ServletContext _context;
|
private ServletContext _context;
|
||||||
private ApplicationBean _appbean;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(FilterConfig filterConfig) throws ServletException {
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
_context = filterConfig.getServletContext();
|
_context = filterConfig.getServletContext();
|
||||||
|
|
||||||
Object o = _context.getAttribute("applicationBean");
|
|
||||||
if (o instanceof ApplicationBean) {
|
|
||||||
_appbean = (ApplicationBean) o;
|
|
||||||
} else {
|
|
||||||
_appbean = new ApplicationBean();
|
|
||||||
}
|
|
||||||
log.debug("VitroRequestPrep: AppBean theme " + _appbean.getThemeDir());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -132,9 +122,6 @@ public class VitroRequestPrep implements Filter {
|
||||||
|
|
||||||
VitroRequest vreq = new VitroRequest(req);
|
VitroRequest vreq = new VitroRequest(req);
|
||||||
|
|
||||||
//-- setup appBean --//
|
|
||||||
vreq.setAppBean(_appbean);
|
|
||||||
|
|
||||||
//-- setup DAO factory --//
|
//-- setup DAO factory --//
|
||||||
WebappDaoFactory wdf = getWebappDaoFactory(vreq);
|
WebappDaoFactory wdf = getWebappDaoFactory(vreq);
|
||||||
//TODO: get accept-language from request and set as preferred languages
|
//TODO: get accept-language from request and set as preferred languages
|
||||||
|
|
231
webapp/src/edu/cornell/mannlib/vitro/webapp/i18n/I18n.java
Normal file
231
webapp/src/edu/cornell/mannlib/vitro/webapp/i18n/I18n.java
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.ResourceBundle.Control;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to a bundle of text strings, based on the name of the bundle,
|
||||||
|
* the Locale of the requesting browser, and the current theme directory.
|
||||||
|
*
|
||||||
|
* If the bundle name is not specified, the default name of "all" is used.
|
||||||
|
*
|
||||||
|
* If a requested bundle is not found, no error is thrown. Instead, an empty
|
||||||
|
* bundle is returned that produces error message strings when asked for text.
|
||||||
|
*/
|
||||||
|
public class I18n {
|
||||||
|
private static final Log log = LogFactory.getLog(I18n.class);
|
||||||
|
|
||||||
|
public static final String DEFAULT_BUNDLE_NAME = "all";
|
||||||
|
private static final String PROPERTY_DEVELOPER_DEFEAT_CACHE = "developer.defeatI18nCache";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is where the work gets done. Not declared final, so it can be
|
||||||
|
* modified in unit tests.
|
||||||
|
*/
|
||||||
|
private static I18n instance = new I18n();
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Static methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A convenience method to get a bundle and format the text.
|
||||||
|
*/
|
||||||
|
public static String text(String bundleName, HttpServletRequest req,
|
||||||
|
String key, Object... parameters) {
|
||||||
|
return bundle(bundleName, req).text(key, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A convenience method to get the default bundle and format the text.
|
||||||
|
*/
|
||||||
|
public static String text(HttpServletRequest req, String key,
|
||||||
|
Object... parameters) {
|
||||||
|
return bundle(req).text(key, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a I18nBundle by this name.
|
||||||
|
*/
|
||||||
|
public static I18nBundle bundle(String bundleName, HttpServletRequest req) {
|
||||||
|
return instance.getBundle(bundleName, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default I18nBundle.
|
||||||
|
*/
|
||||||
|
public static I18nBundle bundle(HttpServletRequest req) {
|
||||||
|
return instance.getBundle(DEFAULT_BUNDLE_NAME, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// The instance
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Holds the current theme directory, as far as we know. */
|
||||||
|
private AtomicReference<String> themeDirectory = new AtomicReference<String>(
|
||||||
|
"");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an I18nBundle by this name. The request provides the preferred
|
||||||
|
* Locale, the application directory, the theme directory and the
|
||||||
|
* development mode flag.
|
||||||
|
*
|
||||||
|
* If the request indicates that the system is in development mode, then the
|
||||||
|
* cache is cleared on each request.
|
||||||
|
*
|
||||||
|
* If the theme directory has changed, the cache is cleared.
|
||||||
|
*/
|
||||||
|
private I18nBundle getBundle(String bundleName, HttpServletRequest req) {
|
||||||
|
log.debug("Getting bundle '" + bundleName + "'");
|
||||||
|
|
||||||
|
try {
|
||||||
|
checkDevelopmentMode(req);
|
||||||
|
checkForChangeInThemeDirectory(req);
|
||||||
|
|
||||||
|
String dir = themeDirectory.get();
|
||||||
|
ServletContext ctx = req.getSession().getServletContext();
|
||||||
|
|
||||||
|
ResourceBundle.Control control = getControl(ctx, dir);
|
||||||
|
ResourceBundle rb = ResourceBundle.getBundle(bundleName,
|
||||||
|
req.getLocale(), control);
|
||||||
|
return new I18nBundle(bundleName, rb);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
log.warn("Didn't find text bundle '" + bundleName + "'");
|
||||||
|
return I18nBundle.emptyBundle(bundleName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to create text bundle '" + bundleName + "'", e);
|
||||||
|
return I18nBundle.emptyBundle(bundleName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we are in development mode, clear the cache on each request.
|
||||||
|
*/
|
||||||
|
private void checkDevelopmentMode(HttpServletRequest req) {
|
||||||
|
ConfigurationProperties bean = ConfigurationProperties.getBean(req);
|
||||||
|
|
||||||
|
String flag = bean
|
||||||
|
.getProperty(PROPERTY_DEVELOPER_DEFEAT_CACHE, "false");
|
||||||
|
if (Boolean.valueOf(flag.trim())) {
|
||||||
|
log.debug("In development mode - clearing the cache.");
|
||||||
|
ResourceBundle.clearCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the theme directory has changed from before, clear the cache of all
|
||||||
|
* ResourceBundles.
|
||||||
|
*/
|
||||||
|
private void checkForChangeInThemeDirectory(HttpServletRequest req) {
|
||||||
|
String currentDir = new VitroRequest(req).getAppBean().getThemeDir();
|
||||||
|
String previousDir = themeDirectory.getAndSet(currentDir);
|
||||||
|
if (!currentDir.equals(previousDir)) {
|
||||||
|
log.debug("Theme directory changed from '" + previousDir + "' to '"
|
||||||
|
+ currentDir + "' - clearing the cache.");
|
||||||
|
ResourceBundle.clearCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method in the unit tests, to return a more testable Control
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
|
protected Control getControl(ServletContext ctx, String dir) {
|
||||||
|
return new ThemeBasedControl(ctx, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Control classes for instantiating ResourceBundles
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instead of looking in the classpath, look in the theme i18n directory and
|
||||||
|
* the application i18n directory.
|
||||||
|
*/
|
||||||
|
private static class ThemeBasedControl extends ResourceBundle.Control {
|
||||||
|
private static final String BUNDLE_DIRECTORY = "i18n/";
|
||||||
|
private final ServletContext ctx;
|
||||||
|
private final String themeDirectory;
|
||||||
|
|
||||||
|
public ThemeBasedControl(ServletContext ctx, String themeDirectory) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.themeDirectory = themeDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't look for classes to satisfy the request, just property files.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getFormats(String baseName) {
|
||||||
|
return FORMAT_PROPERTIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't look in the class path, look in the current servlet context, in
|
||||||
|
* the bundle directory under the theme directory and in the bundle
|
||||||
|
* directory under the application directory.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ResourceBundle newBundle(String baseName, Locale locale,
|
||||||
|
String format, ClassLoader loader, boolean reload)
|
||||||
|
throws IllegalAccessException, InstantiationException,
|
||||||
|
IOException {
|
||||||
|
checkArguments(baseName, locale, format);
|
||||||
|
|
||||||
|
log.debug("Creating bundle for '" + baseName + "', " + locale
|
||||||
|
+ ", '" + format + "', " + reload);
|
||||||
|
|
||||||
|
String bundleName = toBundleName(baseName, locale);
|
||||||
|
if (bundleName == null) {
|
||||||
|
throw new NullPointerException("bundleName may not be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
String themeI18nPath = "/" + themeDirectory + BUNDLE_DIRECTORY;
|
||||||
|
String appI18nPath = "/" + BUNDLE_DIRECTORY;
|
||||||
|
|
||||||
|
log.debug("Paths are '" + themeI18nPath + "' and '" + appI18nPath
|
||||||
|
+ "'");
|
||||||
|
|
||||||
|
return VitroResourceBundle.getBundle(bundleName, ctx, appI18nPath,
|
||||||
|
themeI18nPath, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The documentation for ResourceBundle.Control.newBundle() says I
|
||||||
|
* should throw these exceptions.
|
||||||
|
*/
|
||||||
|
private void checkArguments(String baseName, Locale locale,
|
||||||
|
String format) {
|
||||||
|
if (baseName == null) {
|
||||||
|
throw new NullPointerException("baseName may not be null.");
|
||||||
|
}
|
||||||
|
if (locale == null) {
|
||||||
|
throw new NullPointerException("locale may not be null.");
|
||||||
|
}
|
||||||
|
if (format == null) {
|
||||||
|
throw new NullPointerException("format may not be null.");
|
||||||
|
}
|
||||||
|
if (!FORMAT_DEFAULT.contains(format)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"format must be one of these: " + FORMAT_DEFAULT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
webapp/src/edu/cornell/mannlib/vitro/webapp/i18n/I18nBundle.java
Normal file
102
webapp/src/edu/cornell/mannlib/vitro/webapp/i18n/I18nBundle.java
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for a ResourceBundle that will not throw an exception, no matter
|
||||||
|
* what string you request.
|
||||||
|
*
|
||||||
|
* If the ResourceBundle was not found, or if it doesn't contain the requested
|
||||||
|
* key, an error message string is returned, to help the developer diagnose the
|
||||||
|
* problem.
|
||||||
|
*/
|
||||||
|
public class I18nBundle {
|
||||||
|
private static final Log log = LogFactory.getLog(I18nBundle.class);
|
||||||
|
|
||||||
|
private static final String MESSAGE_BUNDLE_NOT_FOUND = "Text bundle ''{0}'' not found.";
|
||||||
|
private static final String MESSAGE_KEY_NOT_FOUND = "Text bundle ''{0}'' has no text for ''{1}''";
|
||||||
|
|
||||||
|
public static I18nBundle emptyBundle(String bundleName) {
|
||||||
|
return new I18nBundle(bundleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String bundleName;
|
||||||
|
private final ResourceBundle resources;
|
||||||
|
private final String notFoundMessage;
|
||||||
|
|
||||||
|
private I18nBundle(String bundleName) {
|
||||||
|
this(bundleName, new EmptyResourceBundle(), MESSAGE_BUNDLE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
public I18nBundle(String bundleName, ResourceBundle resources) {
|
||||||
|
this(bundleName, resources, MESSAGE_KEY_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
private I18nBundle(String bundleName, ResourceBundle resources, String notFoundMessage) {
|
||||||
|
if (bundleName == null) {
|
||||||
|
throw new IllegalArgumentException("bundleName may not be null");
|
||||||
|
}
|
||||||
|
if (bundleName.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("bundleName may not be empty");
|
||||||
|
}
|
||||||
|
if (resources == null) {
|
||||||
|
throw new NullPointerException("resources may not be null.");
|
||||||
|
}if (notFoundMessage == null) {
|
||||||
|
throw new NullPointerException("notFoundMessage may not be null.");
|
||||||
|
}
|
||||||
|
this.bundleName = bundleName;
|
||||||
|
this.resources = resources;
|
||||||
|
this.notFoundMessage = notFoundMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String text(String key, Object... parameters) {
|
||||||
|
log.debug("Asking for '" + key + "' from bundle '" + bundleName + "'");
|
||||||
|
|
||||||
|
String textString;
|
||||||
|
if (resources.containsKey(key)) {
|
||||||
|
textString = resources.getString(key);
|
||||||
|
return formatString(textString, parameters);
|
||||||
|
} else {
|
||||||
|
String message = MessageFormat.format(notFoundMessage, bundleName,
|
||||||
|
key);
|
||||||
|
log.warn(message);
|
||||||
|
return "ERROR: " + message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatString(String textString, Object... parameters) {
|
||||||
|
if (parameters.length == 0) {
|
||||||
|
return textString;
|
||||||
|
} else {
|
||||||
|
return MessageFormat.format(textString, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A resource bundle that contains no strings.
|
||||||
|
*/
|
||||||
|
public static class EmptyResourceBundle extends ResourceBundle {
|
||||||
|
@Override
|
||||||
|
public Enumeration<String> getKeys() {
|
||||||
|
return Collections.enumeration(Collections.<String> emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object handleGetObject(String key) {
|
||||||
|
if (key == null) {
|
||||||
|
throw new NullPointerException("key may not be null.");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Works like a PropertyResourceBundle with two exceptions:
|
||||||
|
*
|
||||||
|
* It looks for the file in both the i18n directory of the theme and in the i18n
|
||||||
|
* directory of the application. Properties found in the theme override those
|
||||||
|
* found in the application.
|
||||||
|
*
|
||||||
|
* It allows a property to take its contents from a file. File paths are
|
||||||
|
* relative to the i18n directory. Again, a file in the theme will override one
|
||||||
|
* in the application.
|
||||||
|
*
|
||||||
|
* If a property has a value (after overriding) of "@@file <filepath>", the
|
||||||
|
* bundle looks for the file relative to the i18n directory of the theme, then
|
||||||
|
* relative to the i18n directory of the application. If the file is not found
|
||||||
|
* in either location, a warning is written to the log and the property will
|
||||||
|
* contain an error message for displayed.
|
||||||
|
*
|
||||||
|
* Note that the filename is not manipulated for Locale, so the author of the
|
||||||
|
* properties files must do it explicitly. For example:
|
||||||
|
*
|
||||||
|
* In all.properties: account_email_html = @@file accountEmail.html
|
||||||
|
*
|
||||||
|
* In all_es.properties: account_email_html = @@file accountEmail_es.html
|
||||||
|
*/
|
||||||
|
public class VitroResourceBundle extends ResourceBundle {
|
||||||
|
private static final Log log = LogFactory.getLog(VitroResourceBundle.class);
|
||||||
|
|
||||||
|
private static final String FILE_FLAG = "@@file ";
|
||||||
|
private static final String MESSAGE_FILE_NOT_FOUND = "File {1} not found for property {0}.";
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Factory method
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public static VitroResourceBundle getBundle(String bundleName,
|
||||||
|
ServletContext ctx, String appI18nPath, String themeI18nPath,
|
||||||
|
Control control) {
|
||||||
|
try {
|
||||||
|
return new VitroResourceBundle(bundleName, ctx, appI18nPath,
|
||||||
|
themeI18nPath, control);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
log.debug(e);
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// The instance
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private final String bundleName;
|
||||||
|
private final ServletContext ctx;
|
||||||
|
private final String appI18nPath;
|
||||||
|
private final String themeI18nPath;
|
||||||
|
private final Control control;
|
||||||
|
private final Properties defaults;
|
||||||
|
private final Properties properties;
|
||||||
|
|
||||||
|
private VitroResourceBundle(String bundleName, ServletContext ctx,
|
||||||
|
String appI18nPath, String themeI18nPath, Control control)
|
||||||
|
throws IOException {
|
||||||
|
this.bundleName = bundleName;
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.appI18nPath = appI18nPath;
|
||||||
|
this.themeI18nPath = themeI18nPath;
|
||||||
|
this.control = control;
|
||||||
|
|
||||||
|
this.defaults = new Properties();
|
||||||
|
this.properties = new Properties(this.defaults);
|
||||||
|
|
||||||
|
loadProperties();
|
||||||
|
loadReferencedFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadProperties() throws IOException {
|
||||||
|
String resourceName = control.toResourceName(bundleName, "properties");
|
||||||
|
|
||||||
|
String defaultsPath = joinPath(appI18nPath, resourceName);
|
||||||
|
String propertiesPath = joinPath(themeI18nPath, resourceName);
|
||||||
|
File defaultsFile = locateFile(defaultsPath);
|
||||||
|
File propertiesFile = locateFile(propertiesPath);
|
||||||
|
|
||||||
|
if ((defaultsFile == null) && (propertiesFile == null)) {
|
||||||
|
throw new FileNotFoundException("Property file not found at '"
|
||||||
|
+ defaultsPath + "' or '" + propertiesPath + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultsFile != null) {
|
||||||
|
log.debug("Loading bundle '" + bundleName + "' defaults from '"
|
||||||
|
+ defaultsPath + "'");
|
||||||
|
FileInputStream stream = new FileInputStream(defaultsFile);
|
||||||
|
Reader reader = new InputStreamReader(stream, "UTF-8");
|
||||||
|
try {
|
||||||
|
this.defaults.load(reader);
|
||||||
|
} finally {
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (propertiesFile != null) {
|
||||||
|
log.debug("Loading bundle '" + bundleName + "' overrides from '"
|
||||||
|
+ propertiesPath + "'");
|
||||||
|
FileInputStream stream = new FileInputStream(propertiesFile);
|
||||||
|
Reader reader = new InputStreamReader(stream, "UTF-8");
|
||||||
|
try {
|
||||||
|
this.properties.load(reader);
|
||||||
|
} finally {
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadReferencedFiles() throws IOException {
|
||||||
|
for (String key : this.properties.stringPropertyNames()) {
|
||||||
|
String value = this.properties.getProperty(key);
|
||||||
|
if (value.startsWith(FILE_FLAG)) {
|
||||||
|
String filepath = value.substring(FILE_FLAG.length()).trim();
|
||||||
|
loadReferencedFile(key, filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadReferencedFile(String key, String filepath)
|
||||||
|
throws IOException {
|
||||||
|
String appFilePath = joinPath(appI18nPath, filepath);
|
||||||
|
String themeFilePath = joinPath(themeI18nPath, filepath);
|
||||||
|
File appFile = locateFile(appFilePath);
|
||||||
|
File themeFile = locateFile(themeFilePath);
|
||||||
|
|
||||||
|
if (themeFile != null) {
|
||||||
|
this.properties.setProperty(key,
|
||||||
|
FileUtils.readFileToString(themeFile, "UTF-8"));
|
||||||
|
} else if (appFile != null) {
|
||||||
|
this.properties.setProperty(key,
|
||||||
|
FileUtils.readFileToString(appFile, "UTF-8"));
|
||||||
|
} else {
|
||||||
|
String message = MessageFormat.format(MESSAGE_FILE_NOT_FOUND, key,
|
||||||
|
themeFilePath, appFilePath);
|
||||||
|
this.properties.setProperty(key, message);
|
||||||
|
log.warn(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String joinPath(String root, String twig) {
|
||||||
|
if ((root.charAt(root.length() - 1) == File.separatorChar)
|
||||||
|
|| (twig.charAt(0) == File.separatorChar)) {
|
||||||
|
return root + twig;
|
||||||
|
} else {
|
||||||
|
return root + File.separatorChar + twig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File locateFile(String path) {
|
||||||
|
String realPath = ctx.getRealPath(path);
|
||||||
|
if (realPath == null) {
|
||||||
|
log.debug("No real path for '" + path + "'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
File f = new File(realPath);
|
||||||
|
if (!f.isFile()) {
|
||||||
|
log.debug("No file at '" + realPath + "'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!f.canRead()) {
|
||||||
|
log.error("Can't read the file at '" + realPath + "'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
log.debug("Located file '" + path + "' at '" + realPath + "'");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Enumeration<String> getKeys() {
|
||||||
|
return (Enumeration<String>) this.properties.propertyNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object handleGetObject(String key) {
|
||||||
|
String value = this.properties.getProperty(key);
|
||||||
|
if (value == null) {
|
||||||
|
log.debug(bundleName + " has no value for '" + key + "'");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.freemarker;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
|
||||||
|
import freemarker.template.TemplateHashModel;
|
||||||
|
import freemarker.template.TemplateModel;
|
||||||
|
import freemarker.template.TemplateModelException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Freemarker, this acts like a bundle of text strings. It is simply a
|
||||||
|
* wrapper around an I18nBundle.
|
||||||
|
*/
|
||||||
|
public class I18nBundleTemplateModel implements TemplateHashModel {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(I18nBundleTemplateModel.class);
|
||||||
|
|
||||||
|
private final String bundleName;
|
||||||
|
private final I18nBundle textBundle;
|
||||||
|
|
||||||
|
public I18nBundleTemplateModel(String bundleName, I18nBundle textBundle) {
|
||||||
|
this.bundleName = bundleName;
|
||||||
|
this.textBundle = textBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateModel get(String key) throws TemplateModelException {
|
||||||
|
return new I18nStringTemplateModel(bundleName, key,
|
||||||
|
textBundle.text(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() throws TemplateModelException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.freemarker;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
|
||||||
|
import freemarker.core.Environment;
|
||||||
|
import freemarker.template.TemplateMethodModel;
|
||||||
|
import freemarker.template.TemplateModelException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Freemarker method will produce a bundle of text strings. It is simply a
|
||||||
|
* wrapper around I18n that produces a wrapped I18nBundle.
|
||||||
|
*
|
||||||
|
* If the bundle name is not provided, the default bundle is assumed.
|
||||||
|
*/
|
||||||
|
public class I18nMethodModel implements TemplateMethodModel {
|
||||||
|
private static final Log log = LogFactory.getLog(I18nMethodModel.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public Object exec(List args) throws TemplateModelException {
|
||||||
|
if (args.size() > 1) {
|
||||||
|
throw new TemplateModelException("Too many arguments: "
|
||||||
|
+ "displayText method only requires a bundle name.");
|
||||||
|
}
|
||||||
|
Object arg = args.isEmpty() ? I18n.DEFAULT_BUNDLE_NAME : args.get(0);
|
||||||
|
if (!(arg instanceof String)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Arguments to a TemplateMethodModel are supposed to be Strings!");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Asking for this bundle: " + arg);
|
||||||
|
String bundleName = (String) arg;
|
||||||
|
|
||||||
|
Environment env = Environment.getCurrentEnvironment();
|
||||||
|
HttpServletRequest request = (HttpServletRequest) env
|
||||||
|
.getCustomAttribute("request");
|
||||||
|
I18nBundle tb = I18n.bundle(bundleName, request);
|
||||||
|
return new I18nBundleTemplateModel(bundleName, tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.freemarker;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import freemarker.template.TemplateMethodModelEx;
|
||||||
|
import freemarker.template.TemplateModel;
|
||||||
|
import freemarker.template.TemplateModelException;
|
||||||
|
import freemarker.template.TemplateScalarModel;
|
||||||
|
import freemarker.template.utility.DeepUnwrap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Freemarker representation of a text string. Because it implements
|
||||||
|
* TemplateScalarModel, you can use it as a string value. And because it
|
||||||
|
* implements TemplateMethodModel, you can pass arguments to it for formatting.
|
||||||
|
*
|
||||||
|
* So if the string is "His name is {0}!", then these references could be used:
|
||||||
|
*
|
||||||
|
* ${string} ==> "His name is {0}!"
|
||||||
|
*
|
||||||
|
* ${string("Bozo")} ==> "His name is Bozo!"
|
||||||
|
*
|
||||||
|
* Note that the format of the message is determined by java.text.MessageFormat,
|
||||||
|
* so argument indices start at 0 and you can escape a substring by wrapping it
|
||||||
|
* in apostrophes.
|
||||||
|
*/
|
||||||
|
public class I18nStringTemplateModel implements TemplateMethodModelEx,
|
||||||
|
TemplateScalarModel {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(I18nStringTemplateModel.class);
|
||||||
|
|
||||||
|
private final String bundleName;
|
||||||
|
private final String key;
|
||||||
|
private final String textString;
|
||||||
|
|
||||||
|
public I18nStringTemplateModel(String bundleName, String key,
|
||||||
|
String textString) {
|
||||||
|
this.bundleName = bundleName;
|
||||||
|
this.key = key;
|
||||||
|
this.textString = textString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAsString() throws TemplateModelException {
|
||||||
|
return textString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
@Override
|
||||||
|
public Object exec(List args) throws TemplateModelException {
|
||||||
|
log.debug("Formatting string '" + key + "' from bundle '" + bundleName
|
||||||
|
+ "' with these arguments: " + args);
|
||||||
|
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
return textString;
|
||||||
|
} else {
|
||||||
|
Object[] unwrappedArgs = new Object[args.size()];
|
||||||
|
for (int i = 0; i < args.size(); i++) {
|
||||||
|
unwrappedArgs[i] = DeepUnwrap.unwrap((TemplateModel) args
|
||||||
|
.get(i));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return MessageFormat.format(textString, unwrappedArgs);
|
||||||
|
} catch (Exception e) {
|
||||||
|
String message = "Can't format '" + key + "' from bundle '"
|
||||||
|
+ bundleName + "', wrong argument types: " + args
|
||||||
|
+ " for message format'" + textString + "'";
|
||||||
|
log.warn(message);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.LocaleUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this at /selectLocale&selection=[locale_string]
|
||||||
|
*
|
||||||
|
* For example: /selectLocale&selection=en_US or /selectLocale&selection=es
|
||||||
|
*
|
||||||
|
* Write an error to the log (and to DisplayMessage) if the selection is not
|
||||||
|
* syntactically valid.
|
||||||
|
*
|
||||||
|
* Write a warning to the log if the selection code is not one of the selectable
|
||||||
|
* Locales from runtime.properties, or if the selection code is not recognized
|
||||||
|
* by the system.
|
||||||
|
*
|
||||||
|
* Set the new Locale in the Session using SelectedLocale and return to the
|
||||||
|
* referrer.
|
||||||
|
*/
|
||||||
|
public class LocaleSelectionController extends HttpServlet {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(LocaleSelectionController.class);
|
||||||
|
|
||||||
|
public static final String PARAMETER_SELECTION = "selection";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
String referrer = req.getHeader("referer");
|
||||||
|
|
||||||
|
String selectedLocale = req.getParameter(PARAMETER_SELECTION);
|
||||||
|
|
||||||
|
try {
|
||||||
|
processSelectedLocale(req, selectedLocale);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to process the user's Locale selection", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(referrer)) {
|
||||||
|
resp.sendRedirect(UrlBuilder.getHomeUrl());
|
||||||
|
} else {
|
||||||
|
resp.sendRedirect(referrer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processSelectedLocale(HttpServletRequest req,
|
||||||
|
String selectedLocale) {
|
||||||
|
if (StringUtils.isBlank(selectedLocale)) {
|
||||||
|
log.debug("No '" + PARAMETER_SELECTION + "' parameter");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale locale = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
locale = LocaleUtils.toLocale(selectedLocale.trim());
|
||||||
|
log.debug("Locale selection is " + locale);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.error("Failed to convert the selection to a Locale", e);
|
||||||
|
DisplayMessage.setMessage(req,
|
||||||
|
"There was a problem in the system. "
|
||||||
|
+ "Your language choice was rejected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Locale> selectables = SelectedLocale.getSelectableLocales(req);
|
||||||
|
if (!selectables.contains(locale)) {
|
||||||
|
log.warn("User selected a locale '" + locale
|
||||||
|
+ "' that was not in the list: " + selectables);
|
||||||
|
} else if (!LocaleUtils.isAvailableLocale(locale)) {
|
||||||
|
log.warn("User selected an unrecognized locale: '" + locale + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedLocale.setSelectedLocale(req, locale);
|
||||||
|
log.debug("Setting selected locale to " + locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
doGet(req, resp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data for the selectable Locales, so the Freemarker template can
|
||||||
|
* create a row of flag images that will select the desired locale.
|
||||||
|
*
|
||||||
|
* If there are no selectable Locales in runtime.properties, we return an empty
|
||||||
|
* map. (selectLocale?? will return false)
|
||||||
|
*
|
||||||
|
* If the Locale has been forced by runtime.properties, we do the same.
|
||||||
|
*
|
||||||
|
* If there are selectable Locales, the returned map will contain a structure
|
||||||
|
* like this:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {selectLocale={
|
||||||
|
* selectLocaleUrl = [the URL for the form action to select a Locale]
|
||||||
|
* locales={ [a list of maps]
|
||||||
|
* { [a map for each Locale]
|
||||||
|
* code = [the code for the Locale, e.g. "en_US"]
|
||||||
|
* label = [the alt text for the Locale, e.g. "Spanish (Spain)"]
|
||||||
|
* imageUrl = [the URL of the image that represents the Locale]
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class LocaleSelectionDataGetter implements DataGetter {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(LocaleSelectionDataGetter.class);
|
||||||
|
|
||||||
|
private final VitroRequest vreq;
|
||||||
|
|
||||||
|
public LocaleSelectionDataGetter(VitroRequest vreq) {
|
||||||
|
this.vreq = vreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getData(Map<String, Object> valueMap) {
|
||||||
|
List<Locale> selectables = SelectedLocale.getSelectableLocales(vreq);
|
||||||
|
if (selectables.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<String, Object>();
|
||||||
|
result.put("selectLocaleUrl", UrlBuilder.getUrl("/selectLocale"));
|
||||||
|
result.put("locales", buildLocalesList(selectables));
|
||||||
|
|
||||||
|
Map<String, Object> bodyMap = new HashMap<String, Object>();
|
||||||
|
bodyMap.put("selectLocale", result);
|
||||||
|
log.debug("Sending these values: " + bodyMap);
|
||||||
|
return bodyMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Map<String, Object>> buildLocalesList(List<Locale> selectables) {
|
||||||
|
Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
|
||||||
|
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
|
||||||
|
for (Locale locale : selectables) {
|
||||||
|
try {
|
||||||
|
list.add(buildLocaleMap(locale, currentLocale));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
log.warn("Can't show the Locale selector for '" + locale
|
||||||
|
+ "': " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> buildLocaleMap(Locale locale,
|
||||||
|
Locale currentLocale) throws FileNotFoundException {
|
||||||
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
|
map.put("code", locale.toString());
|
||||||
|
map.put("label", locale.getDisplayName(currentLocale));
|
||||||
|
map.put("imageUrl", LocaleSelectorUtilities.getImageUrl(vreq, locale));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
import org.apache.commons.collections.EnumerationUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for a Locale in the ServletContext or the Session that should override
|
||||||
|
* the Locale in the ServletRequest.
|
||||||
|
*
|
||||||
|
* If there is such a Locale, wrap the ServletRequest so it behaves as if that
|
||||||
|
* is the preferred Locale.
|
||||||
|
*
|
||||||
|
* Otherwise, just process the request as usual.
|
||||||
|
*/
|
||||||
|
public class LocaleSelectionFilter implements Filter {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(LocaleSelectionFilter.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
// Nothing to do at startup.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
// Nothing to do at shutdown.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response,
|
||||||
|
FilterChain chain) throws IOException, ServletException {
|
||||||
|
if (request instanceof HttpServletRequest) {
|
||||||
|
HttpServletRequest hreq = (HttpServletRequest) request;
|
||||||
|
|
||||||
|
Locale overridingLocale = SelectedLocale.getOverridingLocale(hreq);
|
||||||
|
log.debug("overriding Locale is " + overridingLocale);
|
||||||
|
|
||||||
|
if (overridingLocale != null) {
|
||||||
|
request = new LocaleSelectionRequestWrapper(hreq,
|
||||||
|
overridingLocale);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("Not an HttpServletRequest.");
|
||||||
|
}
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Helper classes
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the selected Locale as the preferred Locale of the request.
|
||||||
|
*/
|
||||||
|
private static class LocaleSelectionRequestWrapper extends
|
||||||
|
HttpServletRequestWrapper {
|
||||||
|
private final List<Locale> locales;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public LocaleSelectionRequestWrapper(HttpServletRequest request,
|
||||||
|
Locale selectedLocale) {
|
||||||
|
super(request);
|
||||||
|
|
||||||
|
if (request == null) {
|
||||||
|
throw new NullPointerException("request may not be null.");
|
||||||
|
}
|
||||||
|
if (selectedLocale == null) {
|
||||||
|
throw new NullPointerException(
|
||||||
|
"selectedLocale may not be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale selectedLanguage = new Locale(selectedLocale.getLanguage());
|
||||||
|
|
||||||
|
locales = EnumerationUtils.toList(request.getLocales());
|
||||||
|
locales.remove(selectedLanguage);
|
||||||
|
locales.add(0, selectedLanguage);
|
||||||
|
locales.remove(selectedLocale);
|
||||||
|
locales.add(0, selectedLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Locale getLocale() {
|
||||||
|
return locales.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the modified list of locales.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public Enumeration getLocales() {
|
||||||
|
return Collections.enumeration(locales);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.LocaleUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the ConfigurationProperties for a forced locale, or for a
|
||||||
|
* comma-separate list of selectable locales.
|
||||||
|
*
|
||||||
|
* Create the appropriate Locale objects and store them in the ServletContext.
|
||||||
|
*/
|
||||||
|
public class LocaleSelectionSetup implements ServletContextListener {
|
||||||
|
/**
|
||||||
|
* If this is set, the locale is forced. No selection will be offered to the
|
||||||
|
* user, and browser locales will be ignored.
|
||||||
|
*/
|
||||||
|
public static final String PROPERTY_FORCE_LOCALE = "languages.forceLocale";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the list of locales that the user may select. There should be a
|
||||||
|
* national flag or symbol available for each supported locale.
|
||||||
|
*/
|
||||||
|
public static final String PROPERTY_SELECTABLE_LOCALES = "languages.selectableLocales";
|
||||||
|
|
||||||
|
private ServletContext ctx;
|
||||||
|
private StartupStatus ss;
|
||||||
|
private ConfigurationProperties props;
|
||||||
|
|
||||||
|
private String forceString;
|
||||||
|
private String selectableString;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
ctx = sce.getServletContext();
|
||||||
|
ss = StartupStatus.getBean(ctx);
|
||||||
|
props = ConfigurationProperties.getBean(sce);
|
||||||
|
|
||||||
|
readProperties();
|
||||||
|
|
||||||
|
if (isForcing() && hasSelectables()) {
|
||||||
|
warnAboutOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isForcing()) {
|
||||||
|
forceLocale();
|
||||||
|
} else if (hasSelectables()) {
|
||||||
|
setUpSelections();
|
||||||
|
} else {
|
||||||
|
reportNoLocales();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readProperties() {
|
||||||
|
forceString = props.getProperty(PROPERTY_FORCE_LOCALE, "");
|
||||||
|
selectableString = props.getProperty(PROPERTY_SELECTABLE_LOCALES, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isForcing() {
|
||||||
|
return StringUtils.isNotBlank(forceString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasSelectables() {
|
||||||
|
return StringUtils.isNotBlank(selectableString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void warnAboutOverride() {
|
||||||
|
ss.warning(this, "'" + PROPERTY_FORCE_LOCALE + "' will override '"
|
||||||
|
+ PROPERTY_SELECTABLE_LOCALES + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void forceLocale() {
|
||||||
|
try {
|
||||||
|
Locale forceLocale = buildLocale(forceString);
|
||||||
|
SelectedLocale.setForcedLocale(ctx, forceLocale);
|
||||||
|
ssInfo("Setting forced locale to '" + forceLocale + "'.");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
ssWarning("Problem in '" + PROPERTY_FORCE_LOCALE + "': "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpSelections() {
|
||||||
|
List<Locale> locales = new ArrayList<Locale>();
|
||||||
|
for (String string : splitSelectables()) {
|
||||||
|
try {
|
||||||
|
locales.add(buildLocale(string));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
ssWarning("Problem in '" + PROPERTY_SELECTABLE_LOCALES + "': "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedLocale.setSelectableLocales(ctx, locales);
|
||||||
|
ssInfo("Setting selectable locales to '" + locales + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] splitSelectables() {
|
||||||
|
return selectableString.split("\\s*,\\s*");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reportNoLocales() {
|
||||||
|
ssInfo("There is no Locale information.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ssInfo(String message) {
|
||||||
|
ss.info(this, message + showPropertyValues());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ssWarning(String message) {
|
||||||
|
ss.warning(this, message + showPropertyValues());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String showPropertyValues() {
|
||||||
|
return " In runtime.properties, '" + PROPERTY_FORCE_LOCALE
|
||||||
|
+ "' is set to '" + forceString + "', '"
|
||||||
|
+ PROPERTY_SELECTABLE_LOCALES + "' is set to '"
|
||||||
|
+ selectableString + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Locale buildLocale(String localeString)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
Locale locale = LocaleUtils.toLocale(localeString);
|
||||||
|
|
||||||
|
if (!LocaleUtils.isAvailableLocale(locale)) {
|
||||||
|
ssWarning("'" + locale + "' is not a recognized locale.");
|
||||||
|
}
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent arg0) {
|
||||||
|
// Nothing to do at shutdown.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some static methods for the GUI aspects of selecting a Locale.
|
||||||
|
*/
|
||||||
|
public class LocaleSelectorUtilities {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(LocaleSelectorUtilities.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look in the current theme directory to find a selection image for this
|
||||||
|
* Locale.
|
||||||
|
*
|
||||||
|
* Images are expected at a resource path like
|
||||||
|
* /[themeDir]/i18n/images/select_locale_[locale_code].*
|
||||||
|
*
|
||||||
|
* For example, /themes/wilma/i18n/images/select_locale_en.png
|
||||||
|
* /themes/wilma/i18n/images/select_locale_en.JPEG
|
||||||
|
* /themes/wilma/i18n/images/select_locale_en.gif
|
||||||
|
*
|
||||||
|
* To create a proper URL, prepend the context path.
|
||||||
|
*/
|
||||||
|
public static String getImageUrl(VitroRequest vreq, Locale locale)
|
||||||
|
throws FileNotFoundException {
|
||||||
|
String filename = "select_locale_" + locale + ".";
|
||||||
|
|
||||||
|
String themeDir = vreq.getAppBean().getThemeDir();
|
||||||
|
String imageDirPath = "/" + themeDir + "i18n/images/";
|
||||||
|
|
||||||
|
ServletContext ctx = vreq.getSession().getServletContext();
|
||||||
|
for (Object o : ctx.getResourcePaths(imageDirPath)) {
|
||||||
|
String resourcePath = (String) o;
|
||||||
|
if (resourcePath.contains(filename)) {
|
||||||
|
String fullPath = vreq.getContextPath() + resourcePath;
|
||||||
|
log.debug("Found image for " + locale + " at '" + fullPath
|
||||||
|
+ "'");
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new FileNotFoundException("Can't find an image for " + locale);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class for storing and retrieving Locale information.
|
||||||
|
*
|
||||||
|
* The static methods create beans and store them in the ServletContext or the
|
||||||
|
* session, where the information can be found later.
|
||||||
|
*/
|
||||||
|
public abstract class SelectedLocale {
|
||||||
|
private static final Log log = LogFactory.getLog(SelectedLocale.class);
|
||||||
|
|
||||||
|
/** Use this attribute on both the ServletContext and the Session. */
|
||||||
|
protected static final String ATTRIBUTE_NAME = "SELECTED_LOCALE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the forced locale in the servlet context. Clear any selectable
|
||||||
|
* Locales.
|
||||||
|
*/
|
||||||
|
public static void setForcedLocale(ServletContext ctx, Locale forcedLocale) {
|
||||||
|
log.debug("Set forced locale: " + forcedLocale);
|
||||||
|
ctx.setAttribute(ATTRIBUTE_NAME,
|
||||||
|
new ContextSelectedLocale(forcedLocale));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the selected locale in the current session.
|
||||||
|
*/
|
||||||
|
public static void setSelectedLocale(HttpServletRequest req,
|
||||||
|
Locale selectedLocale) {
|
||||||
|
log.debug("Set selected locale: " + selectedLocale);
|
||||||
|
req.getSession().setAttribute(ATTRIBUTE_NAME,
|
||||||
|
new SessionSelectedLocale(selectedLocale));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we need to override the Locale in the current request? return the
|
||||||
|
* first of these to be found:
|
||||||
|
* <ul>
|
||||||
|
* <li>The forced Locale in the servlet context</li>
|
||||||
|
* <li>The selected Locale in the session</li>
|
||||||
|
* <li>null</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static Locale getOverridingLocale(HttpServletRequest req) {
|
||||||
|
HttpSession session = req.getSession();
|
||||||
|
ServletContext ctx = session.getServletContext();
|
||||||
|
|
||||||
|
Object ctxInfo = ctx.getAttribute(ATTRIBUTE_NAME);
|
||||||
|
if (ctxInfo instanceof ContextSelectedLocale) {
|
||||||
|
Locale forcedLocale = ((ContextSelectedLocale) ctxInfo)
|
||||||
|
.getForcedLocale();
|
||||||
|
if (forcedLocale != null) {
|
||||||
|
log.debug("Found forced locale in the context: " + forcedLocale);
|
||||||
|
return forcedLocale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object sessionInfo = session.getAttribute(ATTRIBUTE_NAME);
|
||||||
|
if (sessionInfo instanceof SessionSelectedLocale) {
|
||||||
|
Locale selectedLocale = ((SessionSelectedLocale) sessionInfo)
|
||||||
|
.getSelectedLocale();
|
||||||
|
if (selectedLocale != null) {
|
||||||
|
log.debug("Found selected locale in the session: "
|
||||||
|
+ selectedLocale);
|
||||||
|
return selectedLocale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current Locale to use, which is the first of these to be found:
|
||||||
|
* <ul>
|
||||||
|
* <li>The forced Locale in the servlet context</li>
|
||||||
|
* <li>The selected Locale in the session</li>
|
||||||
|
* <li>The Locale from the request</li>
|
||||||
|
* <li>The default Locale for the JVM</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static Locale getCurrentLocale(HttpServletRequest req) {
|
||||||
|
Locale overridingLocale = getOverridingLocale(req);
|
||||||
|
|
||||||
|
if (overridingLocale != null) {
|
||||||
|
return overridingLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale requestLocale = req.getLocale();
|
||||||
|
if (requestLocale != null) {
|
||||||
|
log.debug("Found locale in the request: " + requestLocale);
|
||||||
|
return requestLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Using default locale: " + Locale.getDefault());
|
||||||
|
return Locale.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a list of selectable Locales in the servlet context, so we can
|
||||||
|
* easily build the selection panel in the GUI. Clears any forced locale.
|
||||||
|
*/
|
||||||
|
public static void setSelectableLocales(ServletContext ctx,
|
||||||
|
List<Locale> selectableLocales) {
|
||||||
|
log.debug("Setting selectable locales: " + selectableLocales);
|
||||||
|
ctx.setAttribute(ATTRIBUTE_NAME, new ContextSelectedLocale(
|
||||||
|
selectableLocales));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of selectable Locales from the servlet context. May return
|
||||||
|
* an empty list, but never returns null.
|
||||||
|
*/
|
||||||
|
public static List<Locale> getSelectableLocales(HttpServletRequest req) {
|
||||||
|
ServletContext ctx = req.getSession().getServletContext();
|
||||||
|
Object ctxInfo = ctx.getAttribute(ATTRIBUTE_NAME);
|
||||||
|
if (ctxInfo instanceof ContextSelectedLocale) {
|
||||||
|
List<Locale> selectableLocales = ((ContextSelectedLocale) ctxInfo)
|
||||||
|
.getSelectableLocales();
|
||||||
|
if (selectableLocales != null) {
|
||||||
|
log.debug("Returning selectable locales: " + selectableLocales);
|
||||||
|
return selectableLocales;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("No selectable locales were found. Returning an empty list.");
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Bean classes
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Holds Locale information in the ServletContext. */
|
||||||
|
protected static class ContextSelectedLocale {
|
||||||
|
// Only one of these is populated.
|
||||||
|
private final Locale forcedLocale;
|
||||||
|
private final List<Locale> selectableLocales;
|
||||||
|
|
||||||
|
public ContextSelectedLocale(Locale forcedLocale) {
|
||||||
|
if (forcedLocale == null) {
|
||||||
|
throw new NullPointerException("forcedLocale may not be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.forcedLocale = forcedLocale;
|
||||||
|
this.selectableLocales = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContextSelectedLocale(List<Locale> selectableLocales) {
|
||||||
|
if (selectableLocales == null) {
|
||||||
|
selectableLocales = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.forcedLocale = null;
|
||||||
|
this.selectableLocales = selectableLocales;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Locale getForcedLocale() {
|
||||||
|
return forcedLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Locale> getSelectableLocales() {
|
||||||
|
return selectableLocales;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ContextSelectedLocale[forced=" + forcedLocale
|
||||||
|
+ ", selectable=" + selectableLocales + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds Locale information in the Session. */
|
||||||
|
protected static class SessionSelectedLocale {
|
||||||
|
private final Locale selectedLocale;
|
||||||
|
|
||||||
|
public SessionSelectedLocale(Locale selectedLocale) {
|
||||||
|
this.selectedLocale = selectedLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Locale getSelectedLocale() {
|
||||||
|
return selectedLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SessionSelectedLocale[" + selectedLocale + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,6 @@ import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
@ -43,23 +42,17 @@ public class LanguageFilteringRDFService implements RDFService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> normalizeLangs(List<String> langs) {
|
private List<String> normalizeLangs(List<String> langs) {
|
||||||
List<String> normalizedLangs = new ArrayList<String>();
|
log.debug("Preferred languages:" + langs);
|
||||||
String currentBaseLang = null;
|
|
||||||
|
List<String> normalizedLangs = new ArrayList<String>(langs);
|
||||||
for (String lang : langs) {
|
for (String lang : langs) {
|
||||||
String normalizedLang = StringUtils.lowerCase(lang);
|
String baseLang = lang.split("-")[0];
|
||||||
String baseLang = normalizedLang.split("-")[0];
|
if (!normalizedLangs.contains(baseLang)) {
|
||||||
if (currentBaseLang == null) {
|
normalizedLangs.add(baseLang);
|
||||||
currentBaseLang = baseLang;
|
|
||||||
} else if (!currentBaseLang.equals(baseLang)) {
|
|
||||||
if (!normalizedLangs.contains(currentBaseLang)) {
|
|
||||||
normalizedLangs.add(currentBaseLang);
|
|
||||||
}
|
|
||||||
currentBaseLang = baseLang;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentBaseLang != null && !normalizedLangs.contains(currentBaseLang)) {
|
|
||||||
normalizedLangs.add(currentBaseLang);
|
log.debug("Normalized languages:" + normalizedLangs);
|
||||||
}
|
|
||||||
return normalizedLangs;
|
return normalizedLangs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +99,7 @@ public class LanguageFilteringRDFService implements RDFService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Model filterModel(Model m) {
|
private Model filterModel(Model m) {
|
||||||
|
log.debug("filterModel");
|
||||||
List<Statement> retractions = new ArrayList<Statement>();
|
List<Statement> retractions = new ArrayList<Statement>();
|
||||||
StmtIterator stmtIt = m.listStatements();
|
StmtIterator stmtIt = m.listStatements();
|
||||||
while (stmtIt.hasNext()) {
|
while (stmtIt.hasNext()) {
|
||||||
|
@ -117,6 +111,7 @@ public class LanguageFilteringRDFService implements RDFService {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Collections.sort(candidatesForRemoval, new StatementSortByLang());
|
Collections.sort(candidatesForRemoval, new StatementSortByLang());
|
||||||
|
log.debug("sorted statements: " + showSortedStatements(candidatesForRemoval));
|
||||||
Iterator<Statement> candIt = candidatesForRemoval.iterator();
|
Iterator<Statement> candIt = candidatesForRemoval.iterator();
|
||||||
String langRegister = null;
|
String langRegister = null;
|
||||||
boolean chuckRemaining = false;
|
boolean chuckRemaining = false;
|
||||||
|
@ -142,9 +137,27 @@ public class LanguageFilteringRDFService implements RDFService {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String showSortedStatements(List<Statement> candidatesForRemoval) {
|
||||||
|
List<String> langStrings = new ArrayList<String>();
|
||||||
|
for (Statement stmt: candidatesForRemoval) {
|
||||||
|
if (stmt == null) {
|
||||||
|
langStrings.add("null stmt");
|
||||||
|
} else {
|
||||||
|
RDFNode node = stmt.getObject();
|
||||||
|
if (!node.isLiteral()) {
|
||||||
|
langStrings.add("not literal");
|
||||||
|
} else {
|
||||||
|
langStrings.add(node.asLiteral().getLanguage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return langStrings.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream sparqlSelectQuery(String query,
|
public InputStream sparqlSelectQuery(String query,
|
||||||
ResultFormat resultFormat) throws RDFServiceException {
|
ResultFormat resultFormat) throws RDFServiceException {
|
||||||
|
log.debug("sparqlSelectQuery: " + query.replaceAll("\\s+", " "));
|
||||||
ResultSet resultSet = ResultSetFactory.fromJSON(
|
ResultSet resultSet = ResultSetFactory.fromJSON(
|
||||||
s.sparqlSelectQuery(query, RDFService.ResultFormat.JSON));
|
s.sparqlSelectQuery(query, RDFService.ResultFormat.JSON));
|
||||||
List<QuerySolution> solnList = getSolutionList(resultSet);
|
List<QuerySolution> solnList = getSolutionList(resultSet);
|
||||||
|
@ -178,6 +191,7 @@ public class LanguageFilteringRDFService implements RDFService {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Collections.sort(candidatesForRemoval, new RowIndexedLiteralSortByLang());
|
Collections.sort(candidatesForRemoval, new RowIndexedLiteralSortByLang());
|
||||||
|
log.debug("sorted RowIndexedLiterals: " + showSortedRILs(candidatesForRemoval));
|
||||||
Iterator<RowIndexedLiteral> candIt = candidatesForRemoval.iterator();
|
Iterator<RowIndexedLiteral> candIt = candidatesForRemoval.iterator();
|
||||||
String langRegister = null;
|
String langRegister = null;
|
||||||
boolean chuckRemaining = false;
|
boolean chuckRemaining = false;
|
||||||
|
@ -223,6 +237,14 @@ public class LanguageFilteringRDFService implements RDFService {
|
||||||
return new ByteArrayInputStream(outputStream.toByteArray());
|
return new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String showSortedRILs(List<RowIndexedLiteral> candidatesForRemoval) {
|
||||||
|
List<String> langstrings = new ArrayList<String>();
|
||||||
|
for (RowIndexedLiteral ril: candidatesForRemoval) {
|
||||||
|
langstrings.add(ril.getLiteral().getLanguage());
|
||||||
|
}
|
||||||
|
return langstrings.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private class RowIndexedLiteral {
|
private class RowIndexedLiteral {
|
||||||
|
|
||||||
private Literal literal;
|
private Literal literal;
|
||||||
|
@ -324,37 +346,44 @@ public class LanguageFilteringRDFService implements RDFService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LangSort {
|
private class LangSort {
|
||||||
|
// any inexact match is worse than any exact match
|
||||||
|
private int inexactMatchPenalty = langs.size();
|
||||||
|
// no language is worse than any inexact match (if the preferred list does not include "").
|
||||||
|
private int noLanguage = 2 * inexactMatchPenalty;
|
||||||
|
// no match is worse than no language.
|
||||||
|
private int noMatch = noLanguage + 1;
|
||||||
|
|
||||||
protected int compareLangs(String t1lang, String t2lang) {
|
protected int compareLangs(String t1lang, String t2lang) {
|
||||||
t1lang = StringUtils.lowerCase(t1lang);
|
return languageIndex(t1lang) - languageIndex(t2lang);
|
||||||
t2lang = StringUtils.lowerCase(t2lang);
|
|
||||||
if ( t1lang == null && t2lang == null) {
|
|
||||||
return 0;
|
|
||||||
} else if (t1lang == null) {
|
|
||||||
return 1;
|
|
||||||
} else if (t2lang == null) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
int t1langPref = langs.indexOf(t1lang);
|
|
||||||
int t2langPref = langs.indexOf(t2lang);
|
|
||||||
if (t1langPref == -1 && t2langPref == -1) {
|
|
||||||
if ("".equals(t1lang) && "".equals(t2lang)) {
|
|
||||||
return 0;
|
|
||||||
} else if ("".equals(t1lang) && !("".equals(t2lang))) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
} else if (t1langPref > -1 && t2langPref == -1) {
|
|
||||||
return -1;
|
/**
|
||||||
} else if (t1langPref == -1 && t2langPref > -1) {
|
* Return index of exact match, or index of partial match, or
|
||||||
return 1;
|
* language-free, or no match.
|
||||||
} else {
|
*/
|
||||||
return t1langPref - t2langPref;
|
private int languageIndex(String lang) {
|
||||||
|
if (lang == null) {
|
||||||
|
lang = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int index = langs.indexOf(lang);
|
||||||
|
if (index >= 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lang.length() > 2) {
|
||||||
|
index = langs.indexOf(lang.substring(0, 2));
|
||||||
|
if (index >= 0) {
|
||||||
|
return index + inexactMatchPenalty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lang.isEmpty()) {
|
||||||
|
return noLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return noMatch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RowIndexedLiteralSortByLang extends LangSort implements Comparator<RowIndexedLiteral> {
|
private class RowIndexedLiteralSortByLang extends LangSort implements Comparator<RowIndexedLiteral> {
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class SolrSetup implements javax.servlet.ServletContextListener{
|
||||||
/* setup the http connection with the solr server */
|
/* setup the http connection with the solr server */
|
||||||
String solrServerUrlString = ConfigurationProperties.getBean(sce).getProperty("vitro.local.solr.url");
|
String solrServerUrlString = ConfigurationProperties.getBean(sce).getProperty("vitro.local.solr.url");
|
||||||
if( solrServerUrlString == null ){
|
if( solrServerUrlString == null ){
|
||||||
ss.fatal(this, "Could not find vitro.local.solr.url in deploy.properties. "+
|
ss.fatal(this, "Could not find vitro.local.solr.url in runtime.properties. "+
|
||||||
"Vitro application needs a URL of a solr server that it can use to index its data. " +
|
"Vitro application needs a URL of a solr server that it can use to index its data. " +
|
||||||
"It should be something like http://localhost:${port}" + context.getContextPath() + "solr"
|
"It should be something like http://localhost:${port}" + context.getContextPath() + "solr"
|
||||||
);
|
);
|
||||||
|
@ -102,7 +102,7 @@ public class SolrSetup implements javax.servlet.ServletContextListener{
|
||||||
solrServerUrl = new URL(solrServerUrlString);
|
solrServerUrl = new URL(solrServerUrlString);
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
ss.fatal(this, "Can't connect with the solr server. " +
|
ss.fatal(this, "Can't connect with the solr server. " +
|
||||||
"The value for vitro.local.solr.url in deploy.properties is not a valid URL: " + solrServerUrlString);
|
"The value for vitro.local.solr.url in runtime.properties is not a valid URL: " + solrServerUrlString);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class ContextNodeFields implements DocumentModifier{
|
||||||
ResultSet results = RDFServiceUtils.sparqlSelectQuery(subInUriQuery, rdfService);
|
ResultSet results = RDFServiceUtils.sparqlSelectQuery(subInUriQuery, rdfService);
|
||||||
while(results.hasNext()){
|
while(results.hasNext()){
|
||||||
valuesForQuery.append(
|
valuesForQuery.append(
|
||||||
getTextForRow( results.nextSolution() ) ) ;
|
getTextForRow( results.nextSolution(), true ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch(Throwable t){
|
}catch(Throwable t){
|
||||||
|
@ -114,7 +114,7 @@ public class ContextNodeFields implements DocumentModifier{
|
||||||
return allValues;
|
return allValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getTextForRow( QuerySolution row){
|
protected String getTextForRow( QuerySolution row, boolean addSpace){
|
||||||
if( row == null )
|
if( row == null )
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
|
@ -124,7 +124,11 @@ public class ContextNodeFields implements DocumentModifier{
|
||||||
String name = iter.next();
|
String name = iter.next();
|
||||||
RDFNode node = row.get( name );
|
RDFNode node = row.get( name );
|
||||||
if( node != null ){
|
if( node != null ){
|
||||||
|
if(addSpace) {
|
||||||
text.append(" ").append( node.toString() );
|
text.append(" ").append( node.toString() );
|
||||||
|
} else {
|
||||||
|
text.append(node.toString());
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
log.debug(name + " is null");
|
log.debug(name + " is null");
|
||||||
}
|
}
|
||||||
|
@ -132,7 +136,6 @@ public class ContextNodeFields implements DocumentModifier{
|
||||||
return text.toString();
|
return text.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void shutdown(){
|
public void shutdown(){
|
||||||
shutdown=true;
|
shutdown=true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -546,7 +546,7 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon {
|
||||||
if ((dns != null) && (!dns.isEmpty())) {
|
if ((dns != null) && (!dns.isEmpty())) {
|
||||||
return dns;
|
return dns;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("deploy.properties does not "
|
throw new IllegalStateException("runtime.properties does not "
|
||||||
+ "contain a value for '" + VITRO_DEFAULT_NAMESPACE + "'");
|
+ "contain a value for '" + VITRO_DEFAULT_NAMESPACE + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class SolrSmokeTest implements ServletContextListener {
|
||||||
.getProperty("vitro.local.solr.url", "");
|
.getProperty("vitro.local.solr.url", "");
|
||||||
if (solrUrlString.isEmpty()) {
|
if (solrUrlString.isEmpty()) {
|
||||||
ss.fatal(this, "Can't connect to Solr search engine. "
|
ss.fatal(this, "Can't connect to Solr search engine. "
|
||||||
+ "deploy.properties must contain a value for "
|
+ "runtime.properties must contain a value for "
|
||||||
+ "vitro.local.solr.url");
|
+ "vitro.local.solr.url");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class SolrSmokeTest implements ServletContextListener {
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
ss.fatal(this, "Can't connect to Solr search engine. "
|
ss.fatal(this, "Can't connect to Solr search engine. "
|
||||||
+ "The value for vitro.local.solr.url "
|
+ "The value for vitro.local.solr.url "
|
||||||
+ "in deploy.properties is not a valid URL: '"
|
+ "in runtime.properties is not a valid URL: '"
|
||||||
+ solrUrlString + "'", e);
|
+ solrUrlString + "'", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,9 +124,7 @@ public class SolrSmokeTest implements ServletContextListener {
|
||||||
int status = e.getStatusCode();
|
int status = e.getStatusCode();
|
||||||
Throwable cause = e.getCause();
|
Throwable cause = e.getCause();
|
||||||
|
|
||||||
if (status == HttpStatus.SC_FORBIDDEN) {
|
if (status == SOCKET_TIMEOUT_STATUS) {
|
||||||
warnForbidden();
|
|
||||||
} else if (status == SOCKET_TIMEOUT_STATUS) {
|
|
||||||
warnSocketTimeout();
|
warnSocketTimeout();
|
||||||
} else if (status != 0) {
|
} else if (status != 0) {
|
||||||
warnBadHttpStatus(status);
|
warnBadHttpStatus(status);
|
||||||
|
@ -151,23 +149,14 @@ public class SolrSmokeTest implements ServletContextListener {
|
||||||
ss.warning(listener, "Can't connect to the Solr search engine. "
|
ss.warning(listener, "Can't connect to the Solr search engine. "
|
||||||
+ "The socket connection has repeatedly timed out. "
|
+ "The socket connection has repeatedly timed out. "
|
||||||
+ "Check the value of vitro.local.solr.url in "
|
+ "Check the value of vitro.local.solr.url in "
|
||||||
+ "deploy.properties. Is Solr responding at that URL?");
|
+ "runtime.properties. Is Solr responding at that URL?");
|
||||||
}
|
|
||||||
|
|
||||||
private void warnForbidden() {
|
|
||||||
ss.warning(listener, "Can't connect to the Solr search engine. "
|
|
||||||
+ "The Solr server will not accept connections from this "
|
|
||||||
+ "host. Check the value of "
|
|
||||||
+ "vitro.local.solr.ipaddress.mask in "
|
|
||||||
+ "deploy.properties -- "
|
|
||||||
+ "does it authorize access from this IP address?");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void warnBadHttpStatus(int status) {
|
private void warnBadHttpStatus(int status) {
|
||||||
ss.warning(listener, "Can't connect to the Solr search engine. "
|
ss.warning(listener, "Can't connect to the Solr search engine. "
|
||||||
+ "The Solr server returned a status code of " + status
|
+ "The Solr server returned a status code of " + status
|
||||||
+ ". Check the value of vitro.local.solr.url in "
|
+ ". Check the value of vitro.local.solr.url in "
|
||||||
+ "deploy.properties.");
|
+ "runtime.properties.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void warnProtocolViolation(HttpException e) {
|
private void warnProtocolViolation(HttpException e) {
|
||||||
|
@ -179,7 +168,7 @@ public class SolrSmokeTest implements ServletContextListener {
|
||||||
ss.warning(listener, "Can't connect to the Solr search engine. '"
|
ss.warning(listener, "Can't connect to the Solr search engine. '"
|
||||||
+ e.getMessage() + "' is an unknown host."
|
+ e.getMessage() + "' is an unknown host."
|
||||||
+ "Check the value of vitro.local.solr.url in "
|
+ "Check the value of vitro.local.solr.url in "
|
||||||
+ "deploy.properties.", e);
|
+ "runtime.properties.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void warnConnectionRefused(ConnectException e) {
|
private void warnConnectionRefused(ConnectException e) {
|
||||||
|
@ -187,7 +176,7 @@ public class SolrSmokeTest implements ServletContextListener {
|
||||||
+ "The host refused the connection. "
|
+ "The host refused the connection. "
|
||||||
+ "Is it possible that the port number is incorrect? "
|
+ "Is it possible that the port number is incorrect? "
|
||||||
+ "Check the value of vitro.local.solr.url in "
|
+ "Check the value of vitro.local.solr.url in "
|
||||||
+ "deploy.properties.", e);
|
+ "runtime.properties.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void warnTransportError(IOException e) {
|
private void warnTransportError(IOException e) {
|
||||||
|
|
|
@ -182,10 +182,10 @@ public class UpdatePermissionSetUris implements ServletContextListener {
|
||||||
|
|
||||||
Journal(ServletContext ctx) throws IOException {
|
Journal(ServletContext ctx) throws IOException {
|
||||||
String homeDirectoryPath = ConfigurationProperties.getBean(ctx)
|
String homeDirectoryPath = ConfigurationProperties.getBean(ctx)
|
||||||
.getProperty("vitro.home.directory");
|
.getProperty("vitro.home");
|
||||||
if (homeDirectoryPath == null) {
|
if (homeDirectoryPath == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"No value found for vitro.home.directory");
|
"No value found for vitro.home");
|
||||||
}
|
}
|
||||||
File homeDirectory = new File(homeDirectoryPath);
|
File homeDirectory = new File(homeDirectoryPath);
|
||||||
confirmIsDirectory(homeDirectory);
|
confirmIsDirectory(homeDirectory);
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
public class StartupStatus {
|
public class StartupStatus {
|
||||||
private static final Log log = LogFactory.getLog(StartupStatus.class);
|
private static final Log log = LogFactory.getLog(StartupStatus.class);
|
||||||
|
|
||||||
private static final String ATTRIBUTE_NAME = "STARTUP_STATUS";
|
protected static final String ATTRIBUTE_NAME = "STARTUP_STATUS";
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// static methods
|
// static methods
|
||||||
|
|
|
@ -59,37 +59,56 @@ public class DataGetterUtils {
|
||||||
* This should not return PageDataGetters and should not throw an
|
* This should not return PageDataGetters and should not throw an
|
||||||
* exception if a page has PageDataGetters.
|
* exception if a page has PageDataGetters.
|
||||||
*/
|
*/
|
||||||
public static List<DataGetter> getDataGettersForPage( VitroRequest vreq, Model displayModel, String pageURI)
|
public static List<DataGetter> getDataGettersForPage(VitroRequest vreq, Model displayModel, String pageURI)
|
||||||
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{
|
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException {
|
||||||
//get data getter uris for pageURI
|
List<String> dgUris = getDataGetterURIsForAssociatedURI(displayModel, pageURI);
|
||||||
List<String> dgUris = getDataGetterURIsForPageURI( displayModel, pageURI);
|
List<DataGetter> dgList = dataGettersForURIs(vreq, displayModel, dgUris);
|
||||||
|
|
||||||
List<DataGetter> dgList = new ArrayList<DataGetter>();
|
|
||||||
for( String dgURI: dgUris){
|
|
||||||
DataGetter dg =dataGetterForURI(vreq, displayModel, dgURI) ;
|
|
||||||
if( dg != null )
|
|
||||||
dgList.add(dg);
|
|
||||||
}
|
|
||||||
log.debug("getDataGettersForPage: " + dgList);
|
log.debug("getDataGettersForPage: " + dgList);
|
||||||
return dgList;
|
return dgList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of DataGetter objects that are associated with a JAVA class.
|
* Get a list of DataGetter objects that are associated with a Vitro VClass.
|
||||||
* This allows the individual profile for an individual of a specific class to be returned .
|
* This allows the individual profile for an individual of a specific class to be returned .
|
||||||
*/
|
*/
|
||||||
public static List<DataGetter> getDataGettersForClass( VitroRequest vreq, Model displayModel, String classURI)
|
public static List<DataGetter> getDataGettersForClass( VitroRequest vreq, Model displayModel, String classURI)
|
||||||
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{
|
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{
|
||||||
//get data getter uris for pageURI
|
List<String> dgUris = getDataGetterURIsForAssociatedURI( displayModel, classURI);
|
||||||
List<String> dgUris = getDataGetterURIsForClassURI( displayModel, classURI);
|
List<DataGetter> dgList = dataGettersForURIs(vreq, displayModel, dgUris);
|
||||||
|
log.debug("getDataGettersForClass: " + dgList);
|
||||||
|
return dgList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of DataGetter objects that are associated with a Freemarker template.
|
||||||
|
* @param templateName a filename like "index.ftl", which will be used as a URI like "freemarker:index.ftl".
|
||||||
|
*/
|
||||||
|
public static List<DataGetter> getDataGettersForTemplate( VitroRequest vreq, Model displayModel, String templateName)
|
||||||
|
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{
|
||||||
|
String templateUri = "freemarker:" + templateName;
|
||||||
|
List<String> dgUris = getDataGetterURIsForAssociatedURI( displayModel, templateUri);
|
||||||
|
List<DataGetter> dgList = dataGettersForURIs(vreq, displayModel, dgUris);
|
||||||
|
log.debug("getDataGettersForTemplate '" + templateName + "': " + dgList);
|
||||||
|
return dgList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of DataGetters from the list of URIs. Each DataGetter will be configured from information
|
||||||
|
* in the displayModel.
|
||||||
|
*
|
||||||
|
* Problems instantiating and configuring a particular DataGetter may result in an exception,
|
||||||
|
* or may just mean that there will be no entry in the result for that URI.
|
||||||
|
*
|
||||||
|
* May return an empty list, but will not return null.
|
||||||
|
*/
|
||||||
|
private static List<DataGetter> dataGettersForURIs(VitroRequest vreq, Model displayModel, List<String> dgUris)
|
||||||
|
throws InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException {
|
||||||
List<DataGetter> dgList = new ArrayList<DataGetter>();
|
List<DataGetter> dgList = new ArrayList<DataGetter>();
|
||||||
for( String dgURI: dgUris){
|
for( String dgURI: dgUris){
|
||||||
DataGetter dg =dataGetterForURI(vreq, displayModel, dgURI) ;
|
DataGetter dg =dataGetterForURI(vreq, displayModel, dgURI) ;
|
||||||
if( dg != null )
|
if( dg != null )
|
||||||
dgList.add(dg);
|
dgList.add(dg);
|
||||||
}
|
}
|
||||||
log.debug("getDataGettersForClass: " + dgList);
|
|
||||||
return dgList;
|
return dgList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +122,7 @@ public class DataGetterUtils {
|
||||||
* that does not implement the DataGetter interface.
|
* that does not implement the DataGetter interface.
|
||||||
*/
|
*/
|
||||||
public static DataGetter dataGetterForURI(VitroRequest vreq, Model displayModel, String dataGetterURI)
|
public static DataGetter dataGetterForURI(VitroRequest vreq, Model displayModel, String dataGetterURI)
|
||||||
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchMethodException
|
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, SecurityException
|
||||||
{
|
{
|
||||||
//get java class for dataGetterURI
|
//get java class for dataGetterURI
|
||||||
String dgClassName = getJClassForDataGetterURI(displayModel, dataGetterURI);
|
String dgClassName = getJClassForDataGetterURI(displayModel, dataGetterURI);
|
||||||
|
@ -180,47 +199,18 @@ public class DataGetterUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static List<String> getDataGetterURIsForPageURI(Model displayModel, String pageURI) {
|
private static List<String> getDataGetterURIsForAssociatedURI(Model displayModel, String associatedURI) {
|
||||||
String query = prefixes +
|
String query = prefixes +
|
||||||
"SELECT ?dataGetter WHERE { ?pageURI display:hasDataGetter ?dataGetter. }";
|
"SELECT ?dataGetter WHERE { ?associatedURI display:hasDataGetter ?dataGetter }";
|
||||||
Query dgForPageQuery = QueryFactory.create(query);
|
Query dgForUriQuery = QueryFactory.create(query);
|
||||||
|
|
||||||
QuerySolutionMap initialBindings = new QuerySolutionMap();
|
QuerySolutionMap initialBindings = new QuerySolutionMap();
|
||||||
initialBindings.add("pageURI", ResourceFactory.createResource( pageURI ));
|
initialBindings.add("associatedURI", ResourceFactory.createResource( associatedURI ));
|
||||||
|
|
||||||
List<String> dgURIs = new ArrayList<String>();
|
List<String> dgURIs = new ArrayList<String>();
|
||||||
displayModel.enterCriticalSection(false);
|
displayModel.enterCriticalSection(false);
|
||||||
try{
|
try{
|
||||||
QueryExecution qexec = QueryExecutionFactory.create(dgForPageQuery,displayModel,initialBindings );
|
QueryExecution qexec = QueryExecutionFactory.create(dgForUriQuery,displayModel,initialBindings );
|
||||||
try{
|
|
||||||
ResultSet results = qexec.execSelect();
|
|
||||||
while (results.hasNext()) {
|
|
||||||
QuerySolution soln = results.nextSolution();
|
|
||||||
Resource dg = soln.getResource("dataGetter");
|
|
||||||
if( dg != null && dg.getURI() != null){
|
|
||||||
dgURIs.add( dg.getURI());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}finally{ qexec.close(); }
|
|
||||||
}finally{ displayModel.leaveCriticalSection(); }
|
|
||||||
|
|
||||||
return dgURIs;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get data getters for a specific JAVA class - associates data getters with individuals for a specific JAVA class
|
|
||||||
private static List<String> getDataGetterURIsForClassURI(Model displayModel, String classURI) {
|
|
||||||
//Class URI will be substituted in so this is for a specific class uri
|
|
||||||
String query = prefixes +
|
|
||||||
"SELECT ?dataGetter WHERE { ?classURI display:hasDataGetter ?dataGetter }";
|
|
||||||
Query dgForPageQuery = QueryFactory.create(query);
|
|
||||||
|
|
||||||
QuerySolutionMap initialBindings = new QuerySolutionMap();
|
|
||||||
initialBindings.add("classURI", ResourceFactory.createResource( classURI ));
|
|
||||||
|
|
||||||
List<String> dgURIs = new ArrayList<String>();
|
|
||||||
displayModel.enterCriticalSection(false);
|
|
||||||
try{
|
|
||||||
QueryExecution qexec = QueryExecutionFactory.create(dgForPageQuery,displayModel,initialBindings );
|
|
||||||
try{
|
try{
|
||||||
ResultSet results = qexec.execSelect();
|
ResultSet results = qexec.execSelect();
|
||||||
while (results.hasNext()) {
|
while (results.hasNext()) {
|
||||||
|
@ -233,6 +223,7 @@ public class DataGetterUtils {
|
||||||
}finally{ qexec.close(); }
|
}finally{ qexec.close(); }
|
||||||
}finally{ displayModel.leaveCriticalSection(); }
|
}finally{ displayModel.leaveCriticalSection(); }
|
||||||
|
|
||||||
|
log.debug("Found " + dgURIs.size() +" DataGetter URIs for '" + associatedURI + "': " + dgURIs);
|
||||||
return dgURIs;
|
return dgURIs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -504,6 +505,7 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
|
||||||
|
|
||||||
|
|
||||||
//TODO:Check where this logic should actually go, copied from input element formatting tag
|
//TODO:Check where this logic should actually go, copied from input element formatting tag
|
||||||
|
//Updating to enable multiple vclasses applicable to subject to be analyzed to understand possible range of types
|
||||||
public Map<String, String> getOfferTypesCreateNew() {
|
public Map<String, String> getOfferTypesCreateNew() {
|
||||||
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
|
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
|
||||||
ObjectProperty op =
|
ObjectProperty op =
|
||||||
|
@ -513,9 +515,34 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
|
||||||
wdf.getIndividualDao().getIndividualByURI(editConfig.getSubjectUri());
|
wdf.getIndividualDao().getIndividualByURI(editConfig.getSubjectUri());
|
||||||
|
|
||||||
List<VClass> vclasses = null;
|
List<VClass> vclasses = null;
|
||||||
vclasses = wdf.getVClassDao().getVClassesForProperty(sub.getVClassURI(), op.getURI());
|
List<VClass> subjectVClasses = sub.getVClasses();
|
||||||
if( vclasses == null )
|
if( subjectVClasses == null ) {
|
||||||
vclasses = wdf.getVClassDao().getAllVclasses();
|
vclasses = wdf.getVClassDao().getAllVclasses();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//this hash is used to make sure there are no duplicates in the vclasses
|
||||||
|
//a more elegant method may look at overriding equals/hashcode to enable a single hashset of VClass objects
|
||||||
|
HashSet<String> vclassesURIs = new HashSet<String>();
|
||||||
|
vclasses = new ArrayList<VClass>();
|
||||||
|
//Get the range vclasses applicable for the property and each vclass for the subject
|
||||||
|
for(VClass subjectVClass: subjectVClasses) {
|
||||||
|
List<VClass> rangeVclasses = wdf.getVClassDao().getVClassesForProperty(subjectVClass.getURI(), op.getURI());
|
||||||
|
//add range vclass to hash
|
||||||
|
if(rangeVclasses != null) {
|
||||||
|
for(VClass v: rangeVclasses) {
|
||||||
|
if(!vclassesURIs.contains(v.getURI())) {
|
||||||
|
vclassesURIs.add(v.getURI());
|
||||||
|
vclasses.add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if each subject vclass resulted in null being returned for range vclasses, then size of vclasses would be zero
|
||||||
|
if(vclasses.size() == 0) {
|
||||||
|
vclasses = wdf.getVClassDao().getAllVclasses();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HashMap<String,String> types = new HashMap<String, String>();
|
HashMap<String,String> types = new HashMap<String, String>();
|
||||||
for( VClass vclass : vclasses ){
|
for( VClass vclass : vclasses ){
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class OpenSocialSmokeTests implements ServletContextListener {
|
||||||
configProps = ConfigurationProperties.getBean(ctx);
|
configProps = ConfigurationProperties.getBean(ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If OpenSocial is not configured in deploy.properties, skip the tests.
|
* If OpenSocial is not configured in runtime.properties, skip the tests.
|
||||||
*/
|
*/
|
||||||
if (!configurationPresent()) {
|
if (!configurationPresent()) {
|
||||||
ss.info(this, "The OpenSocial connection is not configured.");
|
ss.info(this, "The OpenSocial connection is not configured.");
|
||||||
|
@ -188,7 +188,7 @@ public class OpenSocialSmokeTests implements ServletContextListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the Token Key file has been specified in deploy.properties,
|
* Check that the Token Key file has been specified in runtime.properties,
|
||||||
* and that it actually does exist.
|
* and that it actually does exist.
|
||||||
*/
|
*/
|
||||||
private void checkTokenKeyFile() {
|
private void checkTokenKeyFile() {
|
||||||
|
@ -210,14 +210,14 @@ public class OpenSocialSmokeTests implements ServletContextListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Token Service info from deploy.properties. It must be in the form
|
* Get the Token Service info from runtime.properties. It must be in the form
|
||||||
* of host:port, and may not refer to localhost.
|
* of host:port, and may not refer to localhost.
|
||||||
*/
|
*/
|
||||||
private void checkTokenServiceInfo() {
|
private void checkTokenServiceInfo() {
|
||||||
String tsInfo = configProps.getProperty(PROPERTY_SHINDIG_TOKEN_SERVICE);
|
String tsInfo = configProps.getProperty(PROPERTY_SHINDIG_TOKEN_SERVICE);
|
||||||
if (StringUtils.isEmpty(tsInfo)) {
|
if (StringUtils.isEmpty(tsInfo)) {
|
||||||
warnings.add(new Warning("There is no value for '"
|
warnings.add(new Warning("There is no value for '"
|
||||||
+ PROPERTY_SHINDIG_TOKEN_SERVICE + "' in deploy.properties"));
|
+ PROPERTY_SHINDIG_TOKEN_SERVICE + "' in runtime.properties"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ public class OpenSocialSmokeTests implements ServletContextListener {
|
||||||
|
|
||||||
private static class NoSuchPropertyException extends Exception {
|
private static class NoSuchPropertyException extends Exception {
|
||||||
NoSuchPropertyException(String key) {
|
NoSuchPropertyException(String key) {
|
||||||
super("There is no value for '" + key + "' in deploy.properties");
|
super("There is no value for '" + key + "' in build.properties");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
308
webapp/test/edu/cornell/mannlib/vitro/webapp/WebXmlTest.java
Normal file
308
webapp/test/edu/cornell/mannlib/vitro/webapp/WebXmlTest.java
Normal file
|
@ -0,0 +1,308 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.xml.namespace.NamespaceContext;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.xpath.XPath;
|
||||||
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import javax.xml.xpath.XPathExpression;
|
||||||
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.io.filefilter.IOFileFilter;
|
||||||
|
import org.apache.commons.io.filefilter.NameFileFilter;
|
||||||
|
import org.apache.commons.io.filefilter.NotFileFilter;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see that web.xml doesn't include any constructs that are permitted
|
||||||
|
* by Tomcat but prohibited by the Servlet 2.4 Specification.
|
||||||
|
*
|
||||||
|
* These are things that might not be noticed when testing Vitro on Tomcat, but
|
||||||
|
* might show up as problems on other containers like GlassFish or WebLogic.
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* The contents of <dispatcher/> elements must be upper-case. Tomcat permits
|
||||||
|
* lower-case, but the specification does not.</li>
|
||||||
|
* <li>
|
||||||
|
* All <servlet-class/> tags must point to existing classes. Tomcat does not try
|
||||||
|
* to load a servlet until it is necessary to service a request, but WebLogic
|
||||||
|
* loads them on startup. Either method is permitted by the specification.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* As long as we're here, let's check some things that would cause Vitro to fail
|
||||||
|
* in any servlet container.
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* All <listener-class/> tags must point to existing classes.</li>
|
||||||
|
* <li>
|
||||||
|
* All <filter-class/> tags must point to existing classes.</li>
|
||||||
|
* <li>
|
||||||
|
* All <taglib-location/> tags must point to existing files.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@RunWith(value = Parameterized.class)
|
||||||
|
public class WebXmlTest extends AbstractTestClass {
|
||||||
|
private static final Log log = LogFactory.getLog(WebXmlTest.class);
|
||||||
|
|
||||||
|
@Parameters
|
||||||
|
public static Collection<Object[]> findWebXmlFiles() {
|
||||||
|
IOFileFilter fileFilter = new NameFileFilter("web.xml");
|
||||||
|
IOFileFilter dirFilter = new NotFileFilter(new NameFileFilter(".build"));
|
||||||
|
Collection<File> files = FileUtils.listFiles(new File("."), fileFilter,
|
||||||
|
dirFilter);
|
||||||
|
if (files.isEmpty()) {
|
||||||
|
System.out.println("WARNING: could not find web.xml");
|
||||||
|
} else {
|
||||||
|
if (files.size() > 1) {
|
||||||
|
System.out
|
||||||
|
.println("WARNING: testing more than one web.xml file: "
|
||||||
|
+ files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<Object[]> parameters = new ArrayList<Object[]>();
|
||||||
|
for (File file : files) {
|
||||||
|
parameters.add(new Object[] { file });
|
||||||
|
}
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DocumentBuilder docBuilder = createDocBuilder();
|
||||||
|
private static XPath xpath = createXPath();
|
||||||
|
|
||||||
|
private static DocumentBuilder createDocBuilder() {
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory
|
||||||
|
.newInstance();
|
||||||
|
factory.setNamespaceAware(true); // never forget this!
|
||||||
|
return factory.newDocumentBuilder();
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static XPath createXPath() {
|
||||||
|
XPath xp = XPathFactory.newInstance().newXPath();
|
||||||
|
xp.setNamespaceContext(new StupidNamespaceContext());
|
||||||
|
return xp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File webXmlFile;
|
||||||
|
private Document webXmlDoc;
|
||||||
|
private List<String> messages = new ArrayList<String>();
|
||||||
|
|
||||||
|
public WebXmlTest(File file) {
|
||||||
|
this.webXmlFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void parseWebXml() throws SAXException, IOException {
|
||||||
|
if (webXmlDoc == null) {
|
||||||
|
webXmlDoc = docBuilder.parse(webXmlFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkAll() throws IOException {
|
||||||
|
checkDispatcherValues();
|
||||||
|
checkServletClasses();
|
||||||
|
checkListenerClasses();
|
||||||
|
checkFilterClasses();
|
||||||
|
checkTaglibLocations();
|
||||||
|
|
||||||
|
if (!messages.isEmpty()) {
|
||||||
|
for (String message : messages) {
|
||||||
|
System.out.println(message);
|
||||||
|
}
|
||||||
|
fail("Found these problems with '" + webXmlFile.getCanonicalPath()
|
||||||
|
+ "'\n " + StringUtils.join(messages, "\n "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDispatcherValues() {
|
||||||
|
List<String> okValues = Arrays.asList(new String[] { "FORWARD",
|
||||||
|
"REQUEST", "INCLUDE", "ERROR" });
|
||||||
|
for (Node n : findNodes("//j2ee:dispatcher")) {
|
||||||
|
String text = n.getTextContent();
|
||||||
|
if (!okValues.contains(text)) {
|
||||||
|
messages.add("<dispatcher>" + text
|
||||||
|
+ "</dispatcher> is not valid. Acceptable values are "
|
||||||
|
+ okValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkServletClasses() {
|
||||||
|
for (Node n : findNodes("//j2ee:servlet-class")) {
|
||||||
|
String text = n.getTextContent();
|
||||||
|
String problem = confirmClassNameIsValid(text, HttpServlet.class);
|
||||||
|
if (problem != null) {
|
||||||
|
messages.add("<servlet-class>" + text
|
||||||
|
+ "</servlet-class> is not valid: " + problem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkListenerClasses() {
|
||||||
|
for (Node n : findNodes("//j2ee:listener-class")) {
|
||||||
|
String text = n.getTextContent();
|
||||||
|
String problem = confirmClassNameIsValid(text,
|
||||||
|
ServletContextListener.class);
|
||||||
|
if (problem != null) {
|
||||||
|
messages.add("<listener-class>" + text
|
||||||
|
+ "</listener-class> is not valid: " + problem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkFilterClasses() {
|
||||||
|
for (Node n : findNodes("//j2ee:filter-class")) {
|
||||||
|
String text = n.getTextContent();
|
||||||
|
String problem = confirmClassNameIsValid(text, Filter.class);
|
||||||
|
if (problem != null) {
|
||||||
|
messages.add("<filter-class>" + text
|
||||||
|
+ "</filter-class> is not valid: " + problem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTaglibLocations() {
|
||||||
|
// TODO Don't know how to do this one. Where do we look for the taglibs?
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Helper methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for an Xpath, returning a handy list.
|
||||||
|
*/
|
||||||
|
private List<Node> findNodes(String pattern) {
|
||||||
|
try {
|
||||||
|
XPathExpression xpe = xpath.compile(pattern);
|
||||||
|
NodeList nodes = (NodeList) xpe.evaluate(
|
||||||
|
webXmlDoc.getDocumentElement(), XPathConstants.NODESET);
|
||||||
|
List<Node> list = new ArrayList<Node>();
|
||||||
|
for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
|
list.add(nodes.item(i));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
} catch (XPathExpressionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the supplied className can be instantiated with a
|
||||||
|
* zero-argument constructor, and assigned to a variable of the target
|
||||||
|
* class.
|
||||||
|
*/
|
||||||
|
private String confirmClassNameIsValid(String className,
|
||||||
|
Class<?> targetClass) {
|
||||||
|
try {
|
||||||
|
Class<?> specifiedClass = Class.forName(className);
|
||||||
|
Object o = specifiedClass.newInstance();
|
||||||
|
if (!targetClass.isInstance(o)) {
|
||||||
|
return specifiedClass.getSimpleName()
|
||||||
|
+ " is not a subclass of "
|
||||||
|
+ targetClass.getSimpleName() + ".";
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return "The class does not exist.";
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
return "The class does not have a public constructor "
|
||||||
|
+ "that takes zero arguments.";
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
return "The class does not have a public constructor "
|
||||||
|
+ "that takes zero arguments.";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump the first 20 nodes of an XML context, excluding comments and blank
|
||||||
|
* text nodes.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private int dumpXml(Node xmlNode, int... parms) {
|
||||||
|
int remaining = (parms.length == 0) ? 20 : parms[0];
|
||||||
|
int level = (parms.length < 2) ? 1 : parms[1];
|
||||||
|
|
||||||
|
Node n = xmlNode;
|
||||||
|
|
||||||
|
if (Node.COMMENT_NODE == n.getNodeType()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (Node.TEXT_NODE == n.getNodeType()) {
|
||||||
|
if (StringUtils.isBlank(n.getTextContent())) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int used = 1;
|
||||||
|
|
||||||
|
System.out.println(StringUtils.repeat("-->", level) + n);
|
||||||
|
NodeList nl = n.getChildNodes();
|
||||||
|
for (int i = 0; (i < nl.getLength() && remaining > used); i++) {
|
||||||
|
used += dumpXml(nl.item(i), remaining - used, level + 1);
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Helper classes
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private static class StupidNamespaceContext implements NamespaceContext {
|
||||||
|
@Override
|
||||||
|
public String getNamespaceURI(String prefix) {
|
||||||
|
if ("j2ee".equals(prefix)) {
|
||||||
|
return "http://java.sun.com/xml/ns/j2ee";
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrefix(String namespaceURI) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<?> getPrefixes(String namespaceURI) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -52,15 +52,6 @@ public class IndividualRequestAnalyzerTest extends AbstractTestClass {
|
||||||
private static final String URL_BYTESTREAM_ALIAS = URL_HOME_PAGE + "/file/"
|
private static final String URL_BYTESTREAM_ALIAS = URL_HOME_PAGE + "/file/"
|
||||||
+ ID_FILE_BYTESTREAM + "/" + BYTESTREAM_FILENAME;
|
+ ID_FILE_BYTESTREAM + "/" + BYTESTREAM_FILENAME;
|
||||||
|
|
||||||
/**
|
|
||||||
* Info about an individual that appears in a different namespace.
|
|
||||||
*/
|
|
||||||
private static final String SOME_PREFIX = "somePrefix";
|
|
||||||
private static final String SOME_NAMESPACE = "http://some.namespace/";
|
|
||||||
private static final String ID_INDIVIDUAL_FOREIGN = "foreignId";
|
|
||||||
private static final String URI_INDIVIDUAL_FOREIGN = SOME_NAMESPACE
|
|
||||||
+ ID_INDIVIDUAL_FOREIGN;
|
|
||||||
|
|
||||||
private IndividualRequestAnalyzer analyzer;
|
private IndividualRequestAnalyzer analyzer;
|
||||||
private IndividualRequestAnalysisContextStub analysisContext;
|
private IndividualRequestAnalysisContextStub analysisContext;
|
||||||
private HttpServletRequestStub req;
|
private HttpServletRequestStub req;
|
||||||
|
@ -69,7 +60,6 @@ public class IndividualRequestAnalyzerTest extends AbstractTestClass {
|
||||||
|
|
||||||
private IndividualStub testIndividual;
|
private IndividualStub testIndividual;
|
||||||
private IndividualStub bytestreamIndividual;
|
private IndividualStub bytestreamIndividual;
|
||||||
private IndividualStub foreignIndividual;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
|
@ -83,10 +73,6 @@ public class IndividualRequestAnalyzerTest extends AbstractTestClass {
|
||||||
bytestreamIndividual = new IndividualStub(URI_FILE_BYTESTREAM);
|
bytestreamIndividual = new IndividualStub(URI_FILE_BYTESTREAM);
|
||||||
analysisContext.addIndividual(bytestreamIndividual);
|
analysisContext.addIndividual(bytestreamIndividual);
|
||||||
analysisContext.setAliasUrl(URI_FILE_BYTESTREAM, URL_BYTESTREAM_ALIAS);
|
analysisContext.setAliasUrl(URI_FILE_BYTESTREAM, URL_BYTESTREAM_ALIAS);
|
||||||
|
|
||||||
foreignIndividual = new IndividualStub(URI_INDIVIDUAL_FOREIGN);
|
|
||||||
analysisContext.addIndividual(foreignIndividual);
|
|
||||||
analysisContext.setNamespacePrefix(SOME_PREFIX, SOME_NAMESPACE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -132,16 +118,6 @@ public class IndividualRequestAnalyzerTest extends AbstractTestClass {
|
||||||
assertDefaultRequestInfo("find by display path", URI_INDIVIDUAL_TEST);
|
assertDefaultRequestInfo("find by display path", URI_INDIVIDUAL_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** /individual/nsPrefix/localname */
|
|
||||||
@Test
|
|
||||||
public void findByPrefixAndLocalname() {
|
|
||||||
req.setRequestUrl(url(DEFAULT_NAMESPACE + SOME_PREFIX + "/"
|
|
||||||
+ ID_INDIVIDUAL_FOREIGN));
|
|
||||||
analyzeIt();
|
|
||||||
assertDefaultRequestInfo("find by prefix and localname",
|
|
||||||
URI_INDIVIDUAL_FOREIGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** /individual/a/b/c fails. */
|
/** /individual/a/b/c fails. */
|
||||||
@Test
|
@Test
|
||||||
public void unrecognizedPath() {
|
public void unrecognizedPath() {
|
||||||
|
|
|
@ -0,0 +1,314 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
|
||||||
|
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionSetup.PROPERTY_FORCE_LOCALE;
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionSetup.PROPERTY_SELECTABLE_LOCALES;
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale.ATTRIBUTE_NAME;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.LocaleUtils;
|
||||||
|
import org.apache.commons.lang.ObjectUtils;
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import stubs.edu.cornell.mannlib.vitro.webapp.config.ConfigurationPropertiesStub;
|
||||||
|
import stubs.edu.cornell.mannlib.vitro.webapp.startup.StartupStatusStub;
|
||||||
|
import stubs.javax.servlet.ServletContextStub;
|
||||||
|
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale.ContextSelectedLocale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public class LocaleSelectionSetupTest extends AbstractTestClass {
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Infrastructure
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private LocaleSelectionSetup lss;
|
||||||
|
private ServletContextStub ctx;
|
||||||
|
private ServletContextEvent sce;
|
||||||
|
private ConfigurationPropertiesStub props;
|
||||||
|
private StartupStatusStub ss;
|
||||||
|
|
||||||
|
private int[] expectedMessageCounts;
|
||||||
|
private Locale expectedForcedLocale;
|
||||||
|
private List<Locale> expectedSelectableLocales;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
// setLoggerLevel(LocaleSelectionSetup.class, Level.DEBUG);
|
||||||
|
// setLoggerLevel(StartupStatusStub.class, Level.DEBUG);
|
||||||
|
setLoggerLevel(ConfigurationProperties.class, Level.WARN);
|
||||||
|
|
||||||
|
ctx = new ServletContextStub();
|
||||||
|
sce = new ServletContextEvent(ctx);
|
||||||
|
|
||||||
|
props = new ConfigurationPropertiesStub();
|
||||||
|
props.setBean(ctx);
|
||||||
|
|
||||||
|
ss = new StartupStatusStub(ctx);
|
||||||
|
|
||||||
|
lss = new LocaleSelectionSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void checkExpectations() {
|
||||||
|
if (expectedMessageCounts == null) {
|
||||||
|
fail("expecteMessages() was not called");
|
||||||
|
}
|
||||||
|
|
||||||
|
String message = compareMessageCount("info", ss.getInfoCount(),
|
||||||
|
expectedMessageCounts[0])
|
||||||
|
+ compareMessageCount("warning", ss.getWarningCount(),
|
||||||
|
expectedMessageCounts[1])
|
||||||
|
+ compareMessageCount("fatal", ss.getFatalCount(),
|
||||||
|
expectedMessageCounts[2])
|
||||||
|
+ checkForced()
|
||||||
|
+ checkSelectable();
|
||||||
|
if (!message.isEmpty()) {
|
||||||
|
fail(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String compareMessageCount(String label, int actual, int expected) {
|
||||||
|
if (expected == actual) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return "expecting " + expected + " " + label
|
||||||
|
+ " messages, but received " + actual + "; ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String checkForced() {
|
||||||
|
Locale actual = null;
|
||||||
|
Object o = ctx.getAttribute(ATTRIBUTE_NAME);
|
||||||
|
if (o instanceof ContextSelectedLocale) {
|
||||||
|
actual = ((ContextSelectedLocale) o).getForcedLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale expected = expectedForcedLocale;
|
||||||
|
if (ObjectUtils.equals(expected, actual)) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return "expected forced locale of " + expectedForcedLocale
|
||||||
|
+ ", but was " + actual + "; ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String checkSelectable() {
|
||||||
|
List<Locale> actual = Collections.emptyList();
|
||||||
|
Object o = ctx.getAttribute(ATTRIBUTE_NAME);
|
||||||
|
if (o instanceof ContextSelectedLocale) {
|
||||||
|
actual = ((ContextSelectedLocale) o).getSelectableLocales();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Locale> expected = expectedSelectableLocales;
|
||||||
|
if (expected == null) {
|
||||||
|
expected = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ObjectUtils.equals(expected, actual)) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return "expected selectable locales of " + expected + ", but was "
|
||||||
|
+ actual + "; ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// The tests
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// General functionality
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void neitherPropertyIsSpecified() {
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forceSuccessL() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectForced("es");
|
||||||
|
expectMessages(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forceSuccessL_C() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_ES");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectForced("es_ES");
|
||||||
|
expectMessages(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forceSuccessL_C_V() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "no_NO_NY");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectForced("no_NO_NY");
|
||||||
|
expectMessages(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneSelectable() {
|
||||||
|
props.setProperty(PROPERTY_SELECTABLE_LOCALES, "fr_FR");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectSelectable("fr_FR");
|
||||||
|
expectMessages(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twoSelectables() {
|
||||||
|
props.setProperty(PROPERTY_SELECTABLE_LOCALES, "fr_FR, es_PE");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectSelectable("fr_FR", "es_PE");
|
||||||
|
expectMessages(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bothPropertiesAreSpecified() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_ES");
|
||||||
|
props.setProperty(PROPERTY_SELECTABLE_LOCALES, "fr_FR");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectForced("es_ES");
|
||||||
|
expectMessages(1, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locale string syntax (common to both force and selectable)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void langaugeIsEmpty() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "_ES");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void languageWrongLength() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "e_ES");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void languageNotAlphabetic() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "e4_ES");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void languageNotLowerCase() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "eS_ES");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void countryIsEmpty() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_ _13");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void countryWrongLength() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_ESS");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void countryNotAlphabetic() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_E@");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void countryNotUpperCase() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_es");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void variantIsEmpty() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_ES_");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectMessages(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void funkyVariantIsAcceptable() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_ES_123_aa");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectForced("es_ES_123_aa");
|
||||||
|
expectMessages(1, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void localeNotRecognizedProducesWarning() {
|
||||||
|
props.setProperty(PROPERTY_FORCE_LOCALE, "es_FR");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectForced("es_FR");
|
||||||
|
expectMessages(1, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Syntax of selectable property
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void emptySelectableLocaleProducesWarning() {
|
||||||
|
props.setProperty(PROPERTY_SELECTABLE_LOCALES, "es_ES, , fr_FR");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectSelectable("es_ES", "fr_FR");
|
||||||
|
expectMessages(1, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void blanksAroundCommasAreIgnored() {
|
||||||
|
props.setProperty(PROPERTY_SELECTABLE_LOCALES, "es_ES,en_US \t , fr_FR");
|
||||||
|
lss.contextInitialized(sce);
|
||||||
|
expectSelectable("es_ES", "en_US", "fr_FR");
|
||||||
|
expectMessages(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// helper methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private void expectMessages(int infoCount, int warningCount, int fatalCount) {
|
||||||
|
this.expectedMessageCounts = new int[] { infoCount, warningCount,
|
||||||
|
fatalCount };
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectForced(String localeString) {
|
||||||
|
this.expectedForcedLocale = stringToLocale(localeString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectSelectable(String... strings) {
|
||||||
|
List<Locale> list = new ArrayList<Locale>();
|
||||||
|
for (String string : strings) {
|
||||||
|
list.add(stringToLocale(string));
|
||||||
|
}
|
||||||
|
this.expectedSelectableLocales = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Locale stringToLocale(String string) {
|
||||||
|
return LocaleUtils.toLocale(string);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,309 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.rdfservice.filter;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import stubs.com.hp.hpl.jena.rdf.model.LiteralStub;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.rdf.model.Literal;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the matching order we expect to see:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* exact match to preferred, by order.
|
||||||
|
* partial match to preferred, by order.
|
||||||
|
* vanilla or null (no language)
|
||||||
|
* no match
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class LanguageFilteringRDFServiceTest extends AbstractTestClass {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(LanguageFilteringRDFServiceTest.class);
|
||||||
|
|
||||||
|
private static final String COLLATOR_CLASSNAME = "edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringRDFService$RowIndexedLiteralSortByLang";
|
||||||
|
private static final String RIL_CLASSNAME = "edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringRDFService$RowIndexedLiteral";
|
||||||
|
|
||||||
|
private LanguageFilteringRDFService filteringRDFService;
|
||||||
|
private List<Object> listOfRowIndexedLiterals;
|
||||||
|
private int literalIndex;
|
||||||
|
|
||||||
|
private List<String> preferredLanguages;
|
||||||
|
private List<String> availableLanguages;
|
||||||
|
private List<String> expectedSortOrders;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
setLoggerLevel(this.getClass(), Level.DEBUG);
|
||||||
|
setLoggerLevel(LanguageFilteringRDFService.class, Level.DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// The tests
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleMatch() {
|
||||||
|
preferredLanguages = list("en-US");
|
||||||
|
availableLanguages = list("en-US");
|
||||||
|
expectedSortOrders = list("en-US");
|
||||||
|
testArbitraryOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleNoMatch() {
|
||||||
|
preferredLanguages = list("en-US");
|
||||||
|
availableLanguages = list("es-MX");
|
||||||
|
expectedSortOrders = list("es-MX");
|
||||||
|
testArbitraryOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doubleMatch() {
|
||||||
|
preferredLanguages = list("en-US", "es-MX");
|
||||||
|
availableLanguages = list("en-US", "es-MX");
|
||||||
|
expectedSortOrders = list("en-US", "es-MX");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noMatches() {
|
||||||
|
preferredLanguages = list("es-MX");
|
||||||
|
availableLanguages = list("en-US", "fr-FR");
|
||||||
|
expectedSortOrders = list("en-US", "fr-FR");
|
||||||
|
testArbitraryOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void partialMatches() {
|
||||||
|
preferredLanguages = list("en", "es");
|
||||||
|
availableLanguages = list("en-US", "es-MX");
|
||||||
|
expectedSortOrders = list("en-US", "es-MX");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void matchIsBetterThanNoMatch() {
|
||||||
|
preferredLanguages = list("en-US", "es-MX");
|
||||||
|
availableLanguages = list("en-US", "fr-FR");
|
||||||
|
expectedSortOrders = list("en-US", "fr-FR");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void matchIsBetterThanPartialMatch() {
|
||||||
|
preferredLanguages = list("es-ES", "en-US");
|
||||||
|
availableLanguages = list("en-US", "es-MX");
|
||||||
|
expectedSortOrders = list("en-US", "es-MX");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exactMatchIsBetterThanPartialMatch() {
|
||||||
|
preferredLanguages = list("es");
|
||||||
|
availableLanguages = list("es", "es-MX");
|
||||||
|
expectedSortOrders = list("es", "es-MX");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void matchIsBetterThanVanilla() {
|
||||||
|
preferredLanguages = list("en-US");
|
||||||
|
availableLanguages = list("en-US", "");
|
||||||
|
expectedSortOrders = list("en-US", "");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void partialMatchIsBetterThanVanilla() {
|
||||||
|
preferredLanguages = list("es-MX");
|
||||||
|
availableLanguages = list("es-ES", "");
|
||||||
|
expectedSortOrders = list("es-ES", "");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void vanillaIsBetterThanNoMatch() {
|
||||||
|
preferredLanguages = list("es-MX");
|
||||||
|
availableLanguages = list("en-US", "");
|
||||||
|
expectedSortOrders = list("", "en-US");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void omnibus() {
|
||||||
|
preferredLanguages = list("es-MX", "es", "en-UK", "es-PE", "fr");
|
||||||
|
availableLanguages = list("es-MX", "es", "fr", "es-ES", "fr-FR", "",
|
||||||
|
"de-DE");
|
||||||
|
expectedSortOrders = list("es-MX", "es", "fr", "es-ES", "fr-FR", "",
|
||||||
|
"de-DE");
|
||||||
|
testBothWays();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Helper methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the available languages as they are presented. Then reverse them and
|
||||||
|
* sort again.
|
||||||
|
*/
|
||||||
|
private void testBothWays() {
|
||||||
|
createLanguageFilter();
|
||||||
|
|
||||||
|
buildListOfLiterals();
|
||||||
|
sortListOfLiterals();
|
||||||
|
assertLanguageOrder("sort literals");
|
||||||
|
|
||||||
|
buildReversedListOfLiterals();
|
||||||
|
sortListOfLiterals();
|
||||||
|
assertLanguageOrder("sort reversed literals");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the available languages, without caring what the eventual sorted
|
||||||
|
* order is. Really, this is just a test to see that no exceptions are
|
||||||
|
* thrown, and no languages are "lost in translation".
|
||||||
|
*/
|
||||||
|
private void testArbitraryOrder() {
|
||||||
|
createLanguageFilter();
|
||||||
|
|
||||||
|
buildListOfLiterals();
|
||||||
|
sortListOfLiterals();
|
||||||
|
assertLanguages("sort literals");
|
||||||
|
|
||||||
|
buildReversedListOfLiterals();
|
||||||
|
sortListOfLiterals();
|
||||||
|
assertLanguages("sort reversed literals");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> list(String... strings) {
|
||||||
|
return new ArrayList<String>(Arrays.asList(strings));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLanguageFilter() {
|
||||||
|
filteringRDFService = new LanguageFilteringRDFService(null,
|
||||||
|
preferredLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildListOfLiterals() {
|
||||||
|
List<Object> list = new ArrayList<Object>();
|
||||||
|
for (String language : availableLanguages) {
|
||||||
|
list.add(buildRowIndexedLiteral(language));
|
||||||
|
}
|
||||||
|
listOfRowIndexedLiterals = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildReversedListOfLiterals() {
|
||||||
|
List<Object> list = new ArrayList<Object>();
|
||||||
|
for (String language : availableLanguages) {
|
||||||
|
list.add(0, buildRowIndexedLiteral(language));
|
||||||
|
}
|
||||||
|
listOfRowIndexedLiterals = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sortListOfLiterals() {
|
||||||
|
log.debug("before sorting: "
|
||||||
|
+ languagesFromLiterals(listOfRowIndexedLiterals));
|
||||||
|
Comparator<Object> comparator = buildRowIndexedLiteralSortByLang();
|
||||||
|
Collections.sort(listOfRowIndexedLiterals, comparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertLanguageOrder(String message) {
|
||||||
|
List<String> expectedLanguages = expectedSortOrders;
|
||||||
|
log.debug("expected order: " + expectedLanguages);
|
||||||
|
|
||||||
|
List<String> actualLanguages = languagesFromLiterals(listOfRowIndexedLiterals);
|
||||||
|
log.debug("actual order: " + actualLanguages);
|
||||||
|
|
||||||
|
assertEquals(message, expectedLanguages, actualLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertLanguages(String message) {
|
||||||
|
Set<String> expectedLanguages = new HashSet<String>(expectedSortOrders);
|
||||||
|
log.debug("expected languages: " + expectedLanguages);
|
||||||
|
|
||||||
|
Set<String> actualLanguages = new HashSet<String>(
|
||||||
|
languagesFromLiterals(listOfRowIndexedLiterals));
|
||||||
|
log.debug("actual languages: " + actualLanguages);
|
||||||
|
|
||||||
|
assertEquals(message, expectedLanguages, actualLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> languagesFromLiterals(List<Object> literals) {
|
||||||
|
List<String> actualLanguages = new ArrayList<String>();
|
||||||
|
for (Object ril : literals) {
|
||||||
|
actualLanguages.add(getLanguageFromRowIndexedLiteral(ril));
|
||||||
|
}
|
||||||
|
return actualLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Reflection methods to get around "private" declarations.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private Object buildRowIndexedLiteral(String language) {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName(RIL_CLASSNAME);
|
||||||
|
Class<?>[] argTypes = { LanguageFilteringRDFService.class,
|
||||||
|
Literal.class, Integer.TYPE };
|
||||||
|
Constructor<?> constructor = clazz.getDeclaredConstructor(argTypes);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
|
||||||
|
Literal l = new LiteralStub(language);
|
||||||
|
int i = literalIndex++;
|
||||||
|
return constructor.newInstance(filteringRDFService, l, i);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Could not create a row-indexed literal", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Comparator<Object> buildRowIndexedLiteralSortByLang() {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName(COLLATOR_CLASSNAME);
|
||||||
|
Class<?>[] argTypes = { LanguageFilteringRDFService.class };
|
||||||
|
Constructor<?> constructor = clazz.getDeclaredConstructor(argTypes);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
|
||||||
|
return (Comparator<Object>) constructor
|
||||||
|
.newInstance(filteringRDFService);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Could not create a collator", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLanguageFromRowIndexedLiteral(Object ril) {
|
||||||
|
try {
|
||||||
|
Method m = ril.getClass().getDeclaredMethod("getLiteral");
|
||||||
|
m.setAccessible(true);
|
||||||
|
Literal l = (Literal) m.invoke(ril);
|
||||||
|
return l.getLanguage();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Could not get the Literal from a RowIndexedLiteral", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
179
webapp/test/stubs/com/hp/hpl/jena/rdf/model/LiteralStub.java
Normal file
179
webapp/test/stubs/com/hp/hpl/jena/rdf/model/LiteralStub.java
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package stubs.com.hp.hpl.jena.rdf.model;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.datatypes.RDFDatatype;
|
||||||
|
import com.hp.hpl.jena.graph.Node;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Literal;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Model;
|
||||||
|
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||||
|
import com.hp.hpl.jena.rdf.model.RDFVisitor;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only implemented what I needed so far. The rest is left as an exercise for
|
||||||
|
* the student.
|
||||||
|
*/
|
||||||
|
public class LiteralStub implements Literal {
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Stub infrastructure
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
final String language;
|
||||||
|
|
||||||
|
public LiteralStub(String language) {
|
||||||
|
this.language = language;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Stub methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLiteral() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAnon() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResource() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isURIResource() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Literal asLiteral() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource asResource() {
|
||||||
|
throw new ClassCastException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLanguage() {
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Un-implemented methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends RDFNode> T as(Class<T> view) {
|
||||||
|
throw new RuntimeException("LiteralStub.as() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends RDFNode> boolean canAs(Class<T> arg0) {
|
||||||
|
throw new RuntimeException("LiteralStub.canAs() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Model getModel() {
|
||||||
|
throw new RuntimeException("LiteralStub.getModel() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitWith(RDFVisitor arg0) {
|
||||||
|
throw new RuntimeException("LiteralStub.visitWith() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node asNode() {
|
||||||
|
throw new RuntimeException("LiteralStub.asNode() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getBoolean() {
|
||||||
|
throw new RuntimeException("LiteralStub.getBoolean() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getByte() {
|
||||||
|
throw new RuntimeException("LiteralStub.getByte() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getChar() {
|
||||||
|
throw new RuntimeException("LiteralStub.getChar() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RDFDatatype getDatatype() {
|
||||||
|
throw new RuntimeException("LiteralStub.getDatatype() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDatatypeURI() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"LiteralStub.getDatatypeURI() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getDouble() {
|
||||||
|
throw new RuntimeException("LiteralStub.getDouble() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFloat() {
|
||||||
|
throw new RuntimeException("LiteralStub.getFloat() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInt() {
|
||||||
|
throw new RuntimeException("LiteralStub.getInt() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLexicalForm() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"LiteralStub.getLexicalForm() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLong() {
|
||||||
|
throw new RuntimeException("LiteralStub.getLong() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getShort() {
|
||||||
|
throw new RuntimeException("LiteralStub.getShort() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString() {
|
||||||
|
throw new RuntimeException("LiteralStub.getString() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
throw new RuntimeException("LiteralStub.getValue() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Literal inModel(Model arg0) {
|
||||||
|
throw new RuntimeException("LiteralStub.inModel() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWellFormedXML() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"LiteralStub.isWellFormedXML() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sameValueAs(Literal arg0) {
|
||||||
|
throw new RuntimeException("LiteralStub.sameValueAs() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,7 +21,6 @@ public class IndividualRequestAnalysisContextStub implements
|
||||||
private final String defaultNamespace;
|
private final String defaultNamespace;
|
||||||
private final Map<String, Individual> individualsByUri = new HashMap<String, Individual>();
|
private final Map<String, Individual> individualsByUri = new HashMap<String, Individual>();
|
||||||
private final Map<String, Individual> profilePages = new HashMap<String, Individual>();
|
private final Map<String, Individual> profilePages = new HashMap<String, Individual>();
|
||||||
private final Map<String, String> namespacesByPrefix = new HashMap<String, String>();
|
|
||||||
private final Map<String, String> aliasUrlsByIndividual = new HashMap<String, String>();
|
private final Map<String, String> aliasUrlsByIndividual = new HashMap<String, String>();
|
||||||
|
|
||||||
public IndividualRequestAnalysisContextStub(String defaultNamespace) {
|
public IndividualRequestAnalysisContextStub(String defaultNamespace) {
|
||||||
|
@ -36,10 +35,6 @@ public class IndividualRequestAnalysisContextStub implements
|
||||||
profilePages.put(netId, individual);
|
profilePages.put(netId, individual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNamespacePrefix(String prefix, String namespace) {
|
|
||||||
namespacesByPrefix.put(prefix, namespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAliasUrl(String individualUri, String aliasUrl) {
|
public void setAliasUrl(String individualUri, String aliasUrl) {
|
||||||
aliasUrlsByIndividual.put(individualUri, aliasUrl);
|
aliasUrlsByIndividual.put(individualUri, aliasUrl);
|
||||||
}
|
}
|
||||||
|
@ -53,15 +48,6 @@ public class IndividualRequestAnalysisContextStub implements
|
||||||
return defaultNamespace;
|
return defaultNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNamespaceForPrefix(String prefix) {
|
|
||||||
if (prefix == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
String namespace = namespacesByPrefix.get(prefix);
|
|
||||||
return (namespace == null) ? "" : namespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Individual getIndividualByURI(String individualUri) {
|
public Individual getIndividualByURI(String individualUri) {
|
||||||
if (individualUri == null) {
|
if (individualUri == null) {
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package stubs.edu.cornell.mannlib.vitro.webapp.startup;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep track of how many messages come in.
|
||||||
|
*/
|
||||||
|
public class StartupStatusStub extends StartupStatus {
|
||||||
|
private static final Log log = LogFactory.getLog(StartupStatusStub.class);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Stub infrastructure
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private int infoCount = 0;
|
||||||
|
private int warningCount = 0;
|
||||||
|
private int fatalCount = 0;
|
||||||
|
|
||||||
|
public StartupStatusStub(ServletContext ctx) {
|
||||||
|
ctx.setAttribute(ATTRIBUTE_NAME, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInfoCount() {
|
||||||
|
return infoCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWarningCount() {
|
||||||
|
return warningCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFatalCount() {
|
||||||
|
return fatalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Stub methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(ServletContextListener listener, String message) {
|
||||||
|
log.debug("INFO: " + message);
|
||||||
|
infoCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(ServletContextListener listener, String message,
|
||||||
|
Throwable cause) {
|
||||||
|
log.debug("INFO: " + message + " " + cause);
|
||||||
|
infoCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warning(ServletContextListener listener, String message) {
|
||||||
|
log.debug("WARNING: " + message);
|
||||||
|
warningCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warning(ServletContextListener listener, String message,
|
||||||
|
Throwable cause) {
|
||||||
|
log.debug("WARNING: " + message + " " + cause);
|
||||||
|
warningCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fatal(ServletContextListener listener, String message) {
|
||||||
|
log.debug("FATAL: " + message);
|
||||||
|
fatalCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fatal(ServletContextListener listener, String message,
|
||||||
|
Throwable cause) {
|
||||||
|
log.debug("FATAL: " + message + " " + cause);
|
||||||
|
fatalCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Un-implemented methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void listenerNotExecuted(ServletContextListener listener) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.listenerNotExecuted() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void listenerExecuted(ServletContextListener listener) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.listenerExecuted() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allClear() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.allClear() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStartupAborted() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.isStartupAborted() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StatusItem> getStatusItems() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.getStatusItems() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StatusItem> getErrorItems() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.getErrorItems() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StatusItem> getWarningItems() {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.getWarningItems() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StatusItem> getItemsForListener(ServletContextListener listener) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"StartupStatusStub.getItemsForListener() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,123 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package stubs.edu.cornell.mannlib.vitro.webapp.utils;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.hp.hpl.jena.rdf.model.Model;
|
|
||||||
import com.hp.hpl.jena.rdf.model.Statement;
|
|
||||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.NamespaceMapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A minimal implementation of the NamespaceMapper.
|
|
||||||
*
|
|
||||||
* I have only implemented the methods that I needed. Feel free to implement
|
|
||||||
* others.
|
|
||||||
*/
|
|
||||||
public class NamespaceMapperStub implements NamespaceMapper {
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Stub infrastructure
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
private final Map<String, String> prefixMap = new HashMap<String, String>();
|
|
||||||
|
|
||||||
public void setPrefixForNamespace(String prefix, String namespace) {
|
|
||||||
prefixMap.put(prefix, namespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Stub methods
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNamespaceForPrefix(String prefix) {
|
|
||||||
return prefixMap.get(prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Un-implemented methods
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addedStatement(Statement arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.addedStatement() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addedStatements(Statement[] arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.addedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addedStatements(List<Statement> arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.addedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addedStatements(StmtIterator arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.addedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addedStatements(Model arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.addedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyEvent(Model arg0, Object arg1) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.notifyEvent() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removedStatement(Statement arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.removedStatement() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removedStatements(Statement[] arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.removedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removedStatements(List<Statement> arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.removedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removedStatements(StmtIterator arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.removedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removedStatements(Model arg0) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.removedStatements() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPrefixForNamespace(String namespace) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.getPrefixForNamespace() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getPrefixesForNamespace(String namespace) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"NamespaceMapperStub.getPrefixesForNamespace() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
<nav role="navigation">
|
<nav role="navigation">
|
||||||
<ul id="header-nav" role="list">
|
<ul id="header-nav" role="list">
|
||||||
|
<#include "languageSelector.ftl">
|
||||||
<li role="listitem"><a href="${urls.index}" title="index">Index</a></li>
|
<li role="listitem"><a href="${urls.index}" title="index">Index</a></li>
|
||||||
<#if user.loggedIn>
|
<#if user.loggedIn>
|
||||||
<#if user.hasSiteAdminAccess>
|
<#if user.hasSiteAdminAccess>
|
||||||
|
|
|
@ -55,6 +55,9 @@ edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewServiceSetup
|
||||||
|
|
||||||
edu.ucsf.vitro.opensocial.OpenSocialSmokeTests
|
edu.ucsf.vitro.opensocial.OpenSocialSmokeTests
|
||||||
|
|
||||||
|
# For multiple language support
|
||||||
|
edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionSetup
|
||||||
|
|
||||||
# The Solr index uses a "public" permission, so the PropertyRestrictionPolicyHelper
|
# The Solr index uses a "public" permission, so the PropertyRestrictionPolicyHelper
|
||||||
# and the PermissionRegistry must already be set up.
|
# and the PermissionRegistry must already be set up.
|
||||||
edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup
|
edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup
|
||||||
|
|
|
@ -78,6 +78,16 @@
|
||||||
<url-pattern>/*</url-pattern>
|
<url-pattern>/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<description>Override the Locale in the HttpRequest, if appropriate.</description>
|
||||||
|
<filter-name>Locale selection filter</filter-name>
|
||||||
|
<filter-class>edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionFilter</filter-class>
|
||||||
|
</filter>
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>Locale selection filter</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
|
||||||
<filter>
|
<filter>
|
||||||
<filter-name>JSession Strip Filter</filter-name>
|
<filter-name>JSession Strip Filter</filter-name>
|
||||||
<filter-class>edu.cornell.mannlib.vitro.webapp.filters.JSessionStripFilter</filter-class>
|
<filter-class>edu.cornell.mannlib.vitro.webapp.filters.JSessionStripFilter</filter-class>
|
||||||
|
@ -112,8 +122,8 @@
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>VitroRequestPrep</filter-name>
|
<filter-name>VitroRequestPrep</filter-name>
|
||||||
<url-pattern>/*</url-pattern>
|
<url-pattern>/*</url-pattern>
|
||||||
<dispatcher>request</dispatcher>
|
<dispatcher>REQUEST</dispatcher>
|
||||||
<dispatcher>forward</dispatcher>
|
<dispatcher>FORWARD</dispatcher>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter>
|
<filter>
|
||||||
|
@ -123,7 +133,7 @@
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>PageRoutingFilter</filter-name>
|
<filter-name>PageRoutingFilter</filter-name>
|
||||||
<url-pattern>/*</url-pattern>
|
<url-pattern>/*</url-pattern>
|
||||||
<dispatcher>request</dispatcher>
|
<dispatcher>REQUEST</dispatcher>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<!-- Spring setup **************************************************** -->
|
<!-- Spring setup **************************************************** -->
|
||||||
|
@ -154,25 +164,6 @@
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<!-- Servlets ********************************************************** -->
|
<!-- Servlets ********************************************************** -->
|
||||||
<servlet>
|
|
||||||
<!--adding only trimSpaces param to defaults to clean up html output-->
|
|
||||||
<servlet-name>jsp</servlet-name>
|
|
||||||
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
|
|
||||||
<init-param>
|
|
||||||
<param-name>fork</param-name>
|
|
||||||
<param-value>false</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<param-name>xpoweredBy</param-name>
|
|
||||||
<param-value>false</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<param-name>trimSpaces</param-name>
|
|
||||||
<param-value>true</param-value>
|
|
||||||
</init-param>
|
|
||||||
<load-on-startup>3</load-on-startup>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>IndexController</servlet-name>
|
<servlet-name>IndexController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.search.controller.IndexController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.search.controller.IndexController</servlet-class>
|
||||||
|
@ -191,15 +182,6 @@
|
||||||
<url-pattern>/RecomputeInferences</url-pattern>
|
<url-pattern>/RecomputeInferences</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>SDBSetupController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.SDBSetupController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>SDBSetupController</servlet-name>
|
|
||||||
<url-pattern>/sdbsetup</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>MenuManagementEdit</servlet-name>
|
<servlet-name>MenuManagementEdit</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.MenuManagementEdit</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.MenuManagementEdit</servlet-class>
|
||||||
|
@ -218,24 +200,6 @@
|
||||||
<url-pattern>/ajax/sparqlQuery</url-pattern>
|
<url-pattern>/ajax/sparqlQuery</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<!-- This is the new navigation controller. It is not ready for the 1.1 release
|
|
||||||
see http://issues.library.cornell.edu/browse/NIHVIVO-597
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>NavigationController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.NavigationController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>NavigationController</servlet-name>
|
|
||||||
<url-pattern>/nav/*</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>fetch</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.QueryServlet</servlet-class>
|
|
||||||
<!--load-on-startup>2</load-on-startup-->
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>AboutController</servlet-name>
|
<servlet-name>AboutController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.AboutController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.AboutController</servlet-class>
|
||||||
|
@ -370,14 +334,13 @@
|
||||||
<url-pattern>/editRequestDispatch</url-pattern>
|
<url-pattern>/editRequestDispatch</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>FlagUpdateController</servlet-name>
|
<servlet-name>EditRequestAJAX</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.FlagUpdateController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.edit.n3editing.controller.EditRequestAJAXController</servlet-class>
|
||||||
</servlet>
|
</servlet>
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>FlagUpdateController</servlet-name>
|
<servlet-name>EditRequestAJAX</servlet-name>
|
||||||
<url-pattern>/flagUpdate</url-pattern>
|
<url-pattern>/editRequestAJAX</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
|
@ -434,24 +397,6 @@
|
||||||
<url-pattern>/jenaXmlFileUpload/*</url-pattern>
|
<url-pattern>/jenaXmlFileUpload/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>OwlImportController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.owl.OwlImportController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>OwlImportController</servlet-name>
|
|
||||||
<url-pattern>/owl</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>OwlImportServlet</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.owl.ProtegeOwlImportServlet</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>OwlImportServlet</servlet-name>
|
|
||||||
<url-pattern>/importOwl</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>JenaAdminServlet</servlet-name>
|
<servlet-name>JenaAdminServlet</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.jena.JenaAdminActions</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.jena.JenaAdminActions</servlet-class>
|
||||||
|
@ -551,16 +496,6 @@
|
||||||
<url-pattern>/datapropEdit</url-pattern>
|
<url-pattern>/datapropEdit</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
|
|
||||||
<servlet-name>KeywordEditController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.KeywordEditController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>KeywordEditController</servlet-name>
|
|
||||||
<url-pattern>/keywordEdit</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>OntologyEditController</servlet-name>
|
<servlet-name>OntologyEditController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.OntologyEditController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.OntologyEditController</servlet-class>
|
||||||
|
@ -759,24 +694,6 @@
|
||||||
<url-pattern>/admin/wait</url-pattern>
|
<url-pattern>/admin/wait</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>StatementChangeListingController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.jena.StatementChangeListingController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>StatementChangeListingController</servlet-name>
|
|
||||||
<url-pattern>/statementHistory</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>WriteOutChangesController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.jena.WriteOutChangesController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>WriteOutChangesController</servlet-name>
|
|
||||||
<url-pattern>/writeOutChanges</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>ListVClassWebappsController</servlet-name>
|
<servlet-name>ListVClassWebappsController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.ListVClassWebappsController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.ListVClassWebappsController</servlet-class>
|
||||||
|
@ -939,15 +856,6 @@
|
||||||
<url-pattern>/edit/reorder</url-pattern>
|
<url-pattern>/edit/reorder</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>AdminController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.AdminController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>AdminController</servlet-name>
|
|
||||||
<url-pattern>/adminCon</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>TermsOfUseController</servlet-name>
|
<servlet-name>TermsOfUseController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.TermsOfUseController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.TermsOfUseController</servlet-class>
|
||||||
|
@ -1087,32 +995,6 @@
|
||||||
<url-pattern>/browse</url-pattern>
|
<url-pattern>/browse</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>pubsbyorg</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.vclass.PubsByDepartmentServlet</servlet-class>
|
|
||||||
<init-param>
|
|
||||||
<param-name>workspaceDir</param-name>
|
|
||||||
<param-value>/usr/local/services/vivo/logs</param-value>
|
|
||||||
</init-param>
|
|
||||||
<!--load-on-startup>2</load-on-startup-->
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>coauthors</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.vclass.CoAuthorServlet</servlet-class>
|
|
||||||
<init-param>
|
|
||||||
<param-name>workspaceDir</param-name>
|
|
||||||
<param-value>/usr/local/services/vivo/logs</param-value>
|
|
||||||
</init-param>
|
|
||||||
<!--load-on-startup>2</load-on-startup-->
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>generic_create</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.GenericDBCreate</servlet-class>
|
|
||||||
<!--load-on-startup>2</load-on-startup-->
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>serveFiles</servlet-name>
|
<servlet-name>serveFiles</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.filestorage.serving.FileServingServlet</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.filestorage.serving.FileServingServlet</servlet-class>
|
||||||
|
@ -1122,21 +1004,6 @@
|
||||||
<url-pattern>/file/*</url-pattern>
|
<url-pattern>/file/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>generic_editprep</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.GenericDBEditPrep</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>generic_update</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.GenericDBUpdate</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>generic_delete</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.GenericDBDelete</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>SparqlQuery</servlet-name>
|
<servlet-name>SparqlQuery</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.SparqlQueryServlet</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.SparqlQueryServlet</servlet-class>
|
||||||
|
@ -1147,16 +1014,6 @@
|
||||||
<url-pattern>/admin/sparqlquery</url-pattern>
|
<url-pattern>/admin/sparqlquery</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>VisualizationController</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>VisualizationController</servlet-name>
|
|
||||||
<url-pattern>/visualization</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>primitiveRdfEdit</servlet-name>
|
<servlet-name>primitiveRdfEdit</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.PrimitiveRdfEdit</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.PrimitiveRdfEdit</servlet-class>
|
||||||
|
@ -1176,10 +1033,6 @@
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<!-- ============================== servlet-mappings ======================== -->
|
<!-- ============================== servlet-mappings ======================== -->
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>fetch</servlet-name>
|
|
||||||
<url-pattern>/fetch</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>mailusers</servlet-name>
|
<servlet-name>mailusers</servlet-name>
|
||||||
<url-pattern>/mailusers</url-pattern>
|
<url-pattern>/mailusers</url-pattern>
|
||||||
|
@ -1238,22 +1091,6 @@
|
||||||
<servlet-name>coauthors</servlet-name>
|
<servlet-name>coauthors</servlet-name>
|
||||||
<url-pattern>/coauthors</url-pattern>
|
<url-pattern>/coauthors</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>generic_create</servlet-name>
|
|
||||||
<url-pattern>/generic_create</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>generic_editprep</servlet-name>
|
|
||||||
<url-pattern>/generic_editprep</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>generic_update</servlet-name>
|
|
||||||
<url-pattern>/generic_update</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>generic_delete</servlet-name>
|
|
||||||
<url-pattern>/generic_delete</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<!-- ==================== sparql query builder ==================== -->
|
<!-- ==================== sparql query builder ==================== -->
|
||||||
|
|
||||||
|
@ -1330,6 +1167,16 @@
|
||||||
<url-pattern>/orng/*</url-pattern>
|
<url-pattern>/orng/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<description>Multiple-language support. Allows user to select his preferred langauge</description>
|
||||||
|
<servlet-name>LocaleSelectionController</servlet-name>
|
||||||
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionController</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>LocaleSelectionController</servlet-name>
|
||||||
|
<url-pattern>/selectLocale</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
|
||||||
<!-- ==================== tag libraries ============================== -->
|
<!-- ==================== tag libraries ============================== -->
|
||||||
<jsp-config>
|
<jsp-config>
|
||||||
|
|
70
webapp/web/css/individual/individual-property-groups.css
Normal file
70
webapp/web/css/individual/individual-property-groups.css
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
span#toggleContainer {
|
||||||
|
float:right;
|
||||||
|
padding:10px 8px 0 0;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
section.property-group {
|
||||||
|
padding-top: 15px;
|
||||||
|
border-top:none;
|
||||||
|
}
|
||||||
|
section.property-group h2 {
|
||||||
|
padding: 8px 10px 4px 12px;
|
||||||
|
}
|
||||||
|
.scroll-up {
|
||||||
|
position: absolute;
|
||||||
|
width: 21px;
|
||||||
|
height: 30px;
|
||||||
|
top: 8px; /* changed for redesign, was 0 */
|
||||||
|
right: 12px; /* changed for redesign, was -21px;*/
|
||||||
|
}
|
||||||
|
section.property-group div {
|
||||||
|
margin-top:15px;
|
||||||
|
/* display:none; */
|
||||||
|
}
|
||||||
|
section.property-group h2 {
|
||||||
|
font-size: 1.15em !important;
|
||||||
|
color: #5e6363 !important;
|
||||||
|
font-weight: normal !important;
|
||||||
|
background: #fafaf9 !important;
|
||||||
|
}
|
||||||
|
ul.propertyTabsList {
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-top: 24px
|
||||||
|
}
|
||||||
|
ul.propertyTabsList li {
|
||||||
|
font-size: 1.0em;
|
||||||
|
}
|
||||||
|
ul.propertyTabsList li:first-child {
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
li.nonSelectedGroupTab {
|
||||||
|
float:left;
|
||||||
|
border: 1px solid #DFE6E5;
|
||||||
|
background-color:#E4ECF3;
|
||||||
|
padding: 6px 8px 6px 8px;
|
||||||
|
cursor:pointer;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
-moz-border-radius-topright: 4px;
|
||||||
|
-webkit-border-top-right-radius: 4px;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
-moz-border-radius-topleft: 4px;
|
||||||
|
-webkit-border-top-left-radius: 4px;
|
||||||
|
}
|
||||||
|
li.selectedGroupTab {
|
||||||
|
float:left;
|
||||||
|
border: 1px solid #DFE6E5;
|
||||||
|
border-bottom-color:#fff;
|
||||||
|
background-color:#FFF;
|
||||||
|
padding: 6px 8px 6px 8px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
-moz-border-radius-topright: 4px;
|
||||||
|
-webkit-border-top-right-radius: 4px;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
-moz-border-radius-topleft: 4px;
|
||||||
|
-webkit-border-top-left-radius: 4px;
|
||||||
|
}
|
||||||
|
li.groupTabSpacer {
|
||||||
|
float:left;border-bottom: 1px solid #DFE6E5;background-color:#fff;width:3px;height:37px
|
||||||
|
}
|
|
@ -32,7 +32,7 @@
|
||||||
/* <------ INDIVIDUAL INTRO FOR ANY CLASS*/
|
/* <------ INDIVIDUAL INTRO FOR ANY CLASS*/
|
||||||
#individual-intro {
|
#individual-intro {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ img#uriIcon {
|
||||||
width: 166px;
|
width: 166px;
|
||||||
float: left;
|
float: left;
|
||||||
padding-right: 1.5em;
|
padding-right: 1.5em;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
#share-contact h3 {
|
#share-contact h3 {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
|
@ -89,7 +89,7 @@ img.individual-photo {
|
||||||
h2#mainImage, #share-contact h2 {
|
h2#mainImage, #share-contact h2 {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
padding-bottom: 0.3em
|
padding-bottom: 0.6em
|
||||||
}
|
}
|
||||||
#photo-wrapper {
|
#photo-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
request.setAttribute("bodyJsp", "/errorbody.jsp");
|
request.setAttribute("bodyJsp", "/errorbody.jsp");
|
||||||
request.setAttribute("title", "Error");
|
request.setAttribute("title", "Error");
|
||||||
request.setAttribute("css", "");
|
request.setAttribute("css", "");
|
||||||
request.setAttribute("appBean", appBean);
|
|
||||||
request.setAttribute("themeDir", themeDir);
|
request.setAttribute("themeDir", themeDir);
|
||||||
%>
|
%>
|
||||||
|
|
||||||
|
|
BIN
webapp/web/images/emailIconSmall.gif
Normal file
BIN
webapp/web/images/emailIconSmall.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 B |
BIN
webapp/web/images/individual/collapse-prop-group.png
Normal file
BIN
webapp/web/images/individual/collapse-prop-group.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3 KiB |
BIN
webapp/web/images/individual/expand-prop-group.png
Normal file
BIN
webapp/web/images/individual/expand-prop-group.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3 KiB |
BIN
webapp/web/images/phoneIconSmall.gif
Normal file
BIN
webapp/web/images/phoneIconSmall.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 95 B |
10
webapp/web/js/amplify/amplify.store.min.js
vendored
Normal file
10
webapp/web/js/amplify/amplify.store.min.js
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/*!
|
||||||
|
* Amplify Store - Persistent Client-Side Storage 1.1.0
|
||||||
|
*
|
||||||
|
* Copyright 2011 appendTo LLC. (http://appendto.com/team)
|
||||||
|
* Dual licensed under the MIT or GPL licenses.
|
||||||
|
* http://appendto.com/open-source-licenses
|
||||||
|
*
|
||||||
|
* http://amplifyjs.com
|
||||||
|
*/
|
||||||
|
(function(a,b){function e(a,e){c.addType(a,function(f,g,h){var i,j,k,l,m=g,n=(new Date).getTime();if(!f){m={},l=[],k=0;try{f=e.length;while(f=e.key(k++))d.test(f)&&(j=JSON.parse(e.getItem(f)),j.expires&&j.expires<=n?l.push(f):m[f.replace(d,"")]=j.data);while(f=l.pop())e.removeItem(f)}catch(o){}return m}f="__amplify__"+f;if(g===b){i=e.getItem(f),j=i?JSON.parse(i):{expires:-1};if(j.expires&&j.expires<=n)e.removeItem(f);else return j.data}else if(g===null)e.removeItem(f);else{j=JSON.stringify({data:g,expires:h.expires?n+h.expires:null});try{e.setItem(f,j)}catch(o){c[a]();try{e.setItem(f,j)}catch(o){throw c.error()}}}return m})}var c=a.store=function(a,b,d,e){var e=c.type;d&&d.type&&d.type in c.types&&(e=d.type);return c.types[e](a,b,d||{})};c.types={},c.type=null,c.addType=function(a,b){c.type||(c.type=a),c.types[a]=b,c[a]=function(b,d,e){e=e||{},e.type=a;return c(b,d,e)}},c.error=function(){return"amplify.store quota exceeded"};var d=/^__amplify__/;for(var f in{localStorage:1,sessionStorage:1})try{window[f].getItem&&e(f,window[f])}catch(g){}if(window.globalStorage)try{e("globalStorage",window.globalStorage[window.location.hostname]),c.type==="sessionStorage"&&(c.type="globalStorage")}catch(g){}(function(){if(!c.types.localStorage){var a=document.createElement("div"),d="amplify";a.style.display="none",document.getElementsByTagName("head")[0].appendChild(a);try{a.addBehavior("#default#userdata"),a.load(d)}catch(e){a.parentNode.removeChild(a);return}c.addType("userData",function(e,f,g){a.load(d);var h,i,j,k,l,m=f,n=(new Date).getTime();if(!e){m={},l=[],k=0;while(h=a.XMLDocument.documentElement.attributes[k++])i=JSON.parse(h.value),i.expires&&i.expires<=n?l.push(h.name):m[h.name]=i.data;while(e=l.pop())a.removeAttribute(e);a.save(d);return m}e=e.replace(/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g,"-");if(f===b){h=a.getAttribute(e),i=h?JSON.parse(h):{expires:-1};if(i.expires&&i.expires<=n)a.removeAttribute(e);else return i.data}else f===null?a.removeAttribute(e):(j=a.getAttribute(e),i=JSON.stringify({data:f,expires:g.expires?n+g.expires:null}),a.setAttribute(e,i));try{a.save(d)}catch(o){j===null?a.removeAttribute(e):a.setAttribute(e,j),c.userData();try{a.setAttribute(e,i),a.save(d)}catch(o){j===null?a.removeAttribute(e):a.setAttribute(e,j);throw c.error()}}return m})}})(),function(){function e(a){return a===b?b:JSON.parse(JSON.stringify(a))}var a={},d={};c.addType("memory",function(c,f,g){if(!c)return e(a);if(f===b)return e(a[c]);d[c]&&(clearTimeout(d[c]),delete d[c]);if(f===null){delete a[c];return null}a[c]=f,g.expires&&(d[c]=setTimeout(function(){delete a[c],delete d[c]},g.expires));return f})}()})(this.amplify=this.amplify||{})
|
|
@ -1,9 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
function validate_upload_file(form_passed){
|
|
||||||
|
|
||||||
if (form_passed.datafile.value == "") {
|
|
||||||
alert ("Please browse and select a photo");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
// This function creates and styles the "qTip" tooltip that displays the resource uri and the rdf link when the user clicks the uri/rdf icon.
|
// This function creates and styles the "qTip" tooltip that displays the resource uri and the rdf link when the user clicks the uri/rdf icon.
|
||||||
$('#uriIcon').each(function()
|
$('span#iconControlsLeftSide').children('img#uriIcon').each(function()
|
||||||
{
|
{
|
||||||
$(this).qtip(
|
$(this).qtip(
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,70 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('span#iconControlsVitro').children('img#uriIcon').each(function()
|
||||||
|
{
|
||||||
|
$(this).qtip(
|
||||||
|
{
|
||||||
|
content: {
|
||||||
|
prerender: true, // We need this for the .click() event listener on 'a.close'
|
||||||
|
text: '<h5>share the URI for this profile</h5> <input id="uriLink" type="text" value="' + $('#uriIcon').attr('title') + '" /><h5><a class ="rdf-url" href="' + individualRdfUrl + '">view profile in RDF format</a></h5><a class="close" href="#">close</a>'
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
corner: {
|
||||||
|
target: 'bottomLeft',
|
||||||
|
tooltip: 'topLeft'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
when: {event: 'click'}
|
||||||
|
},
|
||||||
|
hide: {
|
||||||
|
fixed: true, // Make it fixed so it can be hovered over and interacted with
|
||||||
|
when: {
|
||||||
|
target: $('a.close'),
|
||||||
|
event: 'click'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
padding: '1em',
|
||||||
|
width: 400,
|
||||||
|
backgroundColor: '#f1f2ee'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('span#iconControlsRightSide').children('img#uriIcon').each(function()
|
||||||
|
{
|
||||||
|
$(this).qtip(
|
||||||
|
{
|
||||||
|
content: {
|
||||||
|
prerender: true, // We need this for the .click() event listener on 'a.close'
|
||||||
|
text: '<h5>share the URI for this profile</h5> <input id="uriLink" type="text" value="' + $('#uriIcon').attr('title') + '" /><h5><a class ="rdf-url" href="' + individualRdfUrl + '">view profile in RDF format</a></h5><a class="close" href="#">close</a>'
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
corner: {
|
||||||
|
target: 'bottomRight',
|
||||||
|
tooltip: 'topRight'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
when: {event: 'click'}
|
||||||
|
},
|
||||||
|
hide: {
|
||||||
|
fixed: true, // Make it fixed so it can be hovered over and interacted with
|
||||||
|
when: {
|
||||||
|
target: $('a.close'),
|
||||||
|
event: 'click'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
padding: '1em',
|
||||||
|
width: 400,
|
||||||
|
backgroundColor: '#f1f2ee'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Prevent close link for URI qTip from requesting bogus '#' href
|
// Prevent close link for URI qTip from requesting bogus '#' href
|
||||||
$('a.close').click(function() {
|
$('a.close').click(function() {
|
||||||
$('#uriIcon').qtip("hide");
|
$('#uriIcon').qtip("hide");
|
||||||
|
|
177
webapp/web/js/individual/propertyGroupControls.js
Normal file
177
webapp/web/js/individual/propertyGroupControls.js
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
$.extend(this, individualLocalName);
|
||||||
|
adjustFontSize();
|
||||||
|
padSectionBottoms();
|
||||||
|
retrieveLocalStorage();
|
||||||
|
|
||||||
|
// ensures that shorter property group sections don't cause the page to "jump around"
|
||||||
|
// when the tabs are clicked
|
||||||
|
function padSectionBottoms() {
|
||||||
|
$.each($('section.property-group'), function() {
|
||||||
|
var sectionHeight = $(this).height();
|
||||||
|
if ( sectionHeight < 1000 ) {
|
||||||
|
$(this).css('margin-bottom', 1000-sectionHeight + "px");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// controls the property group tabs
|
||||||
|
$.each($('li.clickable'), function() {
|
||||||
|
var groupName = $(this).attr("groupName");
|
||||||
|
var $propertyGroupLi = $(this);
|
||||||
|
|
||||||
|
$(this).click(function() {
|
||||||
|
|
||||||
|
if ( $propertyGroupLi.attr("class") == "nonSelectedGroupTab clickable" ) {
|
||||||
|
$.each($('li.selectedGroupTab'), function() {
|
||||||
|
$(this).removeClass("selectedGroupTab clickable");
|
||||||
|
$(this).addClass("nonSelectedGroupTab clickable");
|
||||||
|
});
|
||||||
|
$propertyGroupLi.removeClass("nonSelectedGroupTab clickable");
|
||||||
|
$propertyGroupLi.addClass("selectedGroupTab clickable");
|
||||||
|
}
|
||||||
|
if ( $propertyGroupLi.text() == "View All" ) {
|
||||||
|
processViewAllTab();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
padSectionBottoms();
|
||||||
|
var $visibleSection = $('section.property-group:visible');
|
||||||
|
$visibleSection.hide();
|
||||||
|
$('h2[pgroup=tabs]').addClass("hidden");
|
||||||
|
$('nav#scroller').addClass("hidden");
|
||||||
|
$('section#' + groupName).show();
|
||||||
|
}
|
||||||
|
manageLocalStorage();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function processViewAllTab() {
|
||||||
|
$.each($('section.property-group'), function() {
|
||||||
|
$(this).css("margin-bottom", "1px");
|
||||||
|
$(this).children('h2').css("margin-top", "-15px").css("border-bottom","1px solid #DFEBE5").css("padding","12px 25px 10px 20px");
|
||||||
|
$(this).show();
|
||||||
|
$('h2[pgroup=tabs]').removeClass("hidden");
|
||||||
|
$('nav#scroller').removeClass("hidden");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next two functions -- keep track of which property group tab was selected,
|
||||||
|
// so if we return from a custom form or a related individual, even via the back button,
|
||||||
|
// the same property group will be selected as before.
|
||||||
|
function manageLocalStorage() {
|
||||||
|
var localName = this.individualLocalName;
|
||||||
|
// is this individual already stored? If not, how many have been stored?
|
||||||
|
// If the answer is 3, remove the first one in before adding the new one
|
||||||
|
var current = amplify.store(localName);
|
||||||
|
var profiles = amplify.store("profiles");
|
||||||
|
if ( current == undefined ) {
|
||||||
|
if ( profiles == undefined ) {
|
||||||
|
var lnArray = [];
|
||||||
|
lnArray.push(localName);
|
||||||
|
amplify.store("profiles", lnArray);
|
||||||
|
}
|
||||||
|
else if ( profiles != undefined && profiles.length >= 3 ) {
|
||||||
|
firstItem = profiles[0];
|
||||||
|
amplify.store(firstItem, null);
|
||||||
|
profiles.splice(0,1);
|
||||||
|
profiles.push(localName);
|
||||||
|
amplify.store("profiles", profiles)
|
||||||
|
}
|
||||||
|
else if ( profiles != undefined && profiles.length < 3 ) {
|
||||||
|
profiles.push(localName);
|
||||||
|
amplify.store("profiles", profiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var selectedTab = [];
|
||||||
|
selectedTab.push($('li.selectedGroupTab').attr('groupName'));
|
||||||
|
amplify.store(localName, selectedTab);
|
||||||
|
var checkLength = amplify.store(localName);
|
||||||
|
if ( checkLength.length == 0 ) {
|
||||||
|
amplify.store(localName, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function retrieveLocalStorage() {
|
||||||
|
var localName = this.individualLocalName;
|
||||||
|
var selectedTab = amplify.store(individualLocalName);
|
||||||
|
|
||||||
|
if ( selectedTab != undefined ) {
|
||||||
|
var groupName = selectedTab[0];
|
||||||
|
|
||||||
|
// unlikely, but it's possible a tab that was previously selected and stored won't be displayed
|
||||||
|
// because the object properties would have been deleted (in non-edit mode). So ensure that the tab in local
|
||||||
|
// storage has been rendered on the page.
|
||||||
|
if ( $("ul.propertyTabsList li[groupName='" + groupName + "']").length ) {
|
||||||
|
// if the selected tab is the default first one, don't do anything
|
||||||
|
if ( $('li.clickable').first().attr("groupName") != groupName ) {
|
||||||
|
// deselect the default first tab
|
||||||
|
var $firstTab = $('li.clickable').first();
|
||||||
|
$firstTab.removeClass("selectedGroupTab clickable");
|
||||||
|
$firstTab.addClass("nonSelectedGroupTab clickable");
|
||||||
|
// select the stored tab
|
||||||
|
$("li[groupName='" + groupName + "']").removeClass("nonSelectedGroupTab clickable");
|
||||||
|
$("li[groupName='" + groupName + "']").addClass("selectedGroupTab clickable");
|
||||||
|
// hide the first tab section
|
||||||
|
$('section.property-group:visible').hide();
|
||||||
|
|
||||||
|
if ( groupName == "viewAll" ) {
|
||||||
|
processViewAllTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
// show the selected tab section
|
||||||
|
$('section#' + groupName).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if there are so many tabs that they wrap to a second line, adjust the font size to
|
||||||
|
//prevent wrapping
|
||||||
|
function adjustFontSize() {
|
||||||
|
var width = 0;
|
||||||
|
$('ul.propertyTabsList li').each(function() {
|
||||||
|
width += $(this).outerWidth();
|
||||||
|
});
|
||||||
|
if ( width < 922 ) {
|
||||||
|
var diff = 926-width;
|
||||||
|
$('ul.propertyTabsList li:last-child').css('width', diff + 'px');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var diff = width-926;
|
||||||
|
if ( diff < 26 ) {
|
||||||
|
$('ul.propertyTabsList li').css('font-size', "0.96em");
|
||||||
|
}
|
||||||
|
else if ( diff > 26 && diff < 50 ) {
|
||||||
|
$('ul.propertyTabsList li').css('font-size', "0.92em");
|
||||||
|
}
|
||||||
|
else if ( diff > 50 && diff < 80 ) {
|
||||||
|
$('ul.propertyTabsList li').css('font-size', "0.9em");
|
||||||
|
}
|
||||||
|
else if ( diff > 80 && diff < 130 ) {
|
||||||
|
$('ul.propertyTabsList li').css('font-size', "0.84em");
|
||||||
|
}
|
||||||
|
else if ( diff > 130 && diff < 175 ) {
|
||||||
|
$('ul.propertyTabsList li').css('font-size', "0.8em");
|
||||||
|
}
|
||||||
|
else if ( diff > 175 && diff < 260 ) {
|
||||||
|
$('ul.propertyTabsList li').css('font-size', "0.73em");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('ul.propertyTabsList li').css('font-size', "0.7em");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the new width
|
||||||
|
var newWidth = 0
|
||||||
|
$('ul.propertyTabsList li').each(function() {
|
||||||
|
newWidth += $(this).outerWidth();
|
||||||
|
});
|
||||||
|
var newDiff = 926-newWidth;
|
||||||
|
$('ul.propertyTabsList li:last-child').css('width', newDiff + 'px');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,12 @@
|
||||||
SELECT ?pred ?predLabel ?obj ?objLabel ?graph
|
SELECT ?pred ?predLabel ?obj ?objLabel ?graph
|
||||||
WHERE
|
WHERE
|
||||||
{
|
{
|
||||||
|
{ <${entity.URI}> ?pred ?obj
|
||||||
|
MINUS { GRAPH ?g { <${entity.URI}> ?pred ?obj } } }
|
||||||
|
UNION
|
||||||
{ GRAPH ?graph { <${entity.URI}> ?pred ?obj} }
|
{ GRAPH ?graph { <${entity.URI}> ?pred ?obj} }
|
||||||
OPTIONAL { GRAPH ?h { ?obj rdfs:label ?objLabel } }
|
OPTIONAL { ?obj rdfs:label ?objLabel }
|
||||||
OPTIONAL { GRAPH ?i { ?pred rdfs:label ?predLabel } }
|
OPTIONAL { ?pred rdfs:label ?predLabel }
|
||||||
} ORDER BY ?graph ?pred
|
} ORDER BY ?graph ?pred
|
||||||
limit 10000"/>
|
limit 10000"/>
|
||||||
<form action="admin/sparqlquery" method="get">
|
<form action="admin/sparqlquery" method="get">
|
||||||
|
@ -54,9 +57,12 @@
|
||||||
SELECT ?sub ?subL ?pred ?predLabel ?graph
|
SELECT ?sub ?subL ?pred ?predLabel ?graph
|
||||||
WHERE
|
WHERE
|
||||||
{
|
{
|
||||||
|
{ ?sub ?pred <${entity.URI}>
|
||||||
|
MINUS { GRAPH ?g { ?sub ?pred <${entity.URI}> } } }
|
||||||
|
UNION
|
||||||
{ GRAPH ?graph { ?sub ?pred <${entity.URI}> } }
|
{ GRAPH ?graph { ?sub ?pred <${entity.URI}> } }
|
||||||
OPTIONAL { GRAPH ?h { ?sub rdfs:label ?subL } }
|
OPTIONAL { ?sub rdfs:label ?subL }
|
||||||
OPTIONAL { GRAPH ?i { ?pred rdfs:label ?predLabel } }
|
OPTIONAL { ?pred rdfs:label ?predLabel }
|
||||||
} ORDER BY ?graph ?pred
|
} ORDER BY ?graph ?pred
|
||||||
limit 10000"/>
|
limit 10000"/>
|
||||||
<form action="admin/sparqlquery" method="get">
|
<form action="admin/sparqlquery" method="get">
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<#-- Default individual profile page template -->
|
<#-- Default individual profile page template -->
|
||||||
<#--@dumpAll /-->
|
<#--@dumpAll /-->
|
||||||
<section id="individual-intro" class="vcard" role="region">
|
<section id="individual-intro" class="vcard" role="region">
|
||||||
|
<section id="share-contact" role="region">
|
||||||
<#-- Image -->
|
<#-- Image -->
|
||||||
<#assign individualImage>
|
<#assign individualImage>
|
||||||
<@p.image individual=individual
|
<@p.image individual=individual
|
||||||
|
@ -18,9 +19,9 @@
|
||||||
<#if ( individualImage?contains('<img class="individual-photo"') )>
|
<#if ( individualImage?contains('<img class="individual-photo"') )>
|
||||||
<#assign infoClass = 'class="withThumb"'/>
|
<#assign infoClass = 'class="withThumb"'/>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<div id="photo-wrapper">${individualImage}</div>
|
<div id="photo-wrapper">${individualImage}</div>
|
||||||
|
</section>
|
||||||
|
<!-- start section individual-info -->
|
||||||
<section id="individual-info" ${infoClass!} role="region">
|
<section id="individual-info" ${infoClass!} role="region">
|
||||||
<#include "individual-adminPanel.ftl">
|
<#include "individual-adminPanel.ftl">
|
||||||
|
|
||||||
|
@ -34,7 +35,8 @@
|
||||||
<@p.label individual editable labelCount />
|
<@p.label individual editable labelCount />
|
||||||
|
|
||||||
<#-- Most-specific types -->
|
<#-- Most-specific types -->
|
||||||
<@p.mostSpecificTypes individual /><img id="uriIcon" title="${individual.uri}" class="middle" src="${urls.images}/individual/uriIcon.gif" alt="uri icon"/>
|
<@p.mostSpecificTypes individual />
|
||||||
|
<span id="iconControlsVitro"><img id="uriIcon" title="${individual.uri}" class="middle" src="${urls.images}/individual/uriIcon.gif" alt="uri icon"/></span>
|
||||||
</h1>
|
</h1>
|
||||||
</#if>
|
</#if>
|
||||||
</header>
|
</header>
|
||||||
|
@ -48,11 +50,17 @@
|
||||||
|
|
||||||
<#assign nameForOtherGroup = "other"> <#-- used by both individual-propertyGroupMenu.ftl and individual-properties.ftl -->
|
<#assign nameForOtherGroup = "other"> <#-- used by both individual-propertyGroupMenu.ftl and individual-properties.ftl -->
|
||||||
|
|
||||||
<#-- Property group menu -->
|
<!-- Property group menu or tabs -->
|
||||||
<#include "individual-propertyGroupMenu.ftl">
|
<#--
|
||||||
|
With release 1.6 there are now two types of property group displays: the original property group
|
||||||
|
menu and the horizontal tab display, which is the default. If you prefer to use the property
|
||||||
|
group menu, simply substitute the include statement below with the one that appears after this
|
||||||
|
comment section.
|
||||||
|
|
||||||
<#-- Ontology properties -->
|
<#include "individual-property-group-menus.ftl">
|
||||||
<#include "individual-properties.ftl">
|
-->
|
||||||
|
|
||||||
|
<#include "individual-property-group-tabs.ftl">
|
||||||
|
|
||||||
<#assign rdfUrl = individual.rdfUrl>
|
<#assign rdfUrl = individual.rdfUrl>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<#if individual.showAdminPanel>
|
<#if individual.showAdminPanel>
|
||||||
<section id="admin">
|
<section id="admin">
|
||||||
<h3>Admin Panel</h3><a class="edit-individual" href="${individual.controlPanelUrl()}" title="edit this individual">Edit this individual</a>
|
<h3 id="adminPanel">Admin Panel</h3><a class="edit-individual" href="${individual.controlPanelUrl()}" title="edit this individual">Edit this individual</a>
|
||||||
|
|
||||||
<section id = "verbose-mode">
|
<section id = "verbose-mode">
|
||||||
<#if verbosePropertySwitch?has_content>
|
<#if verbosePropertySwitch?has_content>
|
||||||
|
|
|
@ -2,29 +2,6 @@
|
||||||
|
|
||||||
<#-- Template for property listing on individual profile page -->
|
<#-- Template for property listing on individual profile page -->
|
||||||
|
|
||||||
<#import "lib-properties.ftl" as p>
|
|
||||||
<#assign subjectUri = individual.controlPanelUrl()?split("=") >
|
|
||||||
<#list propertyGroups.all as group>
|
|
||||||
<#assign groupName = group.getName(nameForOtherGroup)>
|
|
||||||
<#assign verbose = (verbosePropertySwitch.currentValue)!false>
|
|
||||||
|
|
||||||
<section class="property-group" role="region">
|
|
||||||
<nav class="scroll-up" role="navigation">
|
|
||||||
<a href="#branding" title="scroll up">
|
|
||||||
<img src="${urls.images}/individual/scroll-up.gif" alt="scroll to property group menus" />
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<#-- Display the group heading -->
|
|
||||||
<#if groupName?has_content>
|
|
||||||
<#--the function replaces spaces in the name with underscores, also called for the property group menu-->
|
|
||||||
<#assign groupNameHtmlId = p.createPropertyGroupHtmlId(groupName) >
|
|
||||||
<h2 id="${groupNameHtmlId}">${groupName?capitalize}</h2>
|
|
||||||
<#else>
|
|
||||||
<h2 id="properties">Properties</h2>
|
|
||||||
</#if>
|
|
||||||
|
|
||||||
<#-- List the properties in the group -->
|
|
||||||
<#list group.properties as property>
|
<#list group.properties as property>
|
||||||
<article class="property" role="article">
|
<article class="property" role="article">
|
||||||
<#-- Property display name -->
|
<#-- Property display name -->
|
||||||
|
@ -61,5 +38,3 @@
|
||||||
</ul>
|
</ul>
|
||||||
</article> <!-- end property -->
|
</article> <!-- end property -->
|
||||||
</#list>
|
</#list>
|
||||||
</section> <!-- end property-group -->
|
|
||||||
</#list>
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Template for property listing on individual profile page -->
|
||||||
|
|
||||||
|
<#import "lib-properties.ftl" as p>
|
||||||
|
<#assign subjectUri = individual.controlPanelUrl()?split("=") >
|
||||||
|
<#assign nameForOtherGroup = nameForOtherGroup!"other">
|
||||||
|
|
||||||
|
<#if (propertyGroups.all)??>
|
||||||
|
<#assign groups = propertyGroups.all>
|
||||||
|
<#if groups?has_content>
|
||||||
|
<#if (groups?size > 1) || (groups?first).getName(nameForOtherGroup)?has_content>
|
||||||
|
<nav id="property-group-menu" role="navigation">
|
||||||
|
<ul role="list">
|
||||||
|
<#list groups as group>
|
||||||
|
<#assign groupname = group.getName(nameForOtherGroup)>
|
||||||
|
<#if groupname?has_content>
|
||||||
|
<#--create property group html id is the function that will replace all spaces with underscore to make a valid id-->
|
||||||
|
<#assign groupnameHtmlId = p.createPropertyGroupHtmlId(groupname) >
|
||||||
|
<#-- capitalize will capitalize each word in the name; cap_first only the first. We may need a custom
|
||||||
|
function to capitalize all except function words. -->
|
||||||
|
<li role="listitem"><a href="#${groupnameHtmlId}" title="group name">${groupname?capitalize}</a></li>
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
<#list propertyGroups.all as group>
|
||||||
|
<#assign groupName = group.getName(nameForOtherGroup)>
|
||||||
|
<#assign verbose = (verbosePropertySwitch.currentValue)!false>
|
||||||
|
|
||||||
|
<section class="property-group" role="region">
|
||||||
|
<nav class="scroll-up" role="navigation">
|
||||||
|
<a href="#branding" title="scroll up">
|
||||||
|
<img src="${urls.images}/individual/scroll-up.gif" alt="scroll to property group menus" />
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<#-- Display the group heading -->
|
||||||
|
<#if groupName?has_content>
|
||||||
|
<#--the function replaces spaces in the name with underscores, also called for the property group menu-->
|
||||||
|
<#assign groupNameHtmlId = p.createPropertyGroupHtmlId(groupName) >
|
||||||
|
<h2 id="${groupNameHtmlId}">${groupName?capitalize}</h2>
|
||||||
|
<#else>
|
||||||
|
<h2 id="properties">Properties</h2>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#-- List the properties in the group -->
|
||||||
|
<#include "individual-properties.ftl">
|
||||||
|
</section> <!-- end property-group -->
|
||||||
|
</#list>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue