001/*license*\ 002 Codelet: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com) 003 004 This software is dual-licensed under the: 005 - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version; 006 - Apache Software License (ASL) version 2.0. 007 008 Either license may be applied at your discretion. More information may be found at 009 - http://en.wikipedia.org/wiki/Multi-licensing. 010 011 The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at: 012 - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt 013 - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt 014\*license*/ 015package com.github.aliteralmind.codelet; 016 import com.github.xbn.lang.ExceptionUtil; 017 import com.github.xbn.io.PlainTextFileUtil; 018 import com.github.xbn.util.PropertiesUtil; 019 import java.io.IOException; 020 import java.net.MalformedURLException; 021 import java.nio.file.AccessDeniedException; 022 import java.nio.file.NoSuchFileException; 023 import java.util.Iterator; 024 import java.util.Properties; 025/** 026 <P>Initializes Codelet by loading all configuration--This is {@linkplain TagletProcessor#TagletProcessor(CodeletInstance) triggered} by the first codelet-taglet encountered by {@code javadoc.exe}.</P> 027 028 <P>This:<OL> 029 <LI>Obtains the {@link #CODELET_CONFIG_DIR_SYS_PROP_NAME codelet_config_dir} system property as passed into the {@code javadoc} application.</LI> 030 <LI>Loads {@linkplain CodeletBaseConfig base configuration} from {@link #BASE_CONFIG_FILE_NAME codelet.properties}, as exists in the configuration directory. This includes the {@linkplain #CODELET_RQD_NAMED_DBGRS_CONFIG_FILE Codelet-required} and {@linkplain #NAMED_DEBUGGERS_CONFIG_FILE user-created} named debuggers, and the external JavaDoc library {@linkplain #EXTERNAL_DOC_ROOT_URL_FILE package-lists}.</LI> 031 <LI>Loads {@linkplain CodeletTemplateConfig default templates}.</LI> 032 <LI>Loads the {@linkplain TemplateOverrides template-override} configuration from {@link #TMPL_OVERRIDES_CONFIG_FILE_NAME template_overrides_config}.</LI> 033 </OL>This order is required to avoid <A HREF="http://en.wikipedia.org/wiki/Circular_dependency">circular dependencies</A>.</P> 034 035 <H4>Automated {@linkplain CodeletBootstrap#CODELET_RQD_NAMED_DBGRS_CONFIG_FILE named debuggers}</H4> 036 037 <P>{@code zzconfiguration.}<UL> 038 <LI>{@code nameddebuglevels.listallafterload}: List all levels after being loaded.</LI> 039 <LI>{@code nameddebuglevels.eachquery}: List each level when queried--regardless if on or off. Use this to determine any unused levels that may exist in the configuration file.</LI> 040 <LI>{@code allvaluessummary}: List all {@linkplain CodeletBaseConfig basic configuration} values after complete.</LI> 041 <LI>{@code progress}: The basic steps taken while loading all configuration.</LI> 042 <LI>{@code templateoverrides.}<UL> 043 <LI>{@code allentriespostloaded}: List all entries organized by JavaDoc file.</LI> 044 <LI>{@code eachentryasloaded}: List all entries as they are loaded.</LI> 045 </UL></LI> 046 </UL></P> 047 048 <P><B>Full names:</B></P> 049 050<BLOCKQUOTE><PRE>zzconfiguration.nameddebuglevels.listallafterload 051zzconfiguration.nameddebuglevels.eachquery 052zzconfiguration.allvaluessummary 053zzconfiguration.progress 054zzconfiguration.templateoverrides.allentriespostloaded 055zzconfiguration.templateoverrides.eachentryasloaded</PRE></BLOCKQUOTE> 056 057 @since 0.1.0 058 @author Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <A HREF="http://codelet.aliteralmind.com">{@code http://codelet.aliteralmind.com}</A>, <A HREF="https://github.com/aliteralmind/codelet">{@code https://github.com/aliteralmind/codelet}</A> 059 **/ 060public enum CodeletBootstrap { 061 INSTANCE; 062 static { 063 try { 064 CodeletBootstrap.loadConfiguration(); 065 } catch(Exception x) { 066 throw new ExceptionInInitializerError( 067 new IllegalStateException("Attempting to load Codelet configuration.", x)); 068 } 069 } 070 private static String configDir ; 071 private static CodeletBaseConfig baseConfig ; 072 private static CodeletTemplateConfig tmplConfig ; 073 private static TemplateOverrides tmplOverrides; 074 private static final String NAMED_DBG_LVL_PREFIX = "named_debuggers_config"; 075 /** 076 <P>The name of the system property that is <A HREF="{@docRoot}/overview-summary.html#install_taglets">passed</A> into the {@code javadoc} application, whose value is the directory in which all Codelet configuration files are stored--Equal to {@code "codelet_config_dir"}. </P> 077 078 <P>{@link #BASE_CONFIG_FILE_NAME codelet.properties}, {@link #TMPL_OVERRIDES_CONFIG_FILE_NAME template_overrides_config.txt}, and "{@link #EXTERNAL_DOC_ROOT_URL_FILE external_doc_root_urls.txt}" must all be in this directory.</P> 079 080 @see CodeletBootstrap 081 @see #getCodeletConfigDir() 082 **/ 083 public static final String CODELET_CONFIG_DIR_SYS_PROP_NAME = "codelet_config_dir"; 084 /** 085 <P>The name of the "base" configuration file--Equal to {@code "codelet.properties"}.</P> 086 087 @see #TMPL_OVERRIDES_CONFIG_FILE_NAME 088 @see com.github.aliteralmind.codelet.CodeletBaseConfig 089 **/ 090 public static final String BASE_CONFIG_FILE_NAME = "codelet.properties"; 091 /** 092 <P>The name of the configuration file containing user-created named-debugging-levels--Equal to {@code "named_debuggers_config.txt"}.</P> 093 094 <P><I>(View <A HREF="{@docRoot}/codelet_config/named_debuggers_config.txt">{@code {@docRoot}/codelet_config/named_debuggers_config.txt}</A>.)</I></P> 095 096 <P>This file contains a list of zero or more {@linkplain com.github.aliteralmind.codelet.util.NamedDebuggers#newMapFromConfigFile(Map, Iterator, String, Appendable) names}, each of which is associated to a specific debugging task and {@linkplain CodeletBaseConfig#GLOBAL_DEBUG_LEVEL level}. These are in addition to those in the {@linkplain #CODELET_RQD_NAMED_DBGRS_CONFIG_FILE Codelet-required} configuration file.</P> 097 098 <P>Named debuggers allow for very specific control over what information is logged, <I>without having to recompile code</I>. In particular, named debuggers are useful for debugging <A HREF="CustomizationInstructions.html#overview">custom customizers</A>.</P> 099 100 <P>All possible level numbers:<UL> 101<!-- 102 Originates in 103 com.github.aliteralmind.codelet.util.NamedDebuggers 104 needed by 105 com.github.aliteralmind.codelet.CodeletBootstrap 106 ...START 107 --> 108 <LI><B>{@code -1}</B>: Never output.</LI> 109 <LI><B>{@code 0}</B>: Always output (even if {@link com.github.xbn.io.DebugLevel#OFF OFF}).</LI> 110 <LI><B>{@code 1}</B>: Output only when the actual level {@linkplain com.github.xbn.io.DebugLevel#isOn() on}--equal to or greater than {@link com.github.xbn.io.DebugLevel#ONE ONE}.</LI> 111 <LI><B>{@code 2}</B>: Output when the actual level is {@link com.github.xbn.io.DebugLevel#TWO TWO} or greater.</LI> 112 <LI><B>{@code 3}</B>: Output when the actual level is {@link com.github.xbn.io.DebugLevel#THREE THREE} or greater.</LI> 113 <LI><B>{@code 4}</B>: Output when the actual level is {@link com.github.xbn.io.DebugLevel#FOUR FOUR} or {@link com.github.xbn.io.DebugLevel#FIVE FIVE}.</LI> 114 <LI><B>{@code 5}</B>: Output only when the actual level is {@code FIVE}.</LI> 115<!-- 116 Originates in 117 com.github.aliteralmind.codelet.util.NamedDebuggers 118 needed by 119 com.github.aliteralmind.codelet.CodeletBootstrap 120 ...END 121 --> 122 </UL></P> 123 124 <H4>Example</H4> 125 126 <P>Add this line to {@code "named_debuggers_config.txt"}:</P> 127 128<BLOCKQUOTE><PRE>super.important.debugginginformation=2</PRE></BLOCKQUOTE> 129 130 <P>Then associate specific debugging statements to it:</P> 131 132<BLOCKQUOTE><CODE>if({@link CodeletBaseConfig#isDebugOn(CodeletInstance, String) isDebugOn}("super.important.debugginginformation", null)) { 133 debugln("Super-duper important!") 134}</CODE></BLOCKQUOTE> 135 136 <P><I>(Unless otherwise noted, all below "See" links are located in {@link CodeletBaseConfig}.)</I></P> 137 138 @see com.github.aliteralmind.codelet.util.NamedDebuggers#newMapFromConfigFile(Map, Iterator, String, Appendable) NamedDebuggers#newMapFromConfigFile 139 @see CodeletBaseConfig#GLOBAL_DEBUG_LEVEL GLOBAL_DEBUG_LEVEL 140 @see CodeletBaseConfig#isDebugOn(CodeletInstance, String) isDebugOn(s,ci) 141 @see CodeletBaseConfig#getDebugApblIfOn(CodeletInstance, String) getDebugApblIfOn(ci,s) 142 @see CodeletBaseConfig#getDebugAptrIfOn(CodeletInstance, String) getDebugAptrIfOn(ci,s) 143 **/ 144 public static final String NAMED_DEBUGGERS_CONFIG_FILE = NAMED_DBG_LVL_PREFIX + ".txt"; 145 /** 146 <P>The name of the configuration file containing Codelet-required named debuggers--Equal to {@code "named_debuggers_CODELET_RQD.txt"}.</P> 147 148 <P><I>(View <A HREF="{@docRoot}/codelet_config/named_debuggers_CODELET_RQD.txt">{@code {@docRoot}/codelet_config/named_debuggers_CODELET_RQD.txt}</A>.)</I></P> 149 150 <P>This file contains a list of {@linkplain com.github.aliteralmind.codelet.util.NamedDebuggers#newMapFromConfigFile(Map, Iterator, String, Appendable) names}, each of which is associated to a specific debugging task and {@linkplain CodeletBaseConfig#GLOBAL_DEBUG_LEVEL level}. These are in addition to those in the {@linkplain #NAMED_DEBUGGERS_CONFIG_FILE user-created} configuration file.</P> 151 152 <P>Changing the level numbers in this file allows you to print or suppress very specific aspects of debugging information that is <I>already built into Codelet</I>. <B>Warning:</B> Changing the <I>names</I> of any level in this file will result in an error. All Codelet-required levels are prefixed with {@code "zz"}.</P> 153 154 <P>An example of a function taking advantage of named debuggers is 155 <BR> <CODE>{@link BasicCustomizers}.{@link BasicCustomizers#lineRange(CodeletInstance, CodeletType, Integer, Boolean, String, Integer, Boolean, String, String) lineRange}</CODE>.</P> 156 157 @see #NAMED_DEBUGGERS_CONFIG_FILE 158 @see com.github.aliteralmind.codelet.util.NamedDebuggers#newMapFromConfigFile(Map, Iterator, String, Appendable) NamedDebuggers#newMapFromConfigFile 159 **/ 160 public static final String CODELET_RQD_NAMED_DBGRS_CONFIG_FILE = NAMED_DBG_LVL_PREFIX + "_CODELET_RQD.txt"; 161 /** 162 <P>The name of the file in which all <A HREF="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#externalreferencedclasses">external {@code {@docRoot}} urls</A> are listed--Equal to {@code "external_doc_root_urls.txt"}.</P> 163 164 <P>These urls are the directories in which an external JavaDoc library's <A HREF="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#package-list">{@code package-list}</A> file exists. Each url must end with a slash: {@code '/'}.</P> 165 166 <P>Each {@code package-list} file is also stored locally, in a sub-directory named "{@link CodeletBaseConfig#OFFLINE_PACKAGE_LIST_DIR_NAME offline_package_lists}". The offline files are automatically used when the online version is not accessible or available. These files may be manually created and, if {@linkplain CodeletBaseConfig#AUTO_UPDATE_OFFLINE_PACKAGE_LISTS configured}, are automatically updated.</P> 167 168 <P>Each line is in the format</P> 169 170<BLOCKQUOTE><PRE>[offline_file_name_prefix] [url]</PRE></BLOCKQUOTE> 171 172 <P>Where<UL> 173 <LI><CODE>[offline_file_name]</CODE> is the name of the locally-stored file (aside from {@code ".txt"}), which exists in a sub-directory named "{@link CodeletBaseConfig#OFFLINE_PACKAGE_LIST_DIR_NAME offline_package_lists}". This is in the {@linkplain #CODELET_CONFIG_DIR_SYS_PROP_NAME same directory} as this {@code "external_doc_root_urls.txt"} file. Must only contain letters, digits, and underscores ({@code '_'}).</LI> 174 <LI><CODE>[url]</CODE> is the url to the JavaDoc document root ({@code "{@docRoot}"}) of an external Java library. Must end with a slash ({@code '/'}), and must contain the library's {@code "package-list"} file.</LI> 175 </UL>The file-name and url are separated with at least one space or tab.</P> 176 177 <H4>Example file</H4> 178 179<BLOCKQUOTE><PRE>templatefeather http://aliteralmind.com/docs/computer/programming/templatefeather/documentation/javadoc/ 180xbnjava http://aliteralmind.com/docs/computer/programming/xbnjava/documentation/javadoc/ 181commons_collections http://commons.apache.org/proper/commons-collections/javadocs/api-release/ 182commons_io http://commons.apache.org/proper/commons-io/javadocs/api-2.4/ 183commons_lang http://commons.apache.org/proper/commons-lang/javadocs/api-release/ 184java http://docs.oracle.com/javase/7/docs/api/ 185javadoc http://docs.oracle.com/javase/7/docs/jdk/api/javadoc/doclet/ 186junit http://junit.sourceforge.net/javadoc/</PRE></BLOCKQUOTE> 187 188 <P>If the path of {@code "external_doc_root_urls.txt"} is 189 <BR> <CODE>C:\java_code\my_package\codelet_config\external_doc_root_urls.txt</CODE> 190 <BR>then the path to the {@code "commons_io"} offline package-list is 191 <BR> <CODE>C:\java_code\my_package\codelet_config\offline_package_lists\commons_io.txt</CODE> 192 <BR>The {@code ".txt"} postfix is {@linkplain CodeletBaseConfig#PKGLIST_OFFLINE_NAME_POSTFIX customizable}.</P> 193 194 <P><I>(View <A HREF="{@docRoot}/codelet_config/external_doc_root_urls.txt">{@code {@docRoot}/codelet_config/external_doc_root_urls.txt}</A>.)</I></P> 195 196 <P>This configuration file is loaded by <CODE>{@link com.github.aliteralmind.codelet.util.AllOnlineOfflineDocRoots}.{@link com.github.aliteralmind.codelet.util.AllOnlineOfflineDocRoots#newFromConfigLineIterator(Iterator, String, String, int, long, RefreshOffline, IfError, Appendable, Appendable) newFromConfigLineIterator}</CODE></P> 197 198 <P>Related (all in {@link CodeletBaseConfig}):<UL> 199 <LI>{@link CodeletBaseConfig#PKGLIST_ONLINE_ATTEMPT_SLEEP_MILLS pkglist_online_attempt_sleep_mills}: The pause between each attempt.</LI> 200 <LI>{@link CodeletBaseConfig#PKGLIST_ONLINE_FAILS_BEHAVIOR pkglist_if_online_retrieval_fails__warn_crash}: The behavior after all attempts fail</LI> 201 <LI>{@link CodeletBaseConfig#AUTO_UPDATE_OFFLINE_PACKAGE_LISTS pkglist_auto_refresh_offline__yes_no}: After successfully retrieved, should the packages in its offline counterpart be {@linkplain com.github.aliteralmind.codelet.util.OnlineOfflineDocRoot#refreshOffline(Appendable, Appendable) refreshed}?</LI> 202 <LI>{@link CodeletBaseConfig#PKGLIST_OFFLINE_NAME_POSTFIX pkglist_offline_name_postfix}: The postfix added to each offline-name in the {@linkplain CodeletBootstrap#EXTERNAL_DOC_ROOT_URL_FILE configuration file}.</LI> 203 <LI>{@link CodeletBaseConfig#OFFLINE_PACKAGE_LIST_DIR_NAME}: The name of the sub-directory, existing in the main Codelet configuration directory, in which offline package lists are stored.</LI> 204 </UL></P> 205 206 @see com.github.aliteralmind.codelet.alter.NewJavaDocLinkReplacerFor#getDocRootUrlToTargetClass(CodeletInstance, Class) NewJavaDocLinkReplacerFor#getDocRootUrlToTargetClass 207 @see com.github.aliteralmind.codelet.util.AllOnlineOfflineDocRoots#newFromConfigLineIterator(Iterator, String, String, int, long, RefreshOffline, IfError, Appendable, Appendable) util.AllOnlineOfflineDocRoots#newFromConfigLineIterator 208 **/ 209 public static final String EXTERNAL_DOC_ROOT_URL_FILE = "external_doc_root_urls.txt"; 210 /** 211 <P>The name of the {@linkplain TemplateOverrides template-overrides} configuration file--Equal to {@code "template_overrides_config.txt"}.</P> 212 213 @see #BASE_CONFIG_FILE_NAME 214 @see com.github.aliteralmind.codelet.TemplateOverrides 215 **/ 216 public static final String TMPL_OVERRIDES_CONFIG_FILE_NAME = "template_overrides_config.txt"; 217// static final CodeletBootstrap loadConfigGetInstance() throws ClassNotFoundException, NoSuchFileException, AccessDeniedException, MalformedURLException, IOException, InterruptedException { 218 private static final void loadConfiguration() throws ClassNotFoundException, NoSuchFileException, AccessDeniedException, MalformedURLException, IOException, InterruptedException { 219 if(wasLoaded()) { 220 throw new IllegalStateException("Configuration already loaded. wasLoaded()=true"); 221 } 222 223 configDir = System.getProperty(CODELET_CONFIG_DIR_SYS_PROP_NAME, null); 224 225 String configDirEquals = CODELET_CONFIG_DIR_SYS_PROP_NAME + "=" + configDir; 226 Properties props = PropertiesUtil. 227 getPropertiesFromFile(configDir + BASE_CONFIG_FILE_NAME, configDirEquals); 228 229 Iterator<String> externalJDDocRootConfigItr = PlainTextFileUtil. 230 getLineIterator(configDir + EXTERNAL_DOC_ROOT_URL_FILE, 231 configDirEquals); 232 233 Iterator<String> rqdDebugLevelConfigItr = PlainTextFileUtil. 234 getLineIterator(configDir + CODELET_RQD_NAMED_DBGRS_CONFIG_FILE, 235 configDirEquals); 236 Iterator<String> debugLevelConfigItr = PlainTextFileUtil. 237 getLineIterator(configDir + NAMED_DEBUGGERS_CONFIG_FILE, 238 configDirEquals); 239 240 baseConfig = CodeletBaseConfig.loadConfigGetInstance(props, 241 configDir, externalJDDocRootConfigItr, 242 rqdDebugLevelConfigItr, debugLevelConfigItr); 243 244 tmplConfig = CodeletTemplateConfig.loadConfigGetInstance(); 245 246 Iterator<String> overridesItr = PlainTextFileUtil. 247 getLineIterator(configDir + TMPL_OVERRIDES_CONFIG_FILE_NAME, configDirEquals); 248 tmplOverrides = TemplateOverrides.loadConfigGetInstance(overridesItr); 249 } 250 /** 251 <P>Was all Codelet configuration properly loaded?.</P> 252 253 @return <CODE>{@link TemplateOverrides}.{@link TemplateOverrides#wasLoaded() wasLoaded}()</CODE> 254 **/ 255 public static final boolean wasLoaded() { 256 return TemplateOverrides.wasLoaded(); 257 } 258 /** 259 <P>The directory in which all Codelet configuration files exist, as passed in via the {@code javadoc.exe} system property named {@code "codelet_config_dir"}.</P> 260 261 @see #CODELET_CONFIG_DIR_SYS_PROP_NAME 262 **/ 263 public static final String getCodeletConfigDir() { 264 return configDir; 265 } 266}