From 4a47fb97c5ad895be75575a460f1f6227f92493d Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Thu, 29 Aug 2013 15:01:29 -0400 Subject: [PATCH] 13.5.2-2 baseline Former-commit-id: 6cecce21eb6a7c9b72d7a61936dcbe4f4688fba9 --- MHSEmulator/.gitignore | 2 + MHSEmulator/out/SocketClient.jar | Bin 14539 -> 0 bytes MHSEmulator/out/SocketServer.jar | Bin 14538 -> 0 bytes MHSEmulator/src/mhs/core/MhsUtil.java | 103 +- MHSEmulator/src/mhs/core/RsyncThread.java | 105 +- MHSEmulator/src/mhs/core/SocketSrv.java | 370 ++++--- .../static/win32.x86/alertviz/alertviz.bat | 69 -- cave/build/static/win32.x86/cave/cave.bat | 72 -- .../uf/viz/core/AbstractGraphicsTarget.java | 9 + .../raytheon/uf/viz/core/IGraphicsTarget.java | 23 +- .../viz/core/drawables/AbstractAWTFont.java | 165 +++ .../core/drawables/AbstractDescriptor.java | 53 +- .../raytheon/uf/viz/core/drawables/IFont.java | 7 +- .../uf/viz/kml/export/graphics/KmlFont.java | 81 +- .../export/graphics/KmlGraphicsTarget.java | 6 +- .../graphics/DispatchGraphicsTarget.java | 21 +- .../raytheon/viz/core/gl/internal/GLFont.java | 128 +-- .../viz/core/gl/internal/GLTarget.java | 12 +- .../com/raytheon/viz/mpe/util/RenderPcp.java | 814 +++------------ .../viz/mpe/util/RenderPcpBlocking.java | 957 ++++++++++++++++++ .../viz/mpe/util/RenderPcpStandard.java | 603 +++++++++++ .../META-INF/MANIFEST.MF | 3 +- .../dialogs/EmergencyConfirmationMsg.java | 196 ++++ .../dialogs/IWarnGenConfirmationable.java | 67 ++ .../texteditor/dialogs/QCConfirmationMsg.java | 66 ++ .../dialogs/SendConfirmationMsg.java | 102 ++ .../texteditor/dialogs/TextEditorDialog.java | 466 +++++---- .../dialogs/WarnGenConfirmationDlg.java | 4 +- .../viz/warngen/gis/AffectedAreas.java | 12 +- .../com/raytheon/viz/warngen/gis/Area.java | 47 +- .../viz/warngen/gis/CoverageConstants.java | 178 ++++ .../raytheon/viz/warngen/gis/EntityData.java | 65 ++ .../raytheon/viz/warngen/gis/GridUtil.java | 616 +++++++++++ .../viz/warngen/gis/PortionsUtil.java | 471 +++++++++ .../{suppress => gis}/SuppressMap.java | 108 +- .../viz/warngen/gui/FollowupData.java | 5 + .../viz/warngen/gui/WarngenLayer.java | 135 ++- .../viz/warngen/template/TemplateRunner.java | 22 +- .../viz/warngen/util/CurrentWarnings.java | 2 + .../viz/warnings/rsc/AbstractWWAResource.java | 34 +- deltaScripts/13.5.2/addBufrmosDataURI.sh | 22 + .../deploy-common/deploy-gfesuite.xml | 4 + .../plugin/bufrmos/common/BufrMosAvnData.java | 12 + .../plugin/bufrmos/common/BufrMosHpcData.java | 12 + .../plugin/grib/GribLargeFileChecker.java | 6 +- .../common/geospatial/TransformFactory.java | 48 +- .../jaxb/SerializationContextFactory.java | 4 +- .../ServiceBackup/scripts/export_grids | 28 +- msi/AWIPSII.CAVE/AWIPSII.CAVE.suo | Bin 17920 -> 18432 bytes msi/AWIPSII.CAVE/AWIPSII.CAVE/AWIPSII.wxs | 39 +- msi/VizLauncher/VizLauncher.sln | 20 + msi/VizLauncher/VizLauncher.suo | Bin 0 -> 32768 bytes msi/VizLauncher/VizLauncher/Form1.Designer.cs | 79 ++ msi/VizLauncher/VizLauncher/Form1.cs | 20 + msi/VizLauncher/VizLauncher/Form1.resx | 120 +++ msi/VizLauncher/VizLauncher/Program.cs | 31 + .../VizLauncher/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 71 ++ .../VizLauncher/Properties/Resources.resx | 117 +++ .../Properties/Settings.Designer.cs | 30 + .../VizLauncher/Properties/Settings.settings | 7 + .../VizLauncher/VizLauncher.csproj | 94 ++ .../VizLauncher/VizLauncher.csproj.user | 3 + .../com/raytheon/viz/launcher/VizLauncher.cs | 68 ++ .../environment/EnvironmentProperties.cs | 34 + .../launcher/environment/VizEnvironment.cs | 137 +++ .../process/AbstractProcessLauncher.cs | 129 +++ .../viz/launcher/process/IProcessLauncher.cs | 16 + .../process/impl/AlertvizProcessLauncher.cs | 62 ++ .../process/impl/CaveProcessLauncher.cs | 38 + msi/build/A2Staging/Scripts/WiXBuild.ps1 | Bin 4372 -> 4396 bytes .../A2Staging/VisualStudio/VizLauncher.exe | Bin 0 -> 16384 bytes msi/build/A2Staging/VisualStudio/_DELETE_ME_ | 0 .../META-INF/MANIFEST.MF | 3 - .../Installer.gfesuite-client/component.spec | 5 +- .../Installer.gfesuite-server/component.spec | 5 +- rpms/build/i386/build.sh | 12 +- 77 files changed, 5798 insertions(+), 1713 deletions(-) create mode 100644 MHSEmulator/.gitignore delete mode 100644 MHSEmulator/out/SocketClient.jar delete mode 100644 MHSEmulator/out/SocketServer.jar delete mode 100644 cave/build/static/win32.x86/alertviz/alertviz.bat delete mode 100644 cave/build/static/win32.x86/cave/cave.bat create mode 100644 cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractAWTFont.java create mode 100644 cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpBlocking.java create mode 100644 cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpStandard.java create mode 100644 cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/EmergencyConfirmationMsg.java create mode 100644 cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/IWarnGenConfirmationable.java create mode 100644 cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/QCConfirmationMsg.java create mode 100644 cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/SendConfirmationMsg.java create mode 100644 cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/CoverageConstants.java create mode 100644 cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/EntityData.java create mode 100644 cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GridUtil.java create mode 100644 cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PortionsUtil.java rename cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/{suppress => gis}/SuppressMap.java (55%) create mode 100644 deltaScripts/13.5.2/addBufrmosDataURI.sh create mode 100644 msi/VizLauncher/VizLauncher.sln create mode 100644 msi/VizLauncher/VizLauncher.suo create mode 100644 msi/VizLauncher/VizLauncher/Form1.Designer.cs create mode 100644 msi/VizLauncher/VizLauncher/Form1.cs create mode 100644 msi/VizLauncher/VizLauncher/Form1.resx create mode 100644 msi/VizLauncher/VizLauncher/Program.cs create mode 100644 msi/VizLauncher/VizLauncher/Properties/AssemblyInfo.cs create mode 100644 msi/VizLauncher/VizLauncher/Properties/Resources.Designer.cs create mode 100644 msi/VizLauncher/VizLauncher/Properties/Resources.resx create mode 100644 msi/VizLauncher/VizLauncher/Properties/Settings.Designer.cs create mode 100644 msi/VizLauncher/VizLauncher/Properties/Settings.settings create mode 100644 msi/VizLauncher/VizLauncher/VizLauncher.csproj create mode 100644 msi/VizLauncher/VizLauncher/VizLauncher.csproj.user create mode 100644 msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/VizLauncher.cs create mode 100644 msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/environment/EnvironmentProperties.cs create mode 100644 msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/environment/VizEnvironment.cs create mode 100644 msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/AbstractProcessLauncher.cs create mode 100644 msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/IProcessLauncher.cs create mode 100644 msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/impl/AlertvizProcessLauncher.cs create mode 100644 msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/impl/CaveProcessLauncher.cs create mode 100644 msi/build/A2Staging/VisualStudio/VizLauncher.exe delete mode 100644 msi/build/A2Staging/VisualStudio/_DELETE_ME_ diff --git a/MHSEmulator/.gitignore b/MHSEmulator/.gitignore new file mode 100644 index 0000000000..5eb5c53762 --- /dev/null +++ b/MHSEmulator/.gitignore @@ -0,0 +1,2 @@ +out/ +*.jar diff --git a/MHSEmulator/out/SocketClient.jar b/MHSEmulator/out/SocketClient.jar deleted file mode 100644 index ad6f0e5f71be06af99ac9cdce198970f2f3b4321..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14539 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 M1PG{s?XS202l@_laR2}S diff --git a/MHSEmulator/src/mhs/core/MhsUtil.java b/MHSEmulator/src/mhs/core/MhsUtil.java index 236bc7c38e..06b1b105de 100644 --- a/MHSEmulator/src/mhs/core/MhsUtil.java +++ b/MHSEmulator/src/mhs/core/MhsUtil.java @@ -5,10 +5,30 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; +import java.io.IOException; import java.net.InetAddress; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Date; +/** + * Library module for MHS emulator. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * ??? ??  ????            bphillip     Initial creation
+ * Jul 15, 2013  #2099     dgilling     Use safer exception handling for file I/O.
+ * 
+ * 
+ * + * @author bphillip + * @version 1.0 + */ public class MhsUtil { public static final SimpleDateFormat logDateFormat = new SimpleDateFormat( @@ -19,32 +39,51 @@ public class MhsUtil { public static final String END_TOKEN = "------!!!!END!!!!------"; - public static final File MY_MHS_FILE = new File( - "/awips2/.myMHS"); + public static final File MY_MHS_FILE = new File("/awips2/.myMHS"); - public static final File MSG_ID_FILE = new File( - "/awips2/.msgCount"); + public static final File MSG_ID_FILE = new File("/awips2/.msgCount"); - public static String getMsgId() throws Exception { - if (!MSG_ID_FILE.exists()) { - MSG_ID_FILE.createNewFile(); - BufferedWriter out = new BufferedWriter(new FileWriter(MSG_ID_FILE)); - out.write("0"); - out.close(); + private MhsUtil() { + throw new AssertionError(); + } + + public static String getMsgId() throws IOException { + if (MSG_ID_FILE.createNewFile()) { + BufferedWriter out = null; + try { + out = new BufferedWriter(new FileWriter(MSG_ID_FILE)); + out.write("0"); + } finally { + if (out != null) { + out.close(); + } + } } + BufferedReader in = null; - in = new BufferedReader(new FileReader(MSG_ID_FILE)); - String msgId = in.readLine().trim(); - int newMsgNumber = Integer.parseInt(msgId) + 1; - in.close(); - BufferedWriter out = new BufferedWriter(new FileWriter(MSG_ID_FILE)); - out.write(String.valueOf(newMsgNumber)); - out.close(); - for (int i = msgId.length(); i < 6; i++) { - msgId = "0" + msgId; + int newMsgNumber; + try { + in = new BufferedReader(new FileReader(MSG_ID_FILE)); + String msgId = in.readLine().trim(); + newMsgNumber = Integer.parseInt(msgId) + 1; + } finally { + if (in != null) { + in.close(); + } } - return msgId; + BufferedWriter out = null; + try { + out = new BufferedWriter(new FileWriter(MSG_ID_FILE)); + out.write(String.valueOf(newMsgNumber)); + } finally { + if (out != null) { + out.close(); + } + } + + NumberFormat formatter = new DecimalFormat("000000"); + return formatter.format(newMsgNumber); } public static int byteArrayToInt(byte[] b, int offset) { @@ -73,26 +112,26 @@ public class MhsUtil { logFile = new File(logDir + InetAddress.getLocalHost().getCanonicalHostName() + "-" + mode + "-" + MhsUtil.logDateFormat.format(new Date())); + logFile.createNewFile(); - if (logFile != null) { - if (!logFile.exists()) { - logFile.createNewFile(); - } - } message += MhsUtil.logMsgFormat.format(new Date()); for (Object obj : msg) { message += obj.toString() + " "; } message += "\n"; - BufferedWriter out = new BufferedWriter(new FileWriter(logFile, - true)); - out.write(message.trim()); - out.write("\n"); - out.close(); - + BufferedWriter out = null; + try { + out = new BufferedWriter(new FileWriter(logFile, true)); + out.write(message.trim()); + out.write("\n"); + } finally { + if (out != null) { + out.close(); + } + } } catch (Exception e) { - // ignore + e.printStackTrace(); } } diff --git a/MHSEmulator/src/mhs/core/RsyncThread.java b/MHSEmulator/src/mhs/core/RsyncThread.java index a68224f9f1..b8c582a189 100644 --- a/MHSEmulator/src/mhs/core/RsyncThread.java +++ b/MHSEmulator/src/mhs/core/RsyncThread.java @@ -1,59 +1,68 @@ package mhs.core; import java.io.File; +import java.io.FileFilter; +import java.util.Collection; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; import java.util.Properties; -public class RsyncThread extends Thread { +/** + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * ??? ??  ????            bphillip     Initial creation
+ * Jul 15, 2013  #2099     dgilling     Modify to support recursive file listing
+ *                                      since export grids dir structure uses
+ *                                      multiple folders.
+ * 
+ * 
+ * + * @author bphillip + * @version 1.0 + */ +public class RsyncThread implements Runnable { + + private static final Map fileVersion = new HashMap(); private Properties props; - private Map fileVersion; - public RsyncThread(Properties props) { this.props = props; - fileVersion = new HashMap(); - this.setDaemon(true); } + @Override public void run() { - while (true) { - try { - Thread.sleep(1000); - } catch (Exception e) { - e.printStackTrace(); - } + String exportGridsDir = props.getProperty("EXPORT_GRIDS"); + String centralServerDir = props.getProperty("CENTRAL_SERVER"); + String packScriptDir = props.getProperty("UTIL_DIR"); - String exportGridsDir = (String) props.getProperty("EXPORT_GRIDS"); - String centralServerDir = (String) props - .getProperty("CENTRAL_SERVER"); - File[] fileList = new File(exportGridsDir).listFiles(); + Collection fileList = listCdfFiles(new File(exportGridsDir)); + for (File file : fileList) { + if (file.isFile()) { + String currentFilePath = file.getPath(); - String currentFilePath = null; - for (File file : fileList) { - if (file.isDirectory()) { - continue; + boolean copy = true; + if ((fileVersion.containsKey(currentFilePath)) + && (fileVersion.get(currentFilePath) >= file + .lastModified())) { + copy = false; } - currentFilePath = file.getPath(); - boolean copy = false; - if (fileVersion.containsKey(currentFilePath)) { - if (fileVersion.get(currentFilePath).longValue() != file - .lastModified()) { - copy = true; - } - } else { - copy = true; - } if (copy) { String[] copyCmd = new String[] { - centralServerDir + "/../util/packageFile",file.getPath(), - centralServerDir + "/../util/", - file.getName().substring(0, 3), centralServerDir }; + packScriptDir + "/packageFile", currentFilePath, + packScriptDir, file.getName().substring(0, 3), + centralServerDir }; try { Runtime.getRuntime().exec(copyCmd); - fileVersion.put(file.getPath(), file.lastModified()); + fileVersion.put(currentFilePath, file.lastModified()); } catch (Exception e) { e.printStackTrace(); } @@ -61,4 +70,34 @@ public class RsyncThread extends Thread { } } } + + private Collection listCdfFiles(File path) { + Collection fileList = new LinkedList(); + FileFilter cdfFilter = new FileFilter() { + + @Override + public boolean accept(File pathname) { + return (pathname.isDirectory() || pathname.getName().endsWith( + ".netcdf")); + } + }; + innerListFiles(path, fileList, cdfFilter); + return fileList; + } + + private void innerListFiles(File path, Collection fileList, + FileFilter filter) { + try { + File[] matchingFiles = path.listFiles(filter); + for (File file : matchingFiles) { + if (file.isDirectory()) { + innerListFiles(file, fileList, filter); + } else if (file.isFile()) { + fileList.add(file); + } + } + } catch (SecurityException e) { + e.printStackTrace(); + } + } } diff --git a/MHSEmulator/src/mhs/core/SocketSrv.java b/MHSEmulator/src/mhs/core/SocketSrv.java index a17e435ade..356f589df5 100644 --- a/MHSEmulator/src/mhs/core/SocketSrv.java +++ b/MHSEmulator/src/mhs/core/SocketSrv.java @@ -1,5 +1,6 @@ package mhs.core; +import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -7,27 +8,64 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; +import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +import java.net.UnknownHostException; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * ??? ??  ????            bphillip     Initial creation
+ * Jul 15, 2013  #2009     dgilling     Code cleanup.
+ * Jul 23, 2013  #2009     dgilling     Fix NullPointerException on start up.
+ * 
+ * 
+ * + * @author bphillip + * @version 1.0 + */ public class SocketSrv { + private File propertiesFile; + + private boolean runRsync; + + private String myMHS; + + private Properties serverProps; + + private ExecutorService mhsRequestHandler; + + private ScheduledExecutorService rsyncThread; + private int fileIndex = 0; private String fileBase; - private Properties serverProps; - private String configDir; private String centralServerDir; @@ -38,131 +76,191 @@ public class SocketSrv { private Map commandMap; - private RsyncThread rsync; - - private String propertiesFile; - - private String myMHS; + private int serverPort; public static void main(String[] args) { - if (!System.getProperty("user.name").equals("root")) { System.out .println("Socket Server must be run as root user! Current user: " + System.getProperty("user.name")); System.exit(1); } + + File propertiesFile = new File(args[0]); + String mhsId = args[1]; + boolean startRsync = Boolean.parseBoolean(args[2]); + + if (!propertiesFile.isFile()) { + System.out.println("Specified properties file [" + + propertiesFile.toString() + "] does not exist. Exiting."); + System.exit(1); + } + try { - SocketSrv srv = null; - srv = new SocketSrv(args[0], args[1], args[2]); - srv.run(); + final SocketSrv server = new SocketSrv(propertiesFile, mhsId, + startRsync); + Runtime.getRuntime().addShutdownHook(new Thread() { + + @Override + public void run() { + server.shutdown(); + } + }); + server.run(); } catch (Exception e) { e.printStackTrace(); } } - private SocketSrv(String propertiesFile, String myMHS, String startRsync) - throws Exception { - this.propertiesFile = propertiesFile; - this.myMHS = myMHS; - - writeMyMHS(myMHS); + private SocketSrv(File propertiesFile, String mhsId, boolean startRsync) + throws UnknownHostException, IOException { System.out.println("Setting up server (" + InetAddress.getLocalHost().getCanonicalHostName() + ")"); - commandMap = new HashMap(); - configDir = propertiesFile.substring(0, - propertiesFile.lastIndexOf(File.separator) + 1); - loadProperties(true); - if (startRsync.equals("true")) { - System.out.println("Starting Rsync Thread..."); - rsync = new RsyncThread(serverProps); - rsync.start(); - System.out.println("Rsync Thread started!"); - } - } + this.propertiesFile = propertiesFile; + this.myMHS = mhsId; + this.runRsync = startRsync; - private void writeMyMHS(String myMHS) throws Exception { - BufferedWriter out = new BufferedWriter(new FileWriter( - MhsUtil.MY_MHS_FILE)); - out.write(myMHS + "\n"); - out.write(this.propertiesFile); - out.close(); - } + writeMyMHS(myMHS); - private void loadProperties(boolean print) throws Exception { - serverProps = new Properties(); - FileInputStream fis = new FileInputStream(propertiesFile); - serverProps.load(fis); - fis.close(); - fileBase = serverProps.getProperty("DATA_FOLDER"); - centralServerDir = serverProps.getProperty("CENTRAL_SERVER"); - binDir = serverProps.getProperty("UTIL_DIR"); + this.commandMap = new HashMap(); + this.configDir = this.propertiesFile.getParent(); + loadProperties(); loadRcvHandlerTable(); - if (print) { - System.out.println(" Received Data directory: " + fileBase); - System.out.println("Central Server Data Directory: " - + centralServerDir); - System.out.println(" Config directory: " + configDir); + + this.fileBase = serverProps.getProperty("DATA_FOLDER"); + this.centralServerDir = serverProps.getProperty("CENTRAL_SERVER"); + this.binDir = serverProps.getProperty("UTIL_DIR"); + this.serverPort = Integer.parseInt(serverProps + .getProperty("SERVER_PORT")); + + System.out.println("\tReceived Data directory: " + fileBase); + System.out.println("\tCentral Server Data Directory: " + + centralServerDir); + System.out.println("\tConfig directory: " + configDir); + + this.mhsRequestHandler = Executors.newSingleThreadExecutor(); + if (this.runRsync) { + System.out.println("Starting Rsync Thread..."); + this.rsyncThread = Executors.newSingleThreadScheduledExecutor(); } } - public void run() throws Exception { + public void run() throws IOException { + if (rsyncThread != null) { + Runnable rsyncJob = new RsyncThread(serverProps); + rsyncThread + .scheduleWithFixedDelay(rsyncJob, 1, 1, TimeUnit.SECONDS); + } - int port = Integer.parseInt((String) serverProps.get("SERVER_PORT")); - ServerSocket srv = new ServerSocket(port); + ServerSocket socket = new ServerSocket(serverPort); + while (!mhsRequestHandler.isShutdown()) { + try { + log("Waiting for connections..."); + final Socket conn = socket.accept(); + Runnable processTask = new Runnable() { - while (true) { - log("Waiting for connections..."); - Socket socket = srv.accept(); - InetSocketAddress client = (InetSocketAddress) socket - .getRemoteSocketAddress(); - log("Connected to client: " + client.getHostName() + " at " - + client); - loadProperties(false); - String sender = getMhsOfSender(client); - log("Message is from: " + sender); - - InputStream in = socket.getInputStream(); - byte[] message = null; - Map params = new HashMap(); - String flag = ""; - while (true) { - if (in.available() == 0) { - Thread.sleep(100); - continue; - } - - message = getMessage(in); - - if (message.length < 50) { - String strMessage = new String(message); - if (strMessage.equals(MhsUtil.END_TOKEN)) { - log("Disconnected from client: " + client); - if (params.containsKey("-c")) { - executeAction(sender, params); - files.clear(); - params.clear(); - flag = ""; + @Override + public void run() { + try { + handleRequest(conn); + } catch (Exception e) { + e.printStackTrace(); } - break; } - if (strMessage.startsWith("-")) { - flag = strMessage; - } else { - params.put(flag, strMessage); - } - } else { - log("File Received of size: " + message.length); - files.add(writeToFile(myMHS + "-" + params.get("-MSGID"), - message)); + }; + mhsRequestHandler.execute(processTask); + } catch (RejectedExecutionException e) { + if (!mhsRequestHandler.isShutdown()) { + e.printStackTrace(); } } } } + public void shutdown() { + mhsRequestHandler.shutdown(); + if (rsyncThread != null) { + rsyncThread.shutdown(); + } + } + + private void handleRequest(Socket connection) throws IOException, + InterruptedException { + InetSocketAddress client = (InetSocketAddress) connection + .getRemoteSocketAddress(); + log("Connected to client: " + client.getHostName() + " at " + client); + + loadProperties(); + String sender = getMhsOfSender(client); + log("Message is from: " + sender); + + InputStream in = connection.getInputStream(); + byte[] message = null; + Map params = new HashMap(); + String flag = ""; + while (true) { + if (in.available() == 0) { + Thread.sleep(100); + continue; + } + + message = getMessage(in); + + if (message.length < 50) { + String strMessage = new String(message); + if (strMessage.equals(MhsUtil.END_TOKEN)) { + log("Disconnected from client: " + client); + if (params.containsKey("-c")) { + executeAction(sender, params); + files.clear(); + params.clear(); + flag = ""; + } + break; + } + if (strMessage.startsWith("-")) { + flag = strMessage; + } else { + params.put(flag, strMessage); + } + } else { + log("File Received of size: " + message.length); + files.add(writeToFile(myMHS + "-" + params.get("-MSGID"), + message)); + } + } + } + + private void writeMyMHS(String myMHS) throws IOException { + BufferedWriter out = null; + try { + out = new BufferedWriter(new FileWriter(MhsUtil.MY_MHS_FILE)); + out.write(myMHS + "\n"); + out.write(propertiesFile.getPath()); + } finally { + if (out != null) { + out.close(); + } + } + } + + private void loadProperties() throws IOException { + FileInputStream fis = null; + try { + fis = new FileInputStream(propertiesFile); + Properties newProps = new Properties(); + newProps.load(fis); + serverProps = newProps; + } finally { + if (fis != null) { + fis.close(); + } + } + } + private void executeAction(String sender, Map params) - throws Exception { + throws IOException, InterruptedException { int action = Integer.parseInt(params.get("-c")); if (!commandMap.containsKey(action)) { @@ -200,31 +298,19 @@ public class SocketSrv { command = command.replace("%SENDER", sender.toLowerCase()); String[] cmdArray = command.split(" "); log("Executing: " + command); - // - // Map sysEnv = System.getenv(); - // Map newEnv = new HashMap(); - // for (String key : sysEnv.keySet()) { - // newEnv.put(key, sysEnv.get(key)); - // } - // newEnv.put("PATH", "/awips2/python/bin/:"+sysEnv.get("PATH")); - // newEnv.put("LD_PRELOAD", "/awips2/python/lib/libpython2.7.so"); - // newEnv.put("LD_LIBRARY_PATH", "/awips2/python/lib"); - // String[] envp = new String[newEnv.keySet().size()]; - // int i = 0; - // for (String key : newEnv.keySet()) { - // envp[i] = key.trim() + "=" + newEnv.get(key).trim(); - // i++; - // } + Process p = null; try { p = Runtime.getRuntime().exec(cmdArray); p.waitFor(); } finally { - p.destroy(); + if (p != null) { + p.destroy(); + } } } - private byte[] getMessage(InputStream in) throws Exception { + private byte[] getMessage(InputStream in) throws IOException { byte[] sizeBytes = new byte[4]; readBytes(in, sizeBytes); int expectedSize = MhsUtil.byteArrayToInt(sizeBytes, 0); @@ -233,7 +319,7 @@ public class SocketSrv { return message; } - private void readBytes(InputStream in, byte[] bytes) throws Exception { + private void readBytes(InputStream in, byte[] bytes) throws IOException { int expectedSize = bytes.length; int bytesRead = 0; int totalBytesRead = 0; @@ -245,13 +331,20 @@ public class SocketSrv { } private String writeToFile(String fileName, byte[] contents) - throws Exception { + throws IOException, InterruptedException { String fileFQN = fileBase + fileName + "." + getFileIndex(); log("Writing file: " + fileFQN); - FileOutputStream fos = new FileOutputStream(new File(fileFQN)); - fos.write(contents); - fos.flush(); - fos.close(); + + BufferedOutputStream out = null; + try { + out = new BufferedOutputStream(new FileOutputStream(new File( + fileFQN))); + out.write(contents); + } finally { + if (out != null) { + out.close(); + } + } Process p = null; try { @@ -259,7 +352,9 @@ public class SocketSrv { new String[] { "/bin/chmod", "777", fileFQN }); p.waitFor(); } finally { - p.destroy(); + if (p != null) { + p.destroy(); + } } return fileFQN; } @@ -269,40 +364,34 @@ public class SocketSrv { if (fileIndex == 1000) { fileIndex = 0; } - String fileNumber = String.valueOf(fileIndex); - if (fileNumber.length() == 1) { - fileNumber = "00" + fileNumber; - } else if (fileNumber.length() == 2) { - fileNumber = "0" + fileNumber; - } - return fileNumber; + + NumberFormat formatter = new DecimalFormat("000"); + return formatter.format(fileIndex); } - private void loadRcvHandlerTable() throws Exception { + private void loadRcvHandlerTable() throws IOException { BufferedReader in = null; try { - in = new BufferedReader(new FileReader(configDir + in = new BufferedReader(new FileReader(configDir + File.separator + "rcv_handler.tbl")); - String str = null; - String[] tokens = null; + String str = null; while ((str = in.readLine()) != null) { - String command = ""; - tokens = str.split(" "); + StringBuilder commandBuilder = new StringBuilder(); + String[] tokens = str.split(" "); for (int i = 1; i < tokens.length; i++) { String cmd = tokens[i].trim(); if (!cmd.isEmpty()) { if (i != 1) { - command += " "; + commandBuilder.append(' '); } - command += cmd; + commandBuilder.append(cmd); } } - command = command.trim(); - commandMap.put(Integer.parseInt(tokens[0]), command); + String commandString = commandBuilder.toString().trim(); + commandMap.put(Integer.parseInt(tokens[0]), commandString); } - in.close(); } finally { if (in != null) { in.close(); @@ -311,20 +400,19 @@ public class SocketSrv { } private String getMhsOfSender(InetSocketAddress address) { - String hostAddress = address.getAddress().getHostAddress(); - for (Object key : serverProps.keySet()) { - String value = serverProps.getProperty((String) key); + for (String mhsId : serverProps.stringPropertyNames()) { + String value = serverProps.getProperty(mhsId); if (value.contains(",")) { String[] addrs = value.split(","); for (String addr : addrs) { if (addr.contains(hostAddress)) { - return (String) key; + return mhsId; } } } else { if (value.contains(hostAddress)) { - return (String) key; + return mhsId; } } } diff --git a/cave/build/static/win32.x86/alertviz/alertviz.bat b/cave/build/static/win32.x86/alertviz/alertviz.bat deleted file mode 100644 index 5e4b50ee83..0000000000 --- a/cave/build/static/win32.x86/alertviz/alertviz.bat +++ /dev/null @@ -1,69 +0,0 @@ -@echo OFF - -REM Determine if we are running on a 32-bit or 64-bit OS. -IF NOT EXIST C:\Windows\SysWOW64\reg.exe ( - SET REG_EXE=C:\Windows\System32\reg.exe -) ELSE ( - SET REG_EXE=C:\Windows\SysWOW64\reg.exe -) - -REM Determine where we are located. -SET CONTAINING_DIRECTORY=%~dp0 - -REM Prepare the environment. - -REM Registry Query Variables. -SET A2_JAVA_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Java" -SET A2_PYTHON_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Python" -REM Determine where AWIPS II Java (the jre) is located. -%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory > NUL 2>&1 -IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Java. && PAUSE && EXIT) -FOR /F "tokens=2* delims= " %%A IN ( -'%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory') DO ( -SET JavaJreDirectory=%%B) -REM Determine where AWIPS II Python is located. -%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory > NUL 2>&1 -IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Python. && PAUSE && EXIT) -FOR /F "tokens=2* delims= " %%A IN ( -'%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory') DO ( -SET PythonInstallDirectory=%%B) - -REM Add Java and Python to the path. -SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path% -SET Path=%JavaJreDirectory%\bin;%Path% -REM Define 'PythonPath'. -SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath% -SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath% -SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath% -SET PythonPath=%PythonInstallDirectory%;%PythonPath% - -REM Eliminate variables that will no longer be used. -SET PythonInstallDirectory= -SET JavaJreDirectory= -SET REG_EXE= -SET A2_JAVA_REG= -SET A2_PYTHON_REG= - -REM Determine where we will be logging to. -SET HOME_DIRECTORY=%HOMEDRIVE%%HOMEPATH% -SET CAVEDATA_LOG_DIRECTORY=%HOMEDRIVE%%HOMEPATH%\caveData\logs -SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME% -IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%") - -echo Starting ALERTVIZ; leave this CMD window open to enable AlertViz 'restart'. -REM Start AlertViz (and implement the alertviz restart capability). -:AlertVizLoopStart -SET RND=%random% -SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp -REM Python is used to retrieve the current date and time because the order -REM of the Windows date/time fields is not necessarily guaranteed and the -REM Windows date/time fields can only be extracted using substring operations -REM instead of -formatter- strings like Linux allows. -python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE% -SET /p LOG_DATETIME= < %RND_DATETIME_FILE% -DEL %RND_DATETIME_FILE% -"%CONTAINING_DIRECTORY%alertviz.exe" %* > "%CONSOLE_LOG_DIRECTORY%\alertviz_%LOG_DATETIME%.log" 2>&1 -IF %ERRORLEVEL% == 0 (EXIT) -echo Restarting AlertViz. -GOTO AlertVizLoopStart - diff --git a/cave/build/static/win32.x86/cave/cave.bat b/cave/build/static/win32.x86/cave/cave.bat deleted file mode 100644 index 0b347287dd..0000000000 --- a/cave/build/static/win32.x86/cave/cave.bat +++ /dev/null @@ -1,72 +0,0 @@ -@echo OFF - -REM Determine if we are running on a 32-bit or 64-bit OS. -IF NOT EXIST C:\Windows\SysWOW64\reg.exe ( - SET REG_EXE=C:\Windows\System32\reg.exe -) ELSE ( - SET REG_EXE=C:\Windows\SysWOW64\reg.exe -) - -REM Determine where we are located. -SET CONTAINING_DIRECTORY=%~dp0 - -REM Prepare the environment. - -REM Registry Query Variables. -SET A2_JAVA_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Java" -SET A2_PYTHON_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Python" -REM Determine where AWIPS II Java (the jre) is located. -%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory > NUL 2>&1 -IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Java. && PAUSE && EXIT) -FOR /F "tokens=2* delims= " %%A IN ( -'%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory') DO ( -SET JavaJreDirectory=%%B) -REM Determine where AWIPS II Python is located. -%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory > NUL 2>&1 -IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Python. && PAUSE && EXIT) -FOR /F "tokens=2* delims= " %%A IN ( -'%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory') DO ( -SET PythonInstallDirectory=%%B) - -REM Add Java and Python to the path. -SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path% -SET Path=%JavaJreDirectory%\bin;%Path% -REM Add the CAVE lib directory to the path. -SET Path=%CONTAINING_DIRECTORY%lib;%Path% -REM Define 'PythonPath'. -SET PythonPath=%CONTAINING_DIRECTORY%lib;%PythonPath% -SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath% -SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath% -SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath% -SET PythonPath=%PythonInstallDirectory%;%PythonPath% - -REM Eliminate variables that will no longer be used. -SET PythonInstallDirectory= -SET JavaJreDirectory= -SET REG_EXE= -SET A2_JAVA_REG= -SET A2_PYTHON_REG= - -REM Determine where we will be logging to. -SET HOME_DIRECTORY=%HOMEDRIVE%%HOMEPATH% -SET CAVEDATA_LOG_DIRECTORY=%HOMEDRIVE%%HOMEPATH%\caveData\logs -SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME% -IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%") - -SET RND=%random% -SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp -REM Python is used to retrieve the current date and time because the order -REM of the Windows date/time fields is not necessarily guaranteed and the -REM Windows date/time fields can only be extracted using substring operations -REM instead of -formatter- strings like Linux allows. -python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE% -SET /p LOG_DATETIME= < %RND_DATETIME_FILE% -DEL %RND_DATETIME_FILE% - -echo THIS CMD WINDOW CAN BE CLOSED AT ANY TIME! -cd %HOMEPATH% -REM Start CAVE. -"%CONTAINING_DIRECTORY%cave.exe" %* > "%CONSOLE_LOG_DIRECTORY%\cave_%LOG_DATETIME%.log" 2>&1 -IF ERRORLEVEL 1 (echo CAVE ERROR - check the logs for additional information. && PAUSE) - -EXIT diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/AbstractGraphicsTarget.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/AbstractGraphicsTarget.java index 47d1b29b57..548268afa9 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/AbstractGraphicsTarget.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/AbstractGraphicsTarget.java @@ -21,6 +21,7 @@ package com.raytheon.uf.viz.core; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -41,6 +42,8 @@ import com.raytheon.uf.viz.core.data.resp.NumericImageData; import com.raytheon.uf.viz.core.drawables.ColorMapLoader; import com.raytheon.uf.viz.core.drawables.IDescriptor; import com.raytheon.uf.viz.core.drawables.IFont; +import com.raytheon.uf.viz.core.drawables.IFont.FontType; +import com.raytheon.uf.viz.core.drawables.IFont.Style; import com.raytheon.uf.viz.core.drawables.IImage; import com.raytheon.uf.viz.core.drawables.IShadedShape; import com.raytheon.uf.viz.core.drawables.IWireframeShape; @@ -62,6 +65,7 @@ import com.raytheon.uf.viz.core.exception.VizException; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 25, 2012 bsteffen Initial creation + * Jul 18, 2013 2189 mschenke Added ability to specify font type * * * @@ -82,6 +86,11 @@ public abstract class AbstractGraphicsTarget implements IGraphicsTarget { extensionManager = new GraphicsExtensionManager(this); } + @Override + public IFont initializeFont(File fontFile, float size, Style[] styles) { + return initializeFont(fontFile, FontType.TRUETYPE, size, styles); + } + @Override public boolean drawRasters(PaintProperties paintProps, DrawableImage... images) throws VizException { diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/IGraphicsTarget.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/IGraphicsTarget.java index 21e4e69cf6..b7e3285ee1 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/IGraphicsTarget.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/IGraphicsTarget.java @@ -59,6 +59,7 @@ import com.raytheon.uf.viz.core.exception.VizException; * track any needed updates to the Target extents. * This functionality is primarily used by the * Feature Following Zoom Tool at this time. + * 7/18/13 #2189 mschenke Added ability to specify font type * * * @@ -234,8 +235,10 @@ public interface IGraphicsTarget extends IImagingExtension { IFont.Style[] styles); /** - * Create a font object from a truetype font + * Create a font object from a truetype font file * + * @deprecated {@link #initializeFont(File, com.raytheon.uf.viz.core.drawables.IFont.FontType, float, com.raytheon.uf.viz.core.drawables.IFont.Style[])} + * should be used instead * * @param fontFile * the truetype font @@ -245,9 +248,27 @@ public interface IGraphicsTarget extends IImagingExtension { * the font styles * @return a prepared font reference */ + @Deprecated public abstract IFont initializeFont(File fontFile, float size, IFont.Style[] styles); + /** + * Create a font object from font file + * + * + * @param fontFile + * the font file + * @param type + * the type of the font file + * @param size + * the size in points + * @param styles + * the font styles + * @return a prepared font reference + */ + public abstract IFont initializeFont(File fontFile, IFont.FontType type, + float size, IFont.Style[] styles); + /** * Draw a raster to a target, given an extent and an alpha (transparency) * value. Assumes synchronous operation. diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractAWTFont.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractAWTFont.java new file mode 100644 index 0000000000..667e9374f4 --- /dev/null +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractAWTFont.java @@ -0,0 +1,165 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.core.drawables; + +import java.awt.Font; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Simple abstract base class for an AWT-based IFont implementations + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 24, 2013       2189 mschenke     Initial creation
+ * 
+ * 
+ * + * @author mschenke + * @version 1.0 + */ + +public abstract class AbstractAWTFont implements IFont { + + protected Font font; + + protected boolean scaleFont; + + protected boolean smoothing; + + protected AbstractAWTFont(String fontName, float fontSize, Style[] styles) { + this(new Font(fontName, toAwtStyle(styles), (int) fontSize)); + } + + protected AbstractAWTFont(File fontFile, FontType fontType, float fontSize, + Style[] styles) { + this(createFont(fontFile, fontType, fontSize, styles)); + } + + protected AbstractAWTFont(Font font) { + this.font = font; + } + + @Override + public final String getFontName() { + return font.getName(); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.core.drawables.IFont#getStyle() + */ + @Override + public final Style[] getStyle() { + return toVizStyles(font.getStyle()); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.core.drawables.IFont#setSmoothing(boolean) + */ + @Override + public final void setSmoothing(boolean smooth) { + this.smoothing = smooth; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.core.drawables.IFont#getSmoothing() + */ + @Override + public final boolean getSmoothing() { + return smoothing; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.core.drawables.IFont#isScaleFont() + */ + @Override + public final boolean isScaleFont() { + return scaleFont; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.core.drawables.IFont#setScaleFont(boolean) + */ + @Override + public final void setScaleFont(boolean scaleFont) { + this.scaleFont = scaleFont; + } + + protected static Font createFont(File fontFile, FontType fontType, + float fontSize, Style[] styles) { + try { + return Font.createFont(toAwtFontType(fontType), fontFile) + .deriveFont(fontSize).deriveFont(toAwtStyle(styles)); + } catch (Exception e) { + throw new IllegalArgumentException("Bad Font File", e); + } + } + + protected static int toAwtFontType(FontType type) { + switch (type) { + case TYPE1: + return Font.TYPE1_FONT; + case TRUETYPE: + default: + return Font.TRUETYPE_FONT; + } + } + + protected static int toAwtStyle(Style[] styles) { + int styleInt = Font.PLAIN; + if (styles == null || styles.length == 0) { + return styleInt; + } + for (Style style : styles) { + if (style == Style.BOLD) { + styleInt |= Font.BOLD; + } else if (style == Style.ITALIC) { + styleInt |= Font.ITALIC; + } + } + return styleInt; + } + + protected static Style[] toVizStyles(int style) { + List