Issue #2838 Archive binary feeder creation.

Change-Id: I4e431d62e3d27565af75d52012fe042a18fd1f9c

Former-commit-id: ac03675880 [formerly 9b7715e5e0] [formerly 995d962a66 [formerly 16c38960863df2f993c6ee7e18de31824cbdbb08]]
Former-commit-id: 995d962a66
Former-commit-id: 03843090fa
This commit is contained in:
Roger Ferrel 2014-02-25 10:11:20 -06:00
parent 29f9a87085
commit dae52ad3a0
14 changed files with 524 additions and 0 deletions

View file

@ -72,6 +72,13 @@
id="com.raytheon.uf.edex.archive.feature"
version="0.0.0"/>
<!-- Comment out this include before checking in. This plugin only for debugging. -->
<!--
<includes
id="com.raytheon.uf.edex.archive.feeder.feature"
version="0.0.0"/>
-->
<includes
id="com.raytheon.uf.edex.text.feature"
version="0.0.0"/>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.archive.feeder.feature</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.pde.FeatureBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.FeatureNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1 @@
bin.includes = feature.xml

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<feature
id="com.raytheon.uf.edex.archive.feeder.feature"
label="Archive Binary Feeder Feature"
version="1.0.0.qualifier"
provider-name="RAYTHEON">
<description url="http://www.example.com/description">
Use for testing of archive binary files. Not part of standard EDEX.
</description>
<copyright url="http://www.example.com/copyright">
[Enter Copyright Description here.]
</copyright>
<license url="http://www.example.com/license">
[Enter License Description here.]
</license>
<plugin
id="com.raytheon.uf.edex.archive.feeder"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.archive.feeder</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

View file

@ -0,0 +1,20 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Utility
Bundle-SymbolicName: com.raytheon.uf.edex.archive.feeder
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.raytheon.uf.edex.archive.feeder.Activator
Bundle-Vendor: RAYTHEON
Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.edex.common;bundle-version="1.12.1174",
com.raytheon.uf.edex.database;bundle-version="1.0.0",
org.eclipse.ui,
org.eclipse.core.runtime,
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
com.raytheon.uf.common.status;bundle-version="1.12.1174",
org.apache.camel;bundle-version="1.0.0",
com.raytheon.uf.edex.site;bundle-version="1.0.0",
com.raytheon.uf.edex.core;bundle-version="1.12.1174",
org.apache.commons.beanutils;bundle-version="1.8.3"
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy

View file

@ -0,0 +1,20 @@
The com.raytheon.uf.edex.archive.feeder plugin is not part of the standard EDEX deploy.
It is a tool for debugging the binary files generated for archiving.
The easiest way to generate this plugin jar is to add the following to
com.raytheon.edex.feature.uframe/feature.xml:
<includes
id="com.raytheon.uf.edex.archive.feeder.feature"
version="0.0.0"/>
Then run the build.edex deploy-install.xml. This will create the plugin jar file:
/awips2/edex/lib/plugins/com.raytheon.uf.edex.archive.feeder.jar
the needed configuration file:
/awips2/edex/conf/resources/com.raytheon.uf.edex.archive.feeder.properties
By placing these two files in the corresponding locations on the desired EDEX server and
restarting EDEX will start the clusteredArchiveBinaryFeederProc. You can then drop the
binary files into the archive.feeder.directory, default /tmp/archive-feeder.

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/

View file

@ -0,0 +1,19 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="clusteredArchiveBinaryFeederProc"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<endpoint id="abfFileEndpoint"
uri="file:${archive.feeder.directory}?delete=true&amp;delay=5000&amp;maxMessagesPerPoll=1000&amp;exclusiveReadLockStrategy=#abfFileChangedStrategy" />
<route id="abfFileScan">
<from ref="abfFileEndpoint" />
<bean ref="abfProc" method="processEvent" />
</route>
</camelContext>
<bean id="abfFileChangedStrategy" class="com.raytheon.uf.edex.esb.camel.FileChangedExclusiveReadLockStrategy"/>
<bean id="abfProc" class="com.raytheon.uf.edex.archive.feeder.ArchiveBinaryFeederIngester"/>
</beans>

View file

@ -0,0 +1,5 @@
# When true enables the archive binary feeder
archive.feeder.enable=true
# Directory to check for binary files to ingest.
archive.feeder.directory=/tmp/archive-feeder

View file

@ -0,0 +1,249 @@
/**
* 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.edex.archive.feeder;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.ManyToOne;
import org.apache.commons.beanutils.PropertyUtils;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.database.plugin.PluginDao;
import com.raytheon.uf.edex.database.plugin.PluginFactory;
/**
* This class used to process binary files created for the archive directory.
* Not intended for production. Designed for testing of problems with creating
* archive data.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 25, 2014 2838 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public class ArchiveBinaryFeederIngester {
protected static final IUFStatusHandler statusHandler = UFStatus
.getHandler(ArchiveBinaryFeederIngester.class);
/** The ManyToOne fields in a given class. */
private final Map<Class<?>, Field[]> manyToOneFieldMap = new HashMap<Class<?>, Field[]>();
/**
* The constructor. if needed attempts to created the drop directory
*/
public ArchiveBinaryFeederIngester() {
String rootName = System.getProperty("archive.feeder.directory");
if (rootName != null) {
File rootDir = new File(rootName);
if (rootDir.exists()) {
if (!rootDir.isDirectory()) {
if (rootDir.delete()) {
rootDir.mkdirs();
}
}
} else {
rootDir.mkdirs();
}
}
}
/**
* Process archive binary file.
*
* @param file
* @throws EdexException
*/
public void processEvent(File file) throws EdexException {
IUFStatusHandler statusHandler = UFStatus
.getHandler(ArchiveBinaryFeederIngester.class);
boolean enabled = Boolean.getBoolean("archive.feeder.enable");
if (!enabled) {
if (statusHandler.isPriorityEnabled(Priority.WARN)) {
StringBuilder sb = new StringBuilder(
ArchiveBinaryFeederIngester.class.getName());
sb.setLength(sb.lastIndexOf("."));
statusHandler
.handle(Priority.WARN,
String.format(
"file \"%s\" not processed; feeder not enabled consider removing plugin: %s",
file, sb.toString()));
}
return;
}
long start = System.currentTimeMillis();
ArchiveBinaryReader reader = new ArchiveBinaryReader(file);
try {
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.handle(
Priority.INFO,
String.format("Start processing file \"%1$s\".",
file.getAbsoluteFile()));
}
Object object = reader.getObject();
if (!(object instanceof List<?>)) {
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler
.info(String
.format("file: \"%s\" does not contain a list of PluginDataObjects",
file.getAbsolutePath()));
}
} else {
List<?> objects = (List<?>) object;
process(objects);
}
} catch (Exception e) {
if (statusHandler.isPriorityEnabled(Priority.PROBLEM)) {
statusHandler.handle(Priority.PROBLEM, String.format(
"Problem processing the file: \"%s\", %s",
file.getAbsolutePath(), e.getLocalizedMessage()));
}
} finally {
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
long time = System.currentTimeMillis() - start;
statusHandler.handle(Priority.INFO, String.format(
"Finished processing file \"%1$s\" in %2$d msec.",
file.getAbsoluteFile(), time));
}
}
}
/**
* Checks to see if the objects is a list of PluginDataObjects and attempts
* use the proper dao to send list to the data base.
*
* @param objects
* @throws PluginException
*/
private void process(List<?> objects) throws PluginException {
if (objects.size() > 0) {
Object o = objects.iterator().next();
if (o instanceof PluginDataObject) {
PluginDataObject pdo = (PluginDataObject) o;
String pdoName = pdo.getPluginName();
PluginDao dao = PluginFactory.getInstance().getPluginDao(
pdoName);
processManytoOneFields(objects, pdo.getClass(), dao);
dao.persistAll(objects);
} else {
throw new PluginException("Not a list of PluginDataObjects.");
}
}
}
/**
* Determine the fields in the class that are an instance of the ManyToOne
* class. This will always return a non null result.
*
* @param clazz
* @return fields
*/
private synchronized Field[] getManyToOneFields(Class<?> clazz) {
Field[] fields = manyToOneFieldMap.get(clazz);
if (fields == null) {
List<Field> fieldList = new ArrayList<Field>();
Class<?> currentClass = clazz;
while (currentClass != null) {
for (Field field : currentClass.getDeclaredFields()) {
if (field.getAnnotation(ManyToOne.class) != null) {
fieldList.add(field);
}
}
currentClass = currentClass.getSuperclass();
}
fields = fieldList.toArray(new Field[fieldList.size()]);
manyToOneFieldMap.put(clazz, fields);
}
return fields;
}
/**
* Process the Many to one fields of a class so their values are in the data
* base prior to attempting to place the objects in the data base.
*
* @param objects
* @param clazz
*/
private void processManytoOneFields(Collection<?> objects, Class<?> clazz,
PluginDao dao) {
Field[] fields = getManyToOneFields(clazz);
if (fields.length > 0) {
Map<Object, Object> foMap = new HashMap<Object, Object>();
for (Field field : fields) {
for (Object object : objects) {
try {
Object fieldObject = PropertyUtils.getProperty(object,
field.getName());
if (fieldObject != null) {
Object fo = foMap.get(fieldObject);
if (fo == null) {
foMap.put(fieldObject, fieldObject);
} else {
// Set to the instance being sent to the dao.
PropertyUtils.setProperty(object,
field.getName(), fo);
}
}
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
Collection<?> fieldObjects = foMap.values();
processManytoOneFields(fieldObjects, field.getType(), dao);
dao.persistAll(fieldObjects);
}
}
}
}

View file

@ -0,0 +1,112 @@
/**
* 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.edex.archive.feeder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import com.raytheon.uf.common.serialization.DynamicSerializationManager;
import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType;
import com.raytheon.uf.common.serialization.SerializationException;
/**
* This class uses the DynamicSerializationManager to create an instance of the
* first serialized object in a file.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 25, 2014 2838 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public class ArchiveBinaryReader {
/** File containing the serialized object. */
private File binFile;
/** Instance of the file's serialized object. */
Object object;
/**
* Constructor
*
* @param binFile
* - File containing serialized object.
*/
public ArchiveBinaryReader(File binFile) {
this.binFile = binFile;
}
/**
* The object obtained from the binFile.
*
* @return object
* @throws FileNotFoundException
* @throws SerializationException
*/
public Object getObject() throws FileNotFoundException,
SerializationException {
if (object == null) {
object = readObject();
}
return object;
}
/**
* Create an instance of the file's serialized object.
*
* @return object
* @throws FileNotFoundException
* @throws SerializationException
*/
private Object readObject() throws FileNotFoundException,
SerializationException {
InputStream inputStream = null;
Object object = null;
try {
DynamicSerializationManager dsm = DynamicSerializationManager
.getManager(SerializationType.Thrift);
inputStream = new BufferedInputStream(new FileInputStream(binFile));
object = dsm.deserialize(inputStream);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// Ignore
}
inputStream = null;
}
}
return object;
}
}