Java tutorial
/** * JALPTest is a util file to test JALoP. * <p> * Source code in 3rd-party is licensed and owned by their respective * copyright holders. * <p> * All other source code is copyright Tresys Technology and licensed as below. * <p> * Copyright (c) 2012 Tresys Technology LLC, Columbia, Maryland, USA * <p> * This software was developed by Tresys Technology LLC * with U.S. Government sponsorship. * <p> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream.GetField; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.lang.OutOfMemoryError; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.Unmarshaller; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.PosixParser; import com.tresys.jalop.common.JALUtils.DMType; import com.tresys.jalop.producer.ApplicationMetadataXML; import com.tresys.jalop.producer.CustomXML; import com.tresys.jalop.producer.Producer; import com.tresys.jalop.producer.LoggerXML; import com.tresys.jalop.producer.SyslogXML; import com.tresys.jalop.schemas.mil.dod.jalop_1_0.applicationmetadatatypes.ApplicationMetadataType; public class JALPTest { /** * The main method that gets called to test JALoP. * * @param args the command line arguments */ public static void main(String[] args) { Producer producer = null; try { Options options = createOptions(); CommandLineParser parser = new PosixParser(); CommandLine cmd = parser.parse(options, args); String pathToXML = null; String type = null; String input = null; String privateKeyPath = null; String publicKeyPath = null; String certPath = null; String socketPath = null; Boolean hasDigest = false; File file = null; ApplicationMetadataXML xml = null; if (cmd.hasOption("h")) { System.out.println(usage); return; } if (cmd.hasOption("a")) { pathToXML = cmd.getOptionValue("a"); } if (cmd.hasOption("t")) { type = cmd.getOptionValue("t"); } if (cmd.hasOption("p")) { file = new File(cmd.getOptionValue("p")); } if (cmd.hasOption("s")) { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringBuilder sb = new StringBuilder(); String s; while ((s = in.readLine()) != null && s.length() != 0) { sb.append(s); sb.append("\n"); } input = sb.toString(); } if (cmd.hasOption("j")) { socketPath = cmd.getOptionValue("j"); } if (cmd.hasOption("k")) { privateKeyPath = cmd.getOptionValue("k"); } if (cmd.hasOption("b")) { publicKeyPath = cmd.getOptionValue("b"); } if (cmd.hasOption("c")) { certPath = cmd.getOptionValue("c"); } if (cmd.hasOption("d")) { hasDigest = true; } if (pathToXML != null) { xml = createXML(readXML(pathToXML)); } producer = createProducer(xml, socketPath, privateKeyPath, publicKeyPath, certPath, hasDigest); callSend(producer, type, input, file); } catch (IOException e) { if (producer != null) { System.out.println("Failed to open socket: " + producer.getSocketFile()); } else { System.out.println("Failed to create Producer"); } } catch (Exception e) { error(e.toString()); return; } } /** * Unmarshals an xml file into an ApplicationMetadataType. * * @param path the path to the xml file to be unmarshalled * @return the created ApplicationMetadataType * @throws Exception */ private static ApplicationMetadataType readXML(String path) throws Exception { JAXBContext jc = JAXBContext .newInstance("com.tresys.jalop.schemas.mil.dod.jalop_1_0.applicationmetadatatypes"); Unmarshaller unmarshaller = jc.createUnmarshaller(); JAXBElement<ApplicationMetadataType> jaxAmt = (JAXBElement<ApplicationMetadataType>) unmarshaller .unmarshal(new File(path)); return jaxAmt.getValue(); } /** * Creates an ApplicationMetadataXML of the proper type (LoggerXML, SyslogXML, CustomXML). * * @param amt the ApplicationMetadataType that has been unmarshalled from the xml * @return the ApplicationMetadataXML of the proper type * @throws Exception */ private static ApplicationMetadataXML createXML(ApplicationMetadataType amt) throws Exception { ApplicationMetadataXML xml = null; if (amt.getLogger() != null) { xml = new LoggerXML(amt.getLogger()); } else if (amt.getSyslog() != null) { xml = new SyslogXML(amt.getSyslog()); } else { xml = new CustomXML(amt.getCustom().toString()); } xml.setEventId(amt.getEventID()); xml.setJournalMetadata(amt.getJournalMetadata()); return xml; } /** * Creates a Producer using the given command line params. * * @param xml the ApplicationMetadataXML * @param socketPath a String which is the path to the socket * @param privateKeyPath a String which is the path to the private key in DER format * @param publicKeyPath a String which is the path to the public key in DER format * @param certPath a String which is the path to the certificate * @param hasDigest a Boolean, true to set a digest method in the producer * @return the created Producer * @throws Exception */ private static Producer createProducer(ApplicationMetadataXML xml, String socketPath, String privateKeyPath, String publicKeyPath, String certPath, Boolean hasDigest) throws Exception { Producer producer = new Producer(xml); producer.setSocketFile(socketPath); if (privateKeyPath != null && !"".equals(privateKeyPath)) { File privateKeyFile = new File(privateKeyPath); DataInputStream privateDis = new DataInputStream(new FileInputStream(privateKeyFile)); byte[] privateKeyBytes = new byte[(int) privateKeyFile.length()]; privateDis.readFully(privateKeyBytes); privateDis.close(); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); KeySpec privateKs = new PKCS8EncodedKeySpec(privateKeyBytes); PrivateKey privateKey = keyFactory.generatePrivate(privateKs); File publicKeyFile = new File(publicKeyPath); DataInputStream publicDis = new DataInputStream(new FileInputStream(publicKeyFile)); byte[] publicKeyBytes = new byte[(int) publicKeyFile.length()]; publicDis.readFully(publicKeyBytes); publicDis.close(); KeySpec publicKs = new X509EncodedKeySpec(publicKeyBytes); PublicKey publicKey = keyFactory.generatePublic(publicKs); producer.setPrivateKey(privateKey); producer.setPublicKey(publicKey); } if (certPath != null && !"".equals(certPath)) { InputStream inputStream = new FileInputStream(certPath); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); inputStream.close(); producer.setCertificate(cert); } if (hasDigest) { producer.setDigestMethod(DMType.SHA256); } return producer; } /** * Calls the right method in Producer to sign and send the data based on the type. * * @param producer the Producer * @param type the type input (l, a, j, f) * @param input a String that is a buffer * @param file a File which contains the buffer * @throws Exception */ private static void callSend(Producer producer, String type, String input, File file) throws Exception { if ("l".equals(type)) { if (file != null) { producer.jalpLog(file); } else { producer.jalpLog(input); } } else if ("a".equals(type)) { if (file != null) { producer.jalpAudit(file); } else { producer.jalpAudit(input); } } else if ("j".equals(type)) { if (file != null) { producer.jalpJournal(file); } else { producer.jalpJournal(input); } } else if ("f".equals(type)) { producer.jalpJournalFD(file); } else { error("record type of 'j', 'a', 'l', or 'f', must be specified."); } } static final String usage = "Usage:\n" + "-a (optional) the full, or relative path to a file to use for generating the application metadata.\n" + "-p The full or relative path to a file that should be used as the payload for this particular record.\n" + "-s Indicates the payload should be taken from <stdin>.\n" + "-t, --type=T Indicates which type of data to send: 'j' (journal record), 'a' (audit record), 'l' (log entry), or 'f' (journal record using file descriptor passing).\n" + "-h Print a summary of options.\n" + "-j The full or relative path to the JALoP socket.\n" + "-k The full or relative path to a private key file to be used for signing. Must also specify '-a'.\n" + "-b The full or relative path to a public key file to be used for signing. Must also specify '-a'.\n" + "-c The full or relative path to a certificate file to be used for signing. Requires '-k'.\n" + "-d Calculates and adds a SHA256 digest of the payload to the application metadata. Must also specify '-a'.\n"; /** * Prints an error message along with proper usage. * * @param message The String to print out as the error message */ private static void error(String message) { StringBuilder error = new StringBuilder("Error: bad usage, "); error.append(message); error.append("\n"); error.append(usage); System.out.println(error); } /** * Creates the options that can be used on the command line. * * @return the Options for the command line parser */ private static Options createOptions() { Options options = new Options(); options.addOption("a", true, "(optional) the full, or relative path to a file to use for generating the application metadata."); options.addOption("p", true, "The full or relative path to a file that should be used as the payload for this particular record."); options.addOption("s", false, "Indicates the payload should be taken from <stdin>."); options.addOption("t", "type", true, "Indicates which type of data to send: 'j' (journal record), 'a' (audit record), 'l' (log entry), or 'f' (journal record using file descriptor passing)."); options.addOption("h", false, "Print a summary of options."); options.addOption("j", true, "The full or relative path to the JALoP socket."); options.addOption("k", true, "The full or relative path to a private key file to be used for signing. Must also specify '-a'."); options.addOption("b", true, "The full or relative path to a public key file to be used for signing. Must also specify '-a'."); options.addOption("c", true, "The full or relative path to a certificate file to be used for signing. Requires '-k'."); options.addOption("d", false, "Calculates and adds a SHA256 digest of the payload to the application metadata. Must also specify '-a'."); return options; } }