@{@linkplain ThreadRestricted ThreadRestricted}("holds mailLock")
.
*/
public Object mailLock() { return mailLock; }
private final Object mailLock = new Object();
/** Access to the SMTP mail transfer service.
*/
public @ThreadRestricted("holds mailLock") MailSender mailSender()
{
assert Thread.holdsLock( mailLock ); // actually it's the object that is restricted, not this method
return mailSender;
}
private MailSender mailSender; // final after init
/** The mail session for this run of the web interface.
*/
public @ThreadRestricted("holds mailLock") javax.mail.Session mailSession()
{
assert Thread.holdsLock( mailLock ); // actually it's the object that is restricted, not this method
return mailSession;
}
private javax.mail.Session mailSession; // final after init
/** The absolute URI of the static mirror of the context directory, or null if the
* context directory is not statically served. The URI is specified without a
* trailing slash (/).
*
* @see ConstructionContext#setMirroredContextLocation(String)
* @see ConstructionContext#setMirroredContextURI(URI)
* @see VRequestCycle#staticContextLocation()
*/
public URI mirroredContextURI() { return mirroredContextURI; }
private URI mirroredContextURI; // final after init
/** The name that nominally identifies this web interface. It must be valid as the
* local part (before the '@') of an email address, per VoterService.{@linkplain
* VoterService#name() name}().
*
* @see #serviceEmail()
*/
public String name() { return name; }
private String name; // final after init
/** The top navigation bar for navigating among the pages of the vote-server.
*/
public static NavBar navBar() { return navBar; }
private static NavBar navBar; // final after static init
// /** The directory for storage of persistent files that are generated by the web
// * interface. The directory is created at runtime if it did not already exist.
// *
// * This is the same as the vote-server output directory if that directory is // * writeable by the web interface (servlet container); otherwise, it is some other, // * fallback directory.
// * // * // * @see VoteServer#outDirectory() // */ // public File outDirectory() { return outDirectory; } // // // private File outDirectory; // final after init /** The application scope for instances of WP_Activity. */ public WP_Activity.ApplicationScope scopeActivity() { return scopeActivity; } private WP_Activity.ApplicationScope scopeActivity; // final after init /** The application scope for instances of WP_Draft. */ public WP_Draft.ApplicationScope scopeDraft() { return scopeDraft; } private WP_Draft.ApplicationScope scopeDraft; // final after init /** The email address that nominally identifies the web interface. It is constructed * from the interface and server names, as: * *{@linkplain #name() * INTERFACE-NAME}@{@linkplain VoteServer#serverName() * SERVER-NAME}* *
Email authentication messages to users will be sent from this address. * The mail meta-service ought to respond helpfully to any message that happens to be * sent in reply, to this address.
* * @see ConstructionContext#setName(String) * @see votorola.s.mail.MailMetaService * @see votorola.s.mail.MailMetaService#serviceEmail(VoterService) */ public String serviceEmail() { return serviceEmail; } private String serviceEmail; // final after init /** The spool that is unwound prior to destruction of the web interface. */ public Spool spool() { return spool; } private final Spool spool = new SpoolT(); // need this earlier? you'd be better off refering it from init(), which has an exception handler /** The startup configuration file 'vowicket.js' for this web interface. The language * is JavaScript. There are restrictions on the {@linkplain * votorola.g.script.JavaScriptIncluder character encoding}. * * @see ../../manual.xht#vowicket.js */ File startupConfigurationFile() { return startupConfigurationFile; } private File startupConfigurationFile; // final after init /** The vote-server run for which this web interface is provided. */ public final VoteServer.Run vsRun() { return vsRun; } private VoteServer.Run vsRun; // final after init // - A p p l i c a t i o n ------------------------------------------------------------ /** Returns the intance of VOWicket associated with the current thread. * * @see Session#get() */ public static VOWicket get() { return (VOWicket)WebApplication.get(); } public @Override Class extends Page> getHomePage() { return WP_Server.class; } protected @Override IConverterLocator newConverterLocator() { final ConverterLocator cL = new ConverterLocator(); // cL.set( java.util.regex.Pattern.class, new votorola.g.util.regex.WicPatternConverter() ); //// till needed again cL.set( IDPair.class, new IDPairConverter() ); return cL; } public @Override Session newSession( final Request request, final Response response ) { return new VSession( (WebRequest)request, (WebResponse)response, VOWicket.this ); } protected @Override void onDestroy() { spool.unwind(); super.onDestroy(); } // ==================================================================================== /** A context for configuring the web interface. The web interface is configured by * its {@linkplain #startupConfigurationFile startup configuration file}, which * contains a script (s) for that purpose. During construction of the web interface, * an instance of this context is passed to s, via s::constructingVOWicket(wicCC). * *After the interface is running, it itself is passed to s, via * s::initializingVOWicket({@linkplain VOWicket wic}).
*/ public static @ThreadSafe final class ConstructionContext { /** Constructs the complete configuration of the web interface. * * @param s the compiled startup configuration script. */ private static ConstructionContext configure( VoteServer _voteServer, String _contextPath, final JavaScriptIncluder s ) throws ScriptException, URISyntaxException { final ConstructionContext cc = new ConstructionContext( _voteServer, _contextPath, s ); s.invokeKnownFunction( "constructingVOWicket", cc ); return cc; } private ConstructionContext( final VoteServer voteServer, final String contextPath, final JavaScriptIncluder s ) { startupConfigurationFile = s.scriptFile(); mailTransferService = new SMTPTransportX.ConstructionContext( startupConfigurationFile ); name = voteServer.name(); try { defaultPageIcon = new URI( contextPath + "/icon-16.png" ); } catch( URISyntaxException x ) { throw new RuntimeException( x ); } } private final File startupConfigurationFile; // -------------------------------------------------------------------------------- /** The class of user authenticator for the web interface. * * @see VOWicket#authenticator() * @see #setAuthenticatorClass(Class) */ public Class extends Authenticator> getAuthenticatorClass() { return authenticatorClass; } private Class extends Authenticator> authenticatorClass = votorola.a.web.wic.authen.OpenIDAuthenticator.class; /** Sets the class of user authenticator for the web interface. Set it like * this, for example:* * wicCC.setAuthenticatorClass( * Packages.votorola.a.web.wic.authen.WikiAuthenticator );* *
The default class is {@linkplain * votorola.a.web.wic.authen.OpenIDAuthenticator OpenIDAuthenticator}.
* * @see VOWicket#authenticator() */ @ThreadRestricted("constructor") public void setAuthenticatorClass( final Class extends Authenticator> cl ) { authenticatorClass = cl; } /** The location of default page icon, or null if the location is the default. * * @see VOWicket#defaultPageIcon() * @see #setDefaultPageIcon(String) * @see #setDefaultPageIcon(URI) */ public URI getDefaultPageIcon() { return defaultPageIcon; } private URI defaultPageIcon = null; /** Sets the location of default page icon. The default value is "{@linkplain * #name() vote-server}/icon-16.png". * * @see VOWicket#defaultPageIcon() */ @ThreadRestricted("constructor") public void setDefaultPageIcon( final String s ) throws URISyntaxException { setDefaultPageIcon( new URI( s )); } /** Sets the location of default page icon. The default value is "{@linkplain * #name() vote-server}/icon-16.png". * * @see VOWicket#defaultPageIcon() */ @ThreadRestricted("constructor") public void setDefaultPageIcon( final URI uri ) { defaultPageIcon = uri; } /** The site-specific, customized insert for the 'head' section. * * @see VOWicket#htmlHeaderInsert() * @see #setHTMLHeaderInsert(String) */ public String getHTMLHeaderInsert() { return htmlHeaderInsert; } private String htmlHeaderInsert; /** Sets the site-specific, customized insert for the 'head' section. * * @see VOWicket#htmlHeaderInsert() */ @ThreadRestricted("constructor") public void setHTMLHeaderInsert( final String _htmlHeaderInsert ) { htmlHeaderInsert = _htmlHeaderInsert; } /** The absolute URI of the static mirror of the context directory, or null if the * context directory is not statically served. * * @see VOWicket#mirroredContextURI() * @see #setMirroredContextLocation(String) * @see #setMirroredContextURI(URI) */ public URI getMirroredContextURI() { return mirroredContextURI; } private URI mirroredContextURI = null; /** Sets absolute URI of the static mirror of the context directory. The * default value is null which means the context directory is not statically * served. * * @see VOWicket#mirroredContextURI() * @throws IllegalArgumentException if the URI ends with a slash '/' character. */ @ThreadRestricted("constructor") public void setMirroredContextLocation( final String s ) throws URISyntaxException { setMirroredContextURI( new URI( s )); } /** Sets absolute URI of the static mirror of the context directory. The * default value is null which means the context directory is not statically * served. * * @see VOWicket#mirroredContextURI() * @throws IllegalArgumentException if the URI ends with a slash '/' character. */ public @ThreadRestricted("constructor") void setMirroredContextURI( final URI uri ) { if( uri != null && uri.toString().endsWith( "/" )) { throw new IllegalArgumentException( "URI ends with '/'" ); } mirroredContextURI = uri; } /** The name that nominally identifies the web interface and is used to construct * its service email address. * * @see VOWicket#name() * @see VOWicket#serviceEmail() * @see #setName(String) */ public String getName() { return name; } private String name; /** Sets the name that nominally identifies the web interface, and is used to * construct its service email address. The default value is the {@linkplain * VoteServer#name() vote-server name}. * * @see VOWicket#name() * @see VOWicket#serviceEmail() */ @ThreadRestricted("constructor") public void setName( String _name ) { name = _name; } /** The context for configuring access to the mail transfer server, * through which outgoing messages (for email address authentication) are sent. */ public SMTPTransportX.ConstructionContext mailTransferService() { return mailTransferService; } private final SMTPTransportX.ConstructionContext mailTransferService; } //// P r i v a t e /////////////////////////////////////////////////////////////////////// private void ensureWriteable( final File dir ) throws IOException { if( !dir.canWrite() ) // writeable by servlet container? { throw new IOException( "web interface (" + System.getProperty("user.name") + ") lacks write permissions for directory: " + dir ); // fail fast } } /** Set at init start, cleared at end. */ private final AtomicReference