View Javadoc

1   /*
2    PlantUMLDependencyProgram.java
3    Creation date : 8/06/2010
4    Copyright © Benjamin Croizet (graffity2199@yahoo.fr)
5   
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License
8    or GNU Lesser General Public License as published by the
9    Free Software Foundation; either version 3 of the License,
10   or (at your option) any later version.
11  
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16  
17   You should have received copies of the GNU General Public License
18   and GNU Lesser General Public License along with this program;
19   if not, write to the Free Software Foundation, Inc.,
20   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21   http://www.fsf.org/licensing/licenses/gpl.html
22   http://www.gnu.org/licenses/lgpl.html
23   */
24  
25  package net.sourceforge.plantumldependency.cli.main.program;
26  
27  import static java.lang.System.currentTimeMillis;
28  import static java.util.Arrays.asList;
29  import static java.util.logging.Level.INFO;
30  import static java.util.logging.Level.SEVERE;
31  import static java.util.logging.Logger.getLogger;
32  import static net.sourceforge.plantumldependency.cli.constants.PlantUMLDependencyConstants.LOGGING_PROPERTIES_PATH;
33  import static net.sourceforge.plantumldependency.cli.constants.log.ErrorConstants.PLANTUML_DEPENDENCY_ERROR;
34  import static net.sourceforge.plantumldependency.cli.constants.log.InfoConstants.EXECUTION_TIME_INFO;
35  import static net.sourceforge.plantumldependency.cli.constants.log.InfoConstants.PLANTUML_DEPENDENCY_ARGUMENTS_INFO;
36  import static net.sourceforge.plantumldependency.cli.constants.log.InfoConstants.STARTING_PLANTUML_DEPENDENCY_INFO;
37  import static net.sourceforge.plantumldependency.cli.main.program.generated.PlantUMLDependencyProgramVersionImpl.PROGRAM_BUILD_TIME;
38  import static net.sourceforge.plantumldependency.cli.main.program.generated.PlantUMLDependencyProgramVersionImpl.PROGRAM_VERSION;
39  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.DOT_CHAR;
40  import static net.sourceforge.plantumldependency.common.utils.log.LogUtils.buildLogString;
41  import static net.sourceforge.plantumldependency.common.utils.log.LogUtils.readLoggerConfigurationFromResourceFromClassClassLoader;
42  import static net.sourceforge.plantumldependency.commoncli.constants.CommandLineConstants.PROTECTED_DOT_REGEXP;
43  import static net.sourceforge.plantumldependency.commoncli.utils.version.ProgramVersionUtils.createProgramVersionFromString;
44  
45  import java.io.IOException;
46  import java.net.MalformedURLException;
47  import java.net.URL;
48  import java.text.ParseException;
49  import java.util.Arrays;
50  import java.util.logging.Logger;
51  
52  import net.sourceforge.plantumldependency.cli.exception.PlantUMLDependencyException;
53  import net.sourceforge.plantumldependency.cli.main.option.basedirectory.PlantUMLDependencyBaseDirectoryOption;
54  import net.sourceforge.plantumldependency.cli.main.option.display.name.PlantUMLDependencyDisplayNameOption;
55  import net.sourceforge.plantumldependency.cli.main.option.display.packagename.PlantUMLDependencyDisplayPackageNameOption;
56  import net.sourceforge.plantumldependency.cli.main.option.display.type.PlantUMLDependencyDisplayTypeOption;
57  import net.sourceforge.plantumldependency.cli.main.option.exclude.PlantUMLDependencyExcludeOption;
58  import net.sourceforge.plantumldependency.cli.main.option.include.PlantUMLDependencyIncludeOption;
59  import net.sourceforge.plantumldependency.cli.main.option.output.PlantUMLDependencyOutputOption;
60  import net.sourceforge.plantumldependency.cli.main.option.programminglanguage.PlantUMLDependencyProgrammingLanguageOption;
61  import net.sourceforge.plantumldependency.commoncli.command.impl.CommandLineImpl;
62  import net.sourceforge.plantumldependency.commoncli.exception.CommandLineException;
63  import net.sourceforge.plantumldependency.commoncli.option.impl.about.AboutOption;
64  import net.sourceforge.plantumldependency.commoncli.option.impl.help.HelpOption;
65  import net.sourceforge.plantumldependency.commoncli.option.impl.verbose.VerboseLevelOption;
66  import net.sourceforge.plantumldependency.commoncli.option.impl.version.VersionOption;
67  import net.sourceforge.plantumldependency.commoncli.program.JavaProgram;
68  import net.sourceforge.plantumldependency.commoncli.program.execution.JavaProgramExecution;
69  import net.sourceforge.plantumldependency.commoncli.program.impl.JavaProgramImpl;
70  import net.sourceforge.plantumldependency.commoncli.program.version.ProgramVersion;
71  
72  /**
73   * The PlantUML dependency {@link JavaProgram} implementation.
74   *
75   * @author Benjamin Croizet (<a href="mailto:graffity2199@yahoo.fr>graffity2199@yahoo.fr</a>)
76   * @since 1.3.0
77   * @version 1.4.0
78   */
79  public final class PlantUMLDependencyProgram extends JavaProgramImpl {
80  
81      /** The class logger. */
82      private static final transient Logger LOGGER = getLogger(PlantUMLDependencyProgram.class.getName());
83  
84      /** Serial version UID. */
85      private static final long serialVersionUID = 8055066636525797910L;
86  
87      /** The Maven build timestamp pattern. */
88      private static final String MAVEN_BUILD_TIMESTAMP_PATTERN = "yyyyMMdd-HHmm";
89  
90      /**
91       * The PlantUML Dependency program entry point. Note that this method take an internal logging
92       * file and should be used only when the program is used as a stand alone application. If you
93       * call PlantUML Dependency from an other Java program, you should use the
94       * {@link #processProgramArguments(String[])} method.
95       *
96       * @param args
97       *            command line arguments.
98       * @throws PlantUMLDependencyException
99       *             if any error occurs when running PlantUML Dependency.
100      * @since 1.0.0
101      */
102     public static void main(final String[] args) throws PlantUMLDependencyException {
103         try {
104             readLoggerConfigurationFromResourceFromClassClassLoader(LOGGING_PROPERTIES_PATH,
105                     PlantUMLDependencyProgram.class);
106             processProgramArguments(args);
107         } catch (final PlantUMLDependencyException e) {
108             LOGGER.log(SEVERE, e.getMessage(), e);
109             throw e;
110         } catch (final IOException e) {
111             throw new PlantUMLDependencyException(PLANTUML_DEPENDENCY_ERROR, e);
112         }
113     }
114 
115     /**
116      * The PlantUML Dependency program entry point from command line arguments.
117      *
118      * @param args
119      *            command line arguments.
120      * @throws PlantUMLDependencyException
121      *             if any error occurs when running PlantUML Dependency.
122      * @since 1.1.1
123      */
124     public static void processProgramArguments(final String[] args) throws PlantUMLDependencyException {
125         final long start = currentTimeMillis();
126         LOGGER.log(INFO, STARTING_PLANTUML_DEPENDENCY_INFO);
127         LOGGER.log(INFO, buildLogString(PLANTUML_DEPENDENCY_ARGUMENTS_INFO, Arrays.toString(args)));
128 
129         try {
130             final JavaProgram plantumlDependencyProgram = new PlantUMLDependencyProgram();
131             final JavaProgramExecution plantumlDependencyProgramExecution = plantumlDependencyProgram
132                     .parseCommandLine(new CommandLineImpl(args));
133             plantumlDependencyProgramExecution.execute();
134         } catch (final CommandLineException e) {
135             throw new PlantUMLDependencyException(PLANTUML_DEPENDENCY_ERROR, e);
136         } catch (final ParseException e) {
137             throw new PlantUMLDependencyException(PLANTUML_DEPENDENCY_ERROR, e);
138         } catch (final IOException e) {
139             throw new PlantUMLDependencyException(PLANTUML_DEPENDENCY_ERROR, e);
140         }
141 
142         LOGGER.log(INFO, buildLogString(EXECUTION_TIME_INFO, currentTimeMillis() - start));
143     }
144 
145     /**
146      * Default constructor.
147      *
148      * @throws MalformedURLException
149      *             if the program URL doesn't have a good format.
150      * @throws CommandLineException
151      *             if any exception occurs while creating the program.
152      * @throws ParseException
153      *             if the program versio and the program date can't be properly parsed.
154      * @since 1.2.0
155      */
156     public PlantUMLDependencyProgram() throws MalformedURLException, CommandLineException, ParseException {
157         this(createProgramVersionFromString(PROGRAM_VERSION, PROTECTED_DOT_REGEXP, PROGRAM_BUILD_TIME,
158                 MAVEN_BUILD_TIMESTAMP_PATTERN));
159     }
160 
161     /**
162      * Default constructor.
163      *
164      * @param programVersion
165      *            the current {@link ProgramVersion}, mustn't be <code>null</code>.
166      *
167      * @throws MalformedURLException
168      *             if the program URL doesn't have a good format.
169      * @throws CommandLineException
170      *             if any exception occurs while creating the program.
171      * @since 1.0.0
172      */
173     private PlantUMLDependencyProgram(final ProgramVersion programVersion) throws MalformedURLException,
174             CommandLineException {
175         super("PlantUML Dependency", new URL("http://plantuml-depend.sourceforge.net"), "plantuml-dependency-cli-"
176                 + programVersion.getFullVersionNumber() + ".jar", asList(new String[] {
177                 "GPL v3, 29 June 2007 (http://www.gnu.org/licenses/gpl-3.0.txt)",
178                 "LGPL v3, 29 June 2007 (http://www.gnu.org/licenses/lgpl-3.0.txt)"}),
179                 asList(new String[] {"Benjamin Croizet (graffity2199@yahoo.fr)"}), programVersion, new StringBuilder(
180                         "reverse engineering java source files to generate PlantUML description"));
181 
182         final VerboseLevelOption verboseLevelOption = new VerboseLevelOption();
183         addOption(verboseLevelOption);
184 
185         final AboutOption aboutOption = new AboutOption(this, 2);
186         addOption(aboutOption);
187 
188         final HelpOption helpOption = new HelpOption(this, 1);
189         addOption(helpOption);
190 
191         final VersionOption versionOption = new VersionOption(this, 3);
192         addOption(versionOption);
193 
194         final PlantUMLDependencyDisplayTypeOption displayTypeOption = new PlantUMLDependencyDisplayTypeOption();
195         addOption(displayTypeOption);
196 
197         final PlantUMLDependencyDisplayNameOption displayNameOption = new PlantUMLDependencyDisplayNameOption();
198         addOption(displayNameOption);
199 
200         final PlantUMLDependencyDisplayPackageNameOption displayPackageNameOption = new PlantUMLDependencyDisplayPackageNameOption();
201         addOption(displayPackageNameOption);
202 
203         final PlantUMLDependencyProgrammingLanguageOption programmingLanguageOption = new PlantUMLDependencyProgrammingLanguageOption();
204         addOption(programmingLanguageOption);
205 
206         final PlantUMLDependencyIncludeOption includeOption = new PlantUMLDependencyIncludeOption(
207                 programmingLanguageOption);
208         addOption(includeOption);
209 
210         final PlantUMLDependencyExcludeOption excludeOption = new PlantUMLDependencyExcludeOption();
211         addOption(excludeOption);
212 
213         final PlantUMLDependencyBaseDirectoryOption baseDirectoryOption = new PlantUMLDependencyBaseDirectoryOption();
214         addOption(baseDirectoryOption);
215 
216         final PlantUMLDependencyOutputOption outputOption = new PlantUMLDependencyOutputOption(verboseLevelOption,
217                 programmingLanguageOption, includeOption, excludeOption, displayTypeOption, displayPackageNameOption,
218                 displayNameOption, baseDirectoryOption, 4);
219         addOption(outputOption);
220 
221         final String[] example1 = new String[] {helpOption.getName()};
222         final String[] example2 = new String[] {versionOption.getName(), verboseLevelOption.getName()};
223         final String[] example3 = new String[] {outputOption.getName(), "myoutput.txt", baseDirectoryOption.getName(),
224                 "\"C:\\Users\\PlantUML test\"", includeOption.getName(), "**/*Test.java"};
225         final String[] example4 = new String[] {outputOption.getName(), "/home/test/plantuml.txt", "-b", DOT_CHAR,
226                 includeOption.getName(), "**/*.java", excludeOption.getName(), "**/*Test*.java",
227                 displayTypeOption.getName(), "implementations,interfaces,extensions,imports,static_imports"};
228         final String[] example5 = new String[] {outputOption.getName(), "/home/test/plantuml.txt", "-b", DOT_CHAR,
229                 includeOption.getName(), "**/*.java", excludeOption.getName(), "**/*Test*.java",
230                 displayNameOption.getName(), ".*Test.*", verboseLevelOption.getName()};
231         final String[] example6 = new String[] {outputOption.getName(), "/home/test/plantuml.txt", "-b", DOT_CHAR,
232                 displayPackageNameOption.getName(), "^(?!net.sourceforge.plantumldependency)(.+)$",
233                 verboseLevelOption.getName()};
234         addExampleCommandLine(new CommandLineImpl(example1));
235         addExampleCommandLine(new CommandLineImpl(example2));
236         addExampleCommandLine(new CommandLineImpl(example3));
237         addExampleCommandLine(new CommandLineImpl(example4));
238         addExampleCommandLine(new CommandLineImpl(example5));
239         addExampleCommandLine(new CommandLineImpl(example6));
240 
241         addKnownBugOrLimitation("- As PlantUML Dependency reads source files imports, it will generate object - imports relation even if the imports are not used within the object (usually, this raises a warning within the IDE)");
242         addKnownBugOrLimitation("- Be careful, in order to correctly parse source files, it is better to have source code which compiles without any errors");
243         addKnownBugOrLimitation("- Generated annotations (if used) are only supported by PlantUML 7972 and above");
244         addKnownBugOrLimitation("- Import instructions \"import package_name.*\" are ignored because the dependencies are not explicitly defined, use precise imports instead");
245         addKnownBugOrLimitation("- Links between dependencies are found out by parsing \"import\" instructions, so PlantUML Dependency won't display dependencies which are called using their full names in the source code");
246         addKnownBugOrLimitation("- PlantUML Dependency can be run by JRE 1.6+");
247         addKnownBugOrLimitation("- PlantUML Dependency is fully compliant up to Java 1.6 source files (and may work with Java 1.7 source files)");
248         addKnownBugOrLimitation("- The generated output file is better when PlantUML Dependency is launched with a JRE matching the parsed source files");
249     }
250 }