package votorola.a.trust; // Copyright 2010-2012, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE. import java.io.*; import java.util.*; import java.util.concurrent.locks.*; import java.util.logging.*; import java.sql.*; import javax.mail.internet.*; import javax.script.*; import votorola.a.*; import votorola.a.response.*; import votorola.a.voter.*; import votorola.g.lang.*; import votorola.g.logging.*; import votorola.g.script.*; import votorola.g.sql.*; import votorola.g.util.*; /** A trust server. * * @see Stuff:Trustserver */ @ThreadRestricted("holds lock()") public final class Trustserver extends VoterService { // cf. a/count/PollService /** Constructs a Trustserver. * * @param s the compiled startup configuration script. */ public static @ThreadSafe Trustserver newTrustserver( final VoteServer.Run run, final JavaScriptIncluder s ) throws IOException, ScriptException, SQLException { final ConstructionContext cc = new ConstructionContext( run.voteServer(), s ); s.invokeKnownFunction( "constructingTrustserver", cc ); return new Trustserver( run, cc ); } private Trustserver( final VoteServer.Run run, final ConstructionContext cc ) throws IOException, ScriptException, SQLException { super( run, cc ); init( new ArrayList() ); constructionContext = null; // done with it, free the memory } private ConstructionContext cc() { return (ConstructionContext)constructionContext; } // nulled after init // ```````````````````````````````````````````````````````````````````````````````````` // init for early use private final File startupConfigurationFile = cc().startupConfigurationFile(); // ------------------------------------------------------------------------------------ /** The trustserver's facility for converting street addresses to cartographic * coordinates. */ public @ThreadSafe GoogleGeocoder geocoder() { return geocoder; } private final GoogleGeocoder geocoder = new GoogleGeocoder( vsRun.geocodeTable() ); /** Retrieves a registrant's node from a compiled network trace. This is a * convenience method. * * @param trace the trace to use. This may be null, causing lookup the currently * {@linkplain #traceToReport() reported trace}. Note that lookup involves * locking overhead in threaded runs. * * @return TraceNodeW or TraceNodeIC per {@linkplain * TraceNodeW.Table#getOrCreate(IDPair) getOrCreate}(registrant). Or, if * lookup of the trace itself fails, a TraceNode0 with default values. */ public @ThreadSafe TraceNode getTraceNode( NetworkTrace trace, final IDPair registrant ) throws IOException, SQLException { if( trace == null ) trace = traceToReportT(); return trace == null? new TraceNode0( registrant ): trace.traceNodeTable().getOrCreate( registrant ); } /** The primary trust to extend for each trace of the trust network. * * @return unmodifiable list of primary trust extensions. * * @see ConstructionContext#addPrimaryTrust(IDPair,int) */ List primaryTrustList() { return primaryTrustList; } private final ArrayListU primaryTrustList = new ArrayListU( cc().getPrimaryTrustArray() ); /** The compiled runtime-configuration script for the trustserver. Its source file is * located at: * *

~/{@linkplain VoteServer#votorolaDirectory() * votorola}/trust/trustserver-run.js

* *

The language is JavaScript. There are restrictions on the {@linkplain * votorola.g.script.JavaScriptIncluder character encoding}.

* * @see trustserver-run.js (example script) * @see ../manual.xht#trustserver-run.js (FIX broken docs) */ @Warning( "thread restricted object" ) public JavaScriptIncluder runtimeConfigurationScript() { assert lock.isHeldByCurrentThread(); // this method is safe, but not the object return runtimeConfigurationScript; } private final JavaScriptIncluder runtimeConfigurationScript = new JavaScriptIncluder( new File( serviceDirectory(), "trustserver-run.js" )); /** The current network trace to report, or null if there is none. * * @see votorola.a.trust.NetworkTrace.VoteServerScope#readyToReportLink() */ public NetworkTrace traceToReport() throws IOException, SQLException { assert lock.isHeldByCurrentThread(); final File readyToReportLink = vsRun.voteServer().scopeTrace().readyToReportLink(); ReadyDirectory readyDirectory = null; // so far if( readyToReportLink.exists() ) { readyDirectory = new ReadyDirectory( readyToReportLink.getCanonicalPath() ); } if( readyDirectory == null ) { if( traceToReport != null ) { logger.info( readyToReportLink + ": link is lost, stopping report: " + traceToReport.readyDirectory() ); traceToReport = null; } return traceToReport; } if( !readyDirectory.isMounted() ) { logger.warning( readyToReportLink + ": trace not mounted: " + readyDirectory ); traceToReport = null; return traceToReport; } if( traceToReport == null || !traceToReport.isObjectReadFromSerialFile( readyDirectory )) { logger.info( "starting new trace report: " + readyDirectory ); traceToReport = NetworkTrace.readObjectFromSerialFile( readyDirectory ); final Database d = vsRun.database(); traceToReport.init( new Membership.Table( readyDirectory, d ), new TraceNodeW.Table( readyDirectory, d )); } return traceToReport; } private NetworkTrace traceToReport; // lazily set/reset through traceToReport() /** The current network trace to report, or null if there is none. This is just a * thread safe wrapper that automatically siezes and releases the lock. */ public @ThreadSafe NetworkTrace traceToReportT() throws IOException, SQLException { lock.lock(); try { return traceToReport(); } finally { lock.unlock(); } } // - V o t e r - S e r v i c e -------------------------------------------------------- /** @see ../manual.xht#trustserver.js (FIX broken docs) */ public @ThreadSafe @Override File startupConfigurationFile() { return startupConfigurationFile; } /** @see ConstructionContext#setSummaryDescription(String) */ public @ThreadSafe @Override String summaryDescription() { return summaryDescription; } private final String summaryDescription = cc().getSummaryDescription(); /** @see ConstructionContext#setTitle(String) */ public @ThreadSafe @Override String title() { return title; } private final String title = cc().getTitle(); // ==================================================================================== /** A context for configuring the construction of a {@linkplain Trustserver * Trustserver}. Each construction is configured by the trusterver's {@linkplain * Trustserver#startupConfigurationFile startup configuration script} (s). During * construction, an instance of this context (tCC) is passed to s, via * s::constructingTrustserver(tCC). */ public static @ThreadRestricted("constructor") final class ConstructionContext extends VoterService.ConstructionContext { private ConstructionContext( VoteServer _voteServer, final JavaScriptIncluder s ) { super( "trustserver", s ); voteServer = _voteServer; setSummaryDescription( "This is the trustserver. " + "Further information is unavailable because the 'constructingTrustserver' function " + "of script " + startupConfigurationFile() + " " + "makes no call to 'setSummaryDescription'." ); } // -------------------------------------------------------------------------------- /** The primary trust to extend for each trace of the trust network. * * @see #addPrimaryTrust(IDPair,int) */ public TrustEdge.Primary[] getPrimaryTrustArray() { return primaryTrustList.toArray( new TrustEdge.Primary[primaryTrustList.size()] ); } private final ArrayList primaryTrustList = new ArrayList(); /** Adds primary trust extensions. By default, there are no primary trust * extensions and therefore no trust at all in compiled networks. * * @see #getPrimaryTrustArray() */ public void addPrimaryTrust( final IDPair registrant1, final int edgeCount ) { primaryTrustList.add( new TrustEdge.Primary( registrant1, edgeCount )); } /** Adds primary trust extensions for the specified registrant. This is a * convenience method. * * @see #addPrimaryTrust(IDPair,int) */ public void addPrimaryTrustForUsername( final String registrant1Username, final int edgeCount ) throws AddressException { addPrimaryTrust( IDPair.fromUsername(registrant1Username), edgeCount ); } /** @see Trustserver#summaryDescription() * @see #setSummaryDescription(String) */ public String getSummaryDescription() { return summaryDescription; } private String summaryDescription; /** Sets the summary description of the trustserver. The default value is a * placeholder with configuration instructions for the administrator. * * @throws IllegalArgumentException if the description contains any * newline characters, because they might render inconsistently across * different types of user interface. * @see Trustserver#summaryDescription() */ public void setSummaryDescription( String summaryDescription ) { if( summaryDescription.indexOf('\n') >= 0 ) throw new IllegalArgumentException( "argument contains a newline character" ); this.summaryDescription = summaryDescription; } /** @see Trustserver#title() * @see #setTitle(String) */ public String getTitle() { return title; } private String title = "Trustserver"; /** Sets the title of the trustserver. The default value is "Trustserver". * * @see Trustserver#title() */ public void setTitle( String title ) { this.title = title; } /** The vote-server. */ public VoteServer voteServer() { return voteServer; } private final VoteServer voteServer; } //// P r i v a t e /////////////////////////////////////////////////////////////////////// private static final Logger logger = LoggerX.i( Trustserver.class ); }