001    /*
002    Copyright (c) 1996-2011, Damon Hart-Davis
003    All rights reserved.
004    
005    Redistribution and use in source and binary forms, with or without
006    modification, are permitted provided that the following conditions are
007    met:
008    
009      * Redistributions of source code must retain the above copyright
010        notice, this list of conditions and the following disclaimer.
011    
012      * Redistributions in binary form must reproduce the above copyright
013        notice, this list of conditions and the following disclaimer in the
014        documentation and/or other materials provided with the
015        distribution.
016    
017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
018    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
019    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
020    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028    */
029    
030    package org.hd.d.pg2k.svrCore;
031    
032    import java.text.SimpleDateFormat;
033    import java.util.Collections;
034    import java.util.HashSet;
035    import java.util.Set;
036    
037    /**This holds fundamental compile-time constants for all parts of PG2K.
038     */
039    public final class CoreConsts
040        {
041        /**Default name by which whole app is known internally. */
042        public static final String APP_DEFAULT_NAME = "PG2K";
043    
044        /**Role name (user/group) to for most priv actions. */
045        public static final String PRIV_ROLE_NAME = "admin";
046    
047        /**8-bit ISO-8859-1 file encoding. */
048        public static final String FILE_ENCODING_8859_1 = "ISO-8859-1";
049    
050        /**8-bit UTF-8 file encoding. */
051        public static final String FILE_ENCODING_UTF_8 = "UTF-8";
052    
053        /**7-bit ASCII file encoding, also by definition valid ISO-8859-1 and UTF-8. */
054        public static final String FILE_ENCODING_ASCII7 = "ASCII";
055    
056        /**Name of main exhibit and catalogue-page server host(s); generally sessionless.
057         * This may be an alias to one or more hosts.
058         * <p>
059         * This is rendered all lower-case to slightly improve compressability
060         * in certain contexts, and is also prefixless (eg no "www.")
061         * to be in canonical form.
062         * <p>
063         * This is also a base name of which some subdomains are significant, eg as mirrors.
064         */
065        public static final String MAIN_DATA_HOST = "gallery.hd.org";
066    
067        /**Default temporal slackness in seconds; strictly positive.
068         * This is the default slackness or inconsistency that we will
069         * allow in the system in order to gain efficiency.
070         * <p>
071         * This can be used, for example, as a default time for
072         * which exhibits and catalogue pages may be cached by a
073         * client, and that we might internally cache exhibit
074         * properties, etc.
075         * <p>
076         * Note that it may sometimes be necessary to ensure that
077         * multiples of this interval cannot be catenated in bad
078         * cases.
079         */
080        public static final int DEFAULT_TEMPORAL_SLACKNESS_S = 3600;
081    
082        /**Approximate start date of the Gallery, primarily for validating timestamps, etc; strictly positive.
083         * No exhibit timestamp or accession date should be older than this
084         * (nor newer than "now" allowing for clock skew).
085         * <p>
086         * Other dates may be validated with reference this value.
087         * <p>
088         * It is probably accurate enough to use in synthetic copyright notices too.
089         * <p>
090         * The Gallery started in 1996/1997.
091         * <p>
092         * For reference:
093         * <ul>
094         * <li>1996/01/01 00:00 UTC = 820454400000.  Calculated with (new Date(96,0,1,0,0)).getTime().
095         * <li>1997/01/01 00:00 UTC = 852076800000.  Calculated with (new Date(97,0,1,0,0)).getTime().
096         * </ul>
097         */
098        public static final long GALLERY_EPOC_START = 820454400000L; // 1996/01/01 00:00 UTC
099        //static { System.err.println("GALLERY_EPOC_START = " + GALLERY_EPOC_START); }
100    
101        /**java:comp/env usual JNDI namespace prefix for EJBs... */
102        public static final String JNDI_COMPENV_PREFIX = "java:comp/env/";
103    
104        /**Short JNDI name by which ExhibitFacade front-end (session) bean is accessed. */
105        public static final String JNDI_SHORT_NAME_ExhibitFacade = "ejb/ExhibitFacade";
106    
107        /**Short JNDI name by which PropsFacade front-end (session) bean is accessed. */
108        public static final String JNDI_SHORT_NAME_PropsFacade = "ejb/PropsFacade";
109    
110    
111    
112        /**Default dase dir for exhibit data load from filesystem. */
113        public static final String FS_DATA_ROOT = "fs_data";
114    
115        /**Default base dir for meta-data load from filesystem. */
116        public static final String FS_CONF_ROOT = "fs_conf";
117    
118        /**Filesystem path below conf root for load/save of global system properties. */
119        public static final String FS_CONF_SYSPROPS = "sys.props";
120    
121        /**Filesystem path below conf root for load/save of private security properties. */
122        public static final String FS_CONF_SECPROPS = "security.props";
123    
124    //    /**FIXME: REMOVE: Name of pre-PG2K location database (properties) file; only file component. */
125    //    public static final String FS_CONF_PREPG2K_LOCDB_FILENAME = "auxInfo.txt";
126    
127        /**Name of static properties cache file usually within data directory.
128         * For most purposes this is read-only,
129         * but some applications are able to write to it to atomically update it.
130         */
131        public static final String FS_DATA_CACHE_FILENAME = "_expropsCache.dat";
132    
133        /**Name of static properties hash file usually within data directory.
134         * Contains the long hash of the AEP last loaded/assembled from the filesystem.
135         * <p>
136         * Typically, removing this file,
137         * or specifying an old/extant AEP hash different to this,
138         * will force the AEP to be reconstructed from the filesystem.
139         * <p>
140         * For most purposes this is read-only,
141         * but some applications are able to write to it to atomically update it.
142         * <p>
143         * This file should be (maybe manually) removed
144         * once new exhibits have been added/changed.removed;
145         * this will prompt scanning for changes.
146         */
147        public static final String FS_DATA_HASH_FILENAME = "_removeMeToScanForChanges.hash";
148    
149        /**Immutable Set of all configuration filenames (as String values). */
150        public static final Set<String> ALL_FS_CONF_FILENAMES;
151        static
152            {
153            // Provide a small but perfectly formed HashSet for quick access.
154            final Set<String> afcf = new HashSet<String>(7);
155            // Manually add in all the names here.
156            afcf.add(FS_CONF_SYSPROPS);
157            afcf.add(FS_CONF_SECPROPS);
158            // Make an unmodifiable version available...
159            ALL_FS_CONF_FILENAMES = Collections.unmodifiableSet(afcf);
160            }
161    
162        /**Name of properties class/file on classpath containing simple global properties.
163         * This does not include a file suffix.
164         */
165        public static final String GLOBAL_PROPS_NAME = "Global";
166    
167        /**Name of properties class/file on classpath or in exhibits area containing built-in location-map data.
168         * This does not include a file suffix.
169         */
170        public static final String LOCDB_PROPS_NAME = "locationDB";
171    
172        /**Name of WAR context-param boolean flag to set cache aggressiveness. */
173        public static final String WAR_CTXTPARAM_AGGRESSIVE_CACHE = "aggressiveCacheing";
174    
175        /**Name of WAR context-param `master/slave/etc' flag. */
176        public static final String WAR_CTXTPARAM_DISPOSITION = "disposition";
177    
178        // Valid disposition names.
179        /**Master (J2EE) taking data from EJBs (and probably not with / context root). */
180        public static final String WAR_CTXTPARAM_DISPOSITION_MASTER = "master";
181        /**Master (pure WAR) taking data from filesystem, with / context root. */
182        public static final String WAR_CTXTPARAM_DISPOSITION_WARONLY = "waronly";
183        /**Slave (pure WAR) taking data over HTTP tunnel, with / context root. */
184        public static final String WAR_CTXTPARAM_DISPOSITION_SLAVE = "slave";
185    
186    //    /**Name of system property for ``waronly'' indicating root of (read-only) config info. */
187    //    public static final String WAR_SYSPROPNAME_WARONLY_CONFIGROOT = "org.hd.d.pg2k.WAR.waronly.configroot";
188    //    /**Name of system property for ``waronly'' indicating root of (read-only) exhibit data. */
189    //    public static final String WAR_SYSPROPNAME_WARONLY_EXHIBITROOT = "org.hd.d.pg2k.WAR.waronly.exhibitdataroot";
190    //    /**Name of system property for ``waronly'' indicating location of master-readable serialised, compressed, exhibit properties object. */
191    //    public static final String WAR_SYSPROPNAME_WARONLY_STATICCACHEFILE = "org.hd.d.pg2k.WAR.waronly.staticcachefile";
192    //    /**Name of system property for ``waronly'' indicating root of (read-write) meta-data cache. */
193    //    public static final String WAR_SYSPROPNAME_WARONLY_RWMETADATAROOT = "org.hd.d.pg2k.WAR.waronly.metadatacacheroot";
194    //    /**Name of system property for ``waronly'' indicating root of (read-write) log area. */
195    //    public static final String WAR_SYSPROPNAME_WARONLY_LOGROOT = "org.hd.d.pg2k.WAR.waronly.logroot";
196    
197    //    /**Name of system property for ``waronly'' indicating the comma-separated list of properties files from which global exhibit data may be extracted. */
198    //    public static final String WAR_SYSPROPNAME_WARONLY_EXGLOBDATA = "org.hd.d.pg2k.WAR.waronly.exglobdata";
199    
200    
201        /**The WAR context-param `master/slave' flag can be set early with this named system property.
202         * This allows the WAR front-end to start-up faster in some circumstances,
203         * but if this is not set, or not set to a usable value, the WAR front-end
204         * will resort to its default method of determining master/slave disposition.
205         * <p>
206         * The property value must not <em>conflict</em> with that deduced my the
207         * default methods, if this property is defined at all.
208         */
209        public static final String WAR_SYSPROPNAME_DISPOSITION_PRESET = "org.hd.d.pg2k.WAR.disposition";
210    
211    
212        /**Name of WAR context-param boot-server URL. */
213        public static final String WAR_CTXTPARAM_BOOTURL = "bootServerURL";
214    
215    
216    
217        /**Our preferred simple date formater for all locales; yyyy/MM/dd Japanese style.
218         * FIXME: note that SimpleDateFormat is not immutable.
219         */
220        public static final SimpleDateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd");
221    
222        /**Maximum length of description entry (or entries) in characters. */
223        public static final int DESCRIPTION_MAX_CHARS = 2048;
224    
225        /**Description suffix on full path name of exhibit. */
226        public static final String DESCRIPTION_FILE_SUFFIX = ".txt";
227    
228        /**Minimum password length for all (eg Web) logins; strictly positive. */
229        public static final int MIN_PASSWORD_LEN = 4;
230        /**Maximum password length for all (eg Web) logins; strictly positive. */
231        public static final int MAX_PASSWORD_LEN = 16;
232    
233    
234        /**Time short enough not to be noticable to users in GUI interactions, ms; strictly positive.
235         * Humans are said not to notice delays of 100ms or less.
236         */
237        public static final int MAX_INTERACTIVE_DELAY_MS = 100;
238    
239        /**Maximum time that a typical inter-server RPC call should take (eg round the Earth, over the Internet), ms; strictly positive.
240         * This allows a realistic connection set-up and tear-down time
241         * on top of a generous time to process a moderately-complex request
242         * and shift a decent-size serialised payload over a busy link.
243         * <p>
244         * Some RPCs call may legitimately take (much) longer than this,
245         * so this should be used as a limit to stop blocking interactively for a response,
246         * but not to kill the request entirely
247         * (ie so that we can still hope to make progress in the background for next time).
248         * <p>
249         * This should be at least second or more,
250         * and possibly as much as 10--20 seconds (see below),
251         * but not so long as to completely kill interactivity
252         * of on-the-fly generated pages such as JSPs that force RPCs.
253         * <p>
254         * Some observed legitimate common RPCs take ~10s--20s because of bandwidth limits,
255         * eg for large event sets, even after compression.
256         * <p>
257         * (Note that in Windows NT the hard-wired initial HTTP TCP timeout was 3s,
258         * which seems to have been a little too short for legitimate long-delay paths.)
259         */
260        public static final int MAX_TYPICAL_RPC_RTT_MS = 7013;
261    
262    
263        /**Checksum/hash for data to correspond to use in tools such as [G]ZIP; not "secure".
264         * Not a secure hash,
265         * but used "as if" in some non-critical places as a quick cross-check,
266         * and used in ZIP archive so quick to compare against ZIP entries.
267         */
268        public static final String HASH_CRC32 = "CRC32";
269    
270        /**Preferred hash for data integrity; reasonably "secure". */
271        public static final String HASH_SHA1 = "SHA1";
272    
273        /**Alternative fast hash for data integrity; reasonably "secure".
274         * Not as secure as SHA-1, but possibly a good alternative/cross-check,
275         * and commonly used for simple integrity checking,
276         * eg with the HTTP Content-MD5 header.
277         */
278        public static final String HASH_MD5 = "MD5";
279    
280        /**HMAC authentication hash algorithm to protect data in transit.
281         * Although we use a MAC primarily to guard against data corruption on the wire,
282         * we also want to provide some protection against tampering and replay attacks,
283         * eg someone trying to slip p0rn or warez or trojans into the datastream to a slave.
284         * <p>
285         * Thus we want a strong-ish hash that is relatively collision-free,
286         * though hopefully not too expensive to compute
287         * nor contributing too much message overhead (ie too large a hash/MAC).
288         * <p>
289         * Note that our key generation and distribution is not necessarily very robust,
290         * ie anyone with access to any of the servers as root could steal the key,
291         * and thus tamper/insert to their heart's content, so we should not go overboard.
292         * This mechanism should prevent corruption and casual tampering by ISPs,
293         * transparent proxies, broken routers, and others that can play "man-in-the-middle",
294         * but without admin access to any servers.
295         * Note that this does not prevent any "man-in-the-middle" from
296         * <em>observing</em> all our traffic; we only need authetication, not encryption.
297         * <p>
298         * Note that not all communications need to be guarded by this MAC;
299         * in particular read-only operations by lightweight clients may not be
300         * (at least in part so that we do not need to distribute the secret key to them)
301         * which may save some CPU cycles and a little bandwidth.
302         * In particular we may respond without a MAC to a request without a (valid) MAC,
303         * which may also make it harder for an imposter to probe for our key.
304         * <p>
305         * The algorithm must be supported by the JDK or a plugged-in provider.
306         * <p>
307         * MD5 and SHA-1 are showing signs of age and weakness,
308         * so we need to use something of at least SHA-256 (256-bit) strength.
309         * All implementations wishing to communicate must agree on this algorithm.
310         */
311        public static final String HMAC_ALG = "HmacSHA256";
312    
313    
314        /**Max age of an exhibit to be considered "new", in seconds; strictly positive.
315         * A value of a few weeks to a few months is probably appropriate
316         * given observed visitor frequency and upload rate of new exhibits.
317         */
318        public static final int MAX_EXHIBIT_AGE_NEW_S = 183 * 24 * 3600; // 6 months.
319    
320        /**Max age of an exhibit to be considered "new", in milliseconds; strictly positive.
321         * A value of a few weeks to a few months is probably appropriate
322         * given observed visitor frequency and upload rate of new exhibits.
323         */
324        public static final long MAX_EXHIBIT_AGE_NEW_MS = MAX_EXHIBIT_AGE_NEW_S * 1000L;
325    
326    
327        /**If true, avoid using connection and read timeouts on sockets.
328         * Under JDK 1.5.0 (and probably 1.4.x), using read and connection timeouts
329         * forces the VM to use non-blocking I/O which in turn can lead to fd leaks
330         * and other problems.
331         */
332        public static final boolean AVOID_UNSAFE_TCP_TIMEOUTS = false;
333    
334        /**Suggested transfer size of exhibit data (and some other bulk data).
335         * We will usually copy (exhibit) data around in chunks of about this size
336         * (or a small power-of-2 multiple of this size).
337         * This applies to transfer to/from local media,
338         * such as disc, and over slow (eg network) media.
339         * <p>
340         * This is large enough to be efficient and to allow the OS
341         * to be buffering up data for good throughput over TCP/IP for example,
342         * but small enough not to require stupid amounts of memory or time
343         * (and in particular to retain reasonable interactivity).
344         * <p>
345         * A power of two for efficiency in various places.
346         * <p>
347         * A size of about 1kByte to 64kBytes is probably reasonable;
348         * 16kB or less seems good to retain interactivity.
349         */
350        public static final int BULK_DATA_TRANSFER_SIZE = (1<<14);
351    
352        /**Do-nothing page root-relative URL that will accept any parameters and does no work. */
353        public static final String DO_NOTHING_PAGE_RRURL = "/null.jsp";
354    
355        /**Tunnel URL on server. */
356        public static final String TUNNEL_URI = "/_tunnel";
357    
358    
359        /**GenProps debug flag tree root, including trailing dot. */
360        public static final String GEN_PREFIX_debugFlag = "debugFlag.";
361    
362        /**Maximum permissible clock skew between any two PG2K server instances, ms; strictly positive.
363         * Of the order of a few minutes is good.
364         */
365        public static final int MAX_PEER_CLOCK_SKEW_MS = 3 * 60 * 1000;
366    
367        /**Prefix of i18n-ed attribute word descriptions.
368         * The required attribute word can be appended to this and looked up in the common catalogue
369         * for a (possibly localised) description: many not be present for all attributes.
370         */
371        public static final String ATTR_I18N_DESC_PREFIX = "org.hd.pg2k.attribute.word.description.";
372    
373        /**Prefix of i18n-ed symbolic filter times.
374         * The symbolic name should be appended to this and looked up in the common catalogue
375         * for a (possibly localised) description: many not be present for all attributes.
376         */
377        public static final String SYMTIME_I18N_PREFIX = "common.cat.filtersince.recent.";
378    
379        /**Target minimum interval of flushes of non-critical data to disc or persistent store in power-save mode; strictly positive (ms).
380         * This should probably be a small multiple of the underlying disc write interval,
381         * eg for the default linux-laptop-mode disc-flush interval which is 10 minutes,
382         * allowing for the fact that various components may cache private data asynchronously.
383         * <p>
384         * System components that observe this value should take especial care to flush
385         * when the application/JVM shuts down to avoid losing large amounts of data.
386         * <p>
387         * This is not intended to regulate the flushing of critical data.
388         * <p>
389         * Several tens of minutes is probably good.
390         */
391        public static final int ASYNC_MIN_POWER_SAVE_NON_CRITICAL_DATA_FLUSH_MS = 20 * 60 * 1000; // 20 minutes.
392    
393        /**Maximum time that we expect the system to have to remain in low-power mode in one stretch (ms); strictly positive.
394         * We attempt to be able to postpone most CPU/disc/etc-intensive operations
395         * at least this long without too much difficulty.
396         * <p>
397         * This should be long enough to last for mid-winter RE system lows, for example.
398         * Typically this might be several days to even as much as a few weeks,
399         * though systems not running fully or partially off RE power
400         * will probably only run for a few hours in low-power mode each day at most,
401         * eg to avoid local grid peak load or peak carbon-intensity.
402         */
403        public static final long MAX_EXPECTED_LOW_POWER_RUN_MS = 21 * 24 * 3600 * 1000L; // 3 weeks.
404        }