mirror of https://github.com/octoleo/plantuml.git
380 lines
12 KiB
Java
380 lines
12 KiB
Java
/* ========================================================================
|
|
* PlantUML : a free UML diagram generator
|
|
* ========================================================================
|
|
*
|
|
* (C) Copyright 2009-2013, Arnaud Roques
|
|
*
|
|
* Project Info: http://plantuml.sourceforge.net
|
|
*
|
|
* This file is part of PlantUML.
|
|
*
|
|
* PlantUML is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* PlantUML distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
* License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
* USA.
|
|
*
|
|
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
|
|
* in the United States and other countries.]
|
|
*
|
|
* Original Author: Arnaud Roques
|
|
*
|
|
* Revision $Revision: 12023 $
|
|
*
|
|
*/
|
|
package net.sourceforge.plantuml;
|
|
|
|
import java.awt.Font;
|
|
import java.awt.GraphicsEnvironment;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.PrintStream;
|
|
import java.util.List;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
import javax.imageio.ImageIO;
|
|
import javax.swing.UIManager;
|
|
|
|
import net.sourceforge.plantuml.activitydiagram.ActivityDiagramFactory;
|
|
import net.sourceforge.plantuml.classdiagram.ClassDiagramFactory;
|
|
import net.sourceforge.plantuml.code.Transcoder;
|
|
import net.sourceforge.plantuml.code.TranscoderUtil;
|
|
import net.sourceforge.plantuml.command.UmlDiagramFactory;
|
|
import net.sourceforge.plantuml.core.Diagram;
|
|
import net.sourceforge.plantuml.descdiagram.DescriptionDiagramFactory;
|
|
import net.sourceforge.plantuml.ftp.FtpServer;
|
|
import net.sourceforge.plantuml.objectdiagram.ObjectDiagramFactory;
|
|
import net.sourceforge.plantuml.png.MetadataTag;
|
|
import net.sourceforge.plantuml.preproc.Defines;
|
|
import net.sourceforge.plantuml.sequencediagram.SequenceDiagramFactory;
|
|
import net.sourceforge.plantuml.statediagram.StateDiagramFactory;
|
|
import net.sourceforge.plantuml.swing.MainWindow2;
|
|
import net.sourceforge.plantuml.ugraphic.SpriteGrayLevel;
|
|
import net.sourceforge.plantuml.ugraphic.SpriteUtils;
|
|
import net.sourceforge.plantuml.version.Version;
|
|
|
|
public class Run {
|
|
|
|
public static void main(String[] argsArray) throws IOException, InterruptedException {
|
|
final long start = System.currentTimeMillis();
|
|
final Option option = new Option(argsArray);
|
|
if (OptionFlags.getInstance().isEncodesprite()) {
|
|
encodeSprite(option.getResult());
|
|
return;
|
|
}
|
|
if (OptionFlags.getInstance().isVerbose()) {
|
|
Log.info("PlantUML Version " + Version.versionString());
|
|
Log.info("GraphicsEnvironment.isHeadless() " + GraphicsEnvironment.isHeadless());
|
|
}
|
|
if (GraphicsEnvironment.isHeadless()) {
|
|
Log.info("Forcing -Djava.awt.headless=true");
|
|
System.setProperty("java.awt.headless", "true");
|
|
Log.info("java.awt.headless set as true");
|
|
|
|
}
|
|
if (OptionFlags.getInstance().isPrintFonts()) {
|
|
printFonts();
|
|
return;
|
|
}
|
|
|
|
if (option.getFtpPort() != -1) {
|
|
goFtp(option);
|
|
return;
|
|
}
|
|
|
|
boolean error = false;
|
|
boolean forceQuit = false;
|
|
if (option.isPattern()) {
|
|
managePattern();
|
|
} else if (OptionFlags.getInstance().isGui()) {
|
|
try {
|
|
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
|
|
} catch (Exception e) {
|
|
}
|
|
new MainWindow2(option);
|
|
} else if (option.isPipe() || option.isSyntax()) {
|
|
managePipe(option);
|
|
forceQuit = true;
|
|
} else {
|
|
error = manageAllFiles(option);
|
|
forceQuit = true;
|
|
}
|
|
|
|
if (option.isDuration()) {
|
|
final long duration = System.currentTimeMillis() - start;
|
|
Log.error("Duration = " + (duration / 1000L) + " seconds");
|
|
}
|
|
|
|
if (error) {
|
|
Log.error("Some diagram description contains errors");
|
|
System.exit(1);
|
|
}
|
|
|
|
if (forceQuit && OptionFlags.getInstance().isSystemExit()) {
|
|
System.exit(0);
|
|
}
|
|
}
|
|
|
|
private static void encodeSprite(List<String> result) throws IOException {
|
|
SpriteGrayLevel level = SpriteGrayLevel.GRAY_16;
|
|
boolean compressed = false;
|
|
final File f;
|
|
if (result.size() > 1 && result.get(0).matches("(4|8|16)z?")) {
|
|
if (result.get(0).startsWith("8")) {
|
|
level = SpriteGrayLevel.GRAY_8;
|
|
}
|
|
if (result.get(0).startsWith("4")) {
|
|
level = SpriteGrayLevel.GRAY_4;
|
|
}
|
|
compressed = result.get(0).toLowerCase().endsWith("z");
|
|
f = new File(result.get(1));
|
|
} else {
|
|
f = new File(result.get(0));
|
|
}
|
|
final BufferedImage im = ImageIO.read(f);
|
|
final String name = getSpriteName(f);
|
|
final String s = compressed ? SpriteUtils.encodeCompressed(im, name, level) : SpriteUtils.encode(im, name,
|
|
level);
|
|
System.out.println(s);
|
|
}
|
|
|
|
private static String getSpriteName(File f) {
|
|
final String s = getSpriteNameInternal(f);
|
|
if (s.length() == 0) {
|
|
return "test";
|
|
}
|
|
return s;
|
|
}
|
|
|
|
private static String getSpriteNameInternal(File f) {
|
|
final StringBuilder sb = new StringBuilder();
|
|
for (char c : f.getName().toCharArray()) {
|
|
if (("" + c).matches("[\\p{L}0-9_]")) {
|
|
sb.append(c);
|
|
} else {
|
|
return sb.toString();
|
|
}
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
private static void goFtp(Option option) throws IOException {
|
|
final int ftpPort = option.getFtpPort();
|
|
System.err.println("ftpPort=" + ftpPort);
|
|
final FtpServer ftpServer = new FtpServer(ftpPort);
|
|
ftpServer.go();
|
|
}
|
|
|
|
static void printFonts() {
|
|
final Font fonts[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
|
|
for (Font f : fonts) {
|
|
System.out.println("f=" + f + "/" + f.getPSName() + "/" + f.getName() + "/" + f.getFontName() + "/"
|
|
+ f.getFamily());
|
|
}
|
|
final String name[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
|
|
for (String n : name) {
|
|
System.out.println("n=" + n);
|
|
}
|
|
|
|
}
|
|
|
|
private static void managePattern() {
|
|
printPattern(new SequenceDiagramFactory());
|
|
printPattern(new ClassDiagramFactory());
|
|
printPattern(new ActivityDiagramFactory());
|
|
printPattern(new DescriptionDiagramFactory());
|
|
// printPattern(new ComponentDiagramFactory());
|
|
printPattern(new StateDiagramFactory());
|
|
printPattern(new ObjectDiagramFactory());
|
|
}
|
|
|
|
private static void printPattern(UmlDiagramFactory factory) {
|
|
System.out.println();
|
|
System.out.println(factory.getClass().getSimpleName().replaceAll("Factory", ""));
|
|
final List<String> descriptions = factory.getDescription();
|
|
for (String s : descriptions) {
|
|
System.out.println(s);
|
|
}
|
|
}
|
|
|
|
private static void managePipe(Option option) throws IOException {
|
|
final String charset = option.getCharset();
|
|
final BufferedReader br;
|
|
if (charset == null) {
|
|
br = new BufferedReader(new InputStreamReader(System.in));
|
|
} else {
|
|
br = new BufferedReader(new InputStreamReader(System.in, charset));
|
|
}
|
|
managePipe(option, br, System.out);
|
|
}
|
|
|
|
static void managePipe(Option option, final BufferedReader br, final PrintStream ps) throws IOException {
|
|
final StringBuilder sb = new StringBuilder();
|
|
String s = null;
|
|
while ((s = br.readLine()) != null) {
|
|
sb.append(s);
|
|
sb.append("\n");
|
|
}
|
|
String source = sb.toString();
|
|
if (source.contains("@startuml") == false) {
|
|
source = "@startuml\n" + source + "\n@enduml";
|
|
}
|
|
final SourceStringReader sourceStringReader = new SourceStringReader(new Defines(), source, option.getConfig());
|
|
|
|
if (option.isSyntax()) {
|
|
final Diagram system = sourceStringReader.getBlocks().get(0).getDiagram();
|
|
if (system instanceof UmlDiagram) {
|
|
ps.println(((UmlDiagram) system).getUmlDiagramType().name());
|
|
ps.println(system.getDescription());
|
|
} else if (system instanceof PSystemError) {
|
|
ps.println("ERROR");
|
|
final PSystemError sys = (PSystemError) system;
|
|
ps.println(sys.getHigherErrorPosition());
|
|
for (ErrorUml er : sys.getErrorsUml()) {
|
|
ps.println(er.getError());
|
|
}
|
|
} else {
|
|
ps.println("OTHER");
|
|
ps.println(system.getDescription());
|
|
}
|
|
} else if (option.isPipe()) {
|
|
sourceStringReader.generateImage(ps, 0, option.getFileFormatOption());
|
|
}
|
|
}
|
|
|
|
private static boolean manageAllFiles(Option option) throws IOException, InterruptedException {
|
|
|
|
File lockFile = null;
|
|
try {
|
|
if (OptionFlags.getInstance().isWord()) {
|
|
final File dir = new File(option.getResult().get(0));
|
|
final File javaIsRunningFile = new File(dir, "javaisrunning.tmp");
|
|
javaIsRunningFile.delete();
|
|
lockFile = new File(dir, "javaumllock.tmp");
|
|
}
|
|
return processArgs(option);
|
|
} finally {
|
|
if (lockFile != null) {
|
|
lockFile.delete();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private static boolean processArgs(Option option) throws IOException, InterruptedException {
|
|
if (option.isDecodeurl() == false && option.getNbThreads() > 0 && option.isCheckOnly() == false
|
|
&& OptionFlags.getInstance().isMetadata() == false) {
|
|
return multithread(option);
|
|
}
|
|
for (String s : option.getResult()) {
|
|
if (option.isDecodeurl()) {
|
|
final Transcoder transcoder = TranscoderUtil.getDefaultTranscoder();
|
|
System.out.println("@startuml");
|
|
System.out.println(transcoder.decode(s));
|
|
System.out.println("@enduml");
|
|
} else {
|
|
final FileGroup group = new FileGroup(s, option.getExcludes(), option);
|
|
for (File f : group.getFiles()) {
|
|
try {
|
|
final boolean error = manageFileInternal(f, option);
|
|
if (error) {
|
|
return true;
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static boolean multithread(final Option option) throws InterruptedException {
|
|
Log.info("Using several threads: " + option.getNbThreads());
|
|
final ExecutorService executor = Executors.newFixedThreadPool(option.getNbThreads());
|
|
final AtomicBoolean errors = new AtomicBoolean(false);
|
|
for (String s : option.getResult()) {
|
|
final FileGroup group = new FileGroup(s, option.getExcludes(), option);
|
|
for (final File f : group.getFiles()) {
|
|
executor.submit(new Runnable() {
|
|
public void run() {
|
|
if (errors.get()) {
|
|
return;
|
|
}
|
|
try {
|
|
final boolean error = manageFileInternal(f, option);
|
|
if (error) {
|
|
errors.set(true);
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
executor.shutdown();
|
|
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
|
|
return errors.get();
|
|
}
|
|
|
|
private static boolean manageFileInternal(File f, Option option) throws IOException, InterruptedException {
|
|
if (OptionFlags.getInstance().isMetadata()) {
|
|
System.out.println("------------------------");
|
|
System.out.println(f);
|
|
// new Metadata().readAndDisplayMetadata(f);
|
|
System.out.println();
|
|
System.out.println(new MetadataTag(f, "plantuml").getData());
|
|
System.out.println("------------------------");
|
|
return false;
|
|
}
|
|
final ISourceFileReader sourceFileReader;
|
|
if (option.getOutputFile() == null) {
|
|
sourceFileReader = new SourceFileReader(option.getDefaultDefines(), f, option.getOutputDir(),
|
|
option.getConfig(), option.getCharset(), option.getFileFormatOption());
|
|
} else {
|
|
sourceFileReader = new SourceFileReader2(option.getDefaultDefines(), f, option.getOutputFile(),
|
|
option.getConfig(), option.getCharset(), option.getFileFormatOption());
|
|
}
|
|
if (option.isComputeurl()) {
|
|
final List<String> urls = sourceFileReader.getEncodedUrl();
|
|
for (String s : urls) {
|
|
System.out.println(s);
|
|
}
|
|
return false;
|
|
} else if (option.isCheckOnly()) {
|
|
return sourceFileReader.hasError();
|
|
}
|
|
final List<GeneratedImage> result = sourceFileReader.getGeneratedImages();
|
|
if (OptionFlags.getInstance().isFailOnError()) {
|
|
for (GeneratedImage i : result) {
|
|
if (i.isError()) {
|
|
Log.error("Error in file: " + f.getCanonicalPath());
|
|
}
|
|
if (i.isError() && OptionFlags.getInstance().isFailOnError()) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|