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 &quot;{@link #EXTERNAL_DOC_ROOT_URL_FILE external_doc_root_urls.txt}&quot; 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 &quot;base&quot; 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}(&quot;super.important.debugginginformation&quot;, null))  {
133   debugln(&quot;Super-duper important!&quot;)
134}</CODE></BLOCKQUOTE>
135
136      <P><I>(Unless otherwise noted, all below &quot;See&quot; 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> &nbsp; &nbsp; <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 &quot;{@link CodeletBaseConfig#OFFLINE_PACKAGE_LIST_DIR_NAME offline_package_lists}&quot;. 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 &quot;{@link CodeletBaseConfig#OFFLINE_PACKAGE_LIST_DIR_NAME offline_package_lists}&quot;. 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> &nbsp; &nbsp; <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> &nbsp; &nbsp; <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}