Try to use Java Serializable to improve loading of included

ComponentPresets.
This commit is contained in:
kruland2607 2012-10-08 16:37:02 -05:00
parent 78e3931c9e
commit 7f6c542e5d
13 changed files with 290 additions and 133 deletions

View File

@ -68,7 +68,7 @@
</target>
<!-- Executible Eclipse-Jar-In-Jar style JAR -->
<target name="jar" depends="core-jar" description="Create the OpenRocket jar-in-jar Executable">
<target name="jar" depends="core-jar,serialize-presets" description="Create the OpenRocket jar-in-jar Executable">
<mkdir dir="${jar.dir}" />
<jar destfile="${jar.file}">
<manifest>
@ -104,7 +104,13 @@
</jar>
</target>
<target name="serialize-presets" depends="core-jar" description="Preprocess the orc preset files into serialized form">
<java classname="net.sf.openrocket.startup.SerializePresets"
fork="true"
classpathref="run-classpath"
failonerror="true">
</java>
</target>
<!-- Core OpenRocket JAR -->
<target name="core-jar" depends="build" description="Create the OpenRocket code-only jar file">
<jar destfile="${build.dir}/${ant.project.name}-Core.jar" basedir="${dist.dir}">
@ -126,7 +132,7 @@
classpathref="run-classpath"
failonerror="true">
<arg value="@{dir}"/>
<arg value="resources/datafiles/presets/@{vendor}.orc"/>
<arg value="resources-src/datafiles/presets/@{vendor}.orc"/>
</java>
</sequential>
</macrodef>

Binary file not shown.

View File

@ -2,6 +2,11 @@ package net.sf.openrocket.preset;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
@ -10,6 +15,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.motor.Manufacturer;
@ -28,12 +34,12 @@ import net.sf.openrocket.util.TextUtil;
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class ComponentPreset implements Comparable<ComponentPreset> {
public class ComponentPreset implements Comparable<ComponentPreset>, Serializable {
private final TypedPropertyMap properties = new TypedPropertyMap();
private String digest = "";
public enum Type {
BODY_TUBE(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
@ -42,105 +48,105 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
NOSE_CONE(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.SHAPE,
ComponentPreset.AFT_OUTER_DIAMETER,
ComponentPreset.AFT_SHOULDER_DIAMETER,
ComponentPreset.AFT_SHOULDER_LENGTH,
ComponentPreset.LENGTH }),
TRANSITION(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.SHAPE,
ComponentPreset.FORE_OUTER_DIAMETER,
ComponentPreset.FORE_SHOULDER_DIAMETER,
ComponentPreset.FORE_SHOULDER_LENGTH,
ComponentPreset.AFT_OUTER_DIAMETER,
ComponentPreset.AFT_SHOULDER_DIAMETER,
ComponentPreset.AFT_SHOULDER_LENGTH,
ComponentPreset.LENGTH }),
TUBE_COUPLER(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.LENGTH }),
BULK_HEAD(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
CENTERING_RING(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
ENGINE_BLOCK(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
LAUNCH_LUG(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
STREAMER(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.LENGTH,
ComponentPreset.WIDTH,
ComponentPreset.THICKNESS,
ComponentPreset.MATERIAL }),
PARACHUTE(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.DIAMETER,
ComponentPreset.SIDES,
ComponentPreset.LINE_COUNT,
ComponentPreset.LINE_LENGTH,
ComponentPreset.LINE_MATERIAL,
ComponentPreset.MATERIAL });
NOSE_CONE(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.SHAPE,
ComponentPreset.AFT_OUTER_DIAMETER,
ComponentPreset.AFT_SHOULDER_DIAMETER,
ComponentPreset.AFT_SHOULDER_LENGTH,
ComponentPreset.LENGTH }),
TRANSITION(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.SHAPE,
ComponentPreset.FORE_OUTER_DIAMETER,
ComponentPreset.FORE_SHOULDER_DIAMETER,
ComponentPreset.FORE_SHOULDER_LENGTH,
ComponentPreset.AFT_OUTER_DIAMETER,
ComponentPreset.AFT_SHOULDER_DIAMETER,
ComponentPreset.AFT_SHOULDER_LENGTH,
ComponentPreset.LENGTH }),
TUBE_COUPLER(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.LENGTH }),
BULK_HEAD(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
CENTERING_RING(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
ENGINE_BLOCK(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
LAUNCH_LUG(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.LENGTH }),
STREAMER(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.LENGTH,
ComponentPreset.WIDTH,
ComponentPreset.THICKNESS,
ComponentPreset.MATERIAL }),
PARACHUTE(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.DIAMETER,
ComponentPreset.SIDES,
ComponentPreset.LINE_COUNT,
ComponentPreset.LINE_LENGTH,
ComponentPreset.LINE_MATERIAL,
ComponentPreset.MATERIAL });
TypedKey<?>[] displayedColumns;
Type(TypedKey<?>[] displayedColumns) {
this.displayedColumns = displayedColumns;
}
public List<Type> getCompatibleTypes() {
return compatibleTypeMap.get(Type.this);
}
public TypedKey<?>[] getDisplayedColumns() {
return displayedColumns;
}
private static Map<Type, List<Type>> compatibleTypeMap = new HashMap<Type, List<Type>>();
static {
compatibleTypeMap.put(BODY_TUBE, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG));
compatibleTypeMap.put(TUBE_COUPLER, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG));
@ -148,9 +154,9 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
compatibleTypeMap.put(CENTERING_RING, Arrays.asList(CENTERING_RING, ENGINE_BLOCK));
compatibleTypeMap.put(NOSE_CONE, Arrays.asList(NOSE_CONE, TRANSITION));
}
}
public final static TypedKey<Manufacturer> MANUFACTURER = new TypedKey<Manufacturer>("Manufacturer", Manufacturer.class);
public final static TypedKey<String> PARTNO = new TypedKey<String>("PartNo", String.class);
public final static TypedKey<String> DESCRIPTION = new TypedKey<String>("Description", String.class);
@ -177,7 +183,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
public final static TypedKey<Double> LINE_LENGTH = new TypedKey<Double>("LineLength", Double.class, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Material> LINE_MATERIAL = new TypedKey<Material>("LineMaterial", Material.class);
public final static TypedKey<byte[]> IMAGE = new TypedKey<byte[]>("Image", byte[].class);
public final static List<TypedKey<?>> ORDERED_KEY_LIST = Collections.unmodifiableList(Arrays.<TypedKey<?>> asList(
MANUFACTURER,
PARTNO,
@ -204,12 +210,12 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
FINISH,
MATERIAL
));
// package scope constructor to encourage use of factory.
ComponentPreset() {
}
/**
* Convenience method to retrieve the Type of this ComponentPreset.
*
@ -218,7 +224,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
public Type getType() {
return properties.get(TYPE);
}
/**
* Convenience method to retrieve the Manufacturer of this ComponentPreset.
* @return
@ -226,7 +232,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
public Manufacturer getManufacturer() {
return properties.get(MANUFACTURER);
}
/**
* Convenience method to retrieve the PartNo of this ComponentPreset.
* @return
@ -234,15 +240,15 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
public String getPartNo() {
return properties.get(PARTNO);
}
public String getDigest() {
return digest;
}
public boolean has(Object key) {
return properties.containsKey(key);
}
/**
* Package scope so the ComponentPresetFactory can call it.
* @param other
@ -253,7 +259,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
}
properties.putAll(other);
}
/**
* Package scope so the ComponentPresetFactory can call it.
* @param key
@ -262,7 +268,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
<T> void put(TypedKey<T> key, T value) {
properties.put(key, value);
}
public <T> T get(TypedKey<T> key) {
T value = properties.get(key);
if (value == null) {
@ -270,26 +276,26 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
}
return value;
}
@Override
public int compareTo(ComponentPreset p2) {
int manuCompare = this.getManufacturer().getSimpleName().compareTo(p2.getManufacturer().getSimpleName());
if (manuCompare != 0)
return manuCompare;
int partNoCompare = this.getPartNo().compareTo(p2.getPartNo());
return partNoCompare;
}
@Override
public String toString() {
return get(PARTNO);
}
public String preferenceKey() {
return String.valueOf(get(MANUFACTURER)) + "|" + String.valueOf(get(PARTNO));
}
@Override
public boolean equals(final Object o) {
if (this == o) {
@ -298,45 +304,45 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
if (o == null || getClass() != o.getClass()) {
return false;
}
ComponentPreset that = (ComponentPreset) o;
if (digest != null ? !digest.equals(that.digest) : that.digest != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
return digest != null ? digest.hashCode() : 0;
}
/**
* Package scope so the factory can call it.
*/
void computeDigest() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream(bos);
List<TypedKey<?>> keys = new ArrayList<TypedKey<?>>(properties.keySet());
Collections.sort(keys, new Comparator<TypedKey<?>>() {
@Override
public int compare(TypedKey<?> a, TypedKey<?> b) {
return a.getName().compareTo(b.getName());
}
});
for (TypedKey<?> key : keys) {
Object value = properties.get(key);
os.writeBytes(key.getName());
if (key.getType() == Double.class) {
Double d = (Double) value;
os.writeDouble(d);
@ -363,9 +369,9 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
int i = ((Shape) value).ordinal();
os.writeInt(i);
}
}
MessageDigest md5 = MessageDigest.getInstance("MD5");
digest = TextUtil.hexString(md5.digest(bos.toByteArray()));
} catch (Exception e) {
@ -373,5 +379,70 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
throw new BugException(e);
}
}
private static class MaterialDTO implements Serializable {
String name;
String type;
boolean userDefined;
Double density;
}
private void writeObject( ObjectOutputStream oos ) throws IOException {
Map<String,Object> DTO = new HashMap<String,Object>();
for ( Entry<TypedKey<?>, Object> entry :properties.entrySet() ) {
TypedKey<?> key = entry.getKey();
Object value = entry.getValue();
String keyName = key.getName();
if ( MANUFACTURER.getName().equals(keyName) ) {
value = ((Manufacturer) value).getDisplayName();
} else if ( value instanceof Material ) {
Material material = (Material) value;
MaterialDTO m = new MaterialDTO();
m.name = material.getName();
m.type = material.getType().name();
m.density = material.getDensity();
m.userDefined = material.isUserDefined();
value = m;
}
DTO.put(keyName,value);
}
oos.writeObject(DTO);
}
private void readObject( ObjectInputStream ois ) throws IOException, ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Map<String,Object> DTO = (Map<String,Object>) ois.readObject();
Field propField = ComponentPreset.class.getDeclaredField("properties");
propField.setAccessible(true);
propField.set(this, new TypedPropertyMap());
for ( Entry<String,Object> entry : DTO.entrySet() ) {
String keyName = entry.getKey();
Object value = entry.getValue();
if ( MANUFACTURER.getName().equals(keyName)) {
value = Manufacturer.getManufacturer((String) value);
} else if ( value instanceof MaterialDTO ) {
MaterialDTO m = (MaterialDTO) value;
value = Material.newMaterial(Material.Type.valueOf(m.type), m.name, m.density, m.userDefined);
}
if ( TYPE.getName().equals(keyName)) {
this.properties.put(TYPE, (ComponentPreset.Type) value);
} else {
for( TypedKey k : ORDERED_KEY_LIST ) {
if ( k.getName().equals(keyName)) {
this.properties.put( k, value );
break;
}
}
}
}
this.computeDigest();
}
}

View File

@ -2,7 +2,9 @@ package net.sf.openrocket.startup;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -17,6 +19,7 @@ import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.xml.OpenRocketComponentLoader;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Pair;
public class ConcurrentComponentPresetDatabaseLoader {
@ -90,19 +93,26 @@ public class ConcurrentComponentPresetDatabaseLoader {
// Start loading
log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
SimpleFileFilter orcFilter = new SimpleFileFilter("", false, "orc");
iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR, orcFilter);
iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR, new SimpleFileFilter("",false,"ser"));
if (iterator != null) {
while( iterator.hasNext() ) {
Pair<String,InputStream> f = iterator.next();
FileLoader loader = new FileLoader( f.getV(), f.getU() );
loaderPool.execute(loader);
fileCount ++;
try {
ObjectInputStream ois = new ObjectInputStream(f.getV());
List<ComponentPreset> list = (List<ComponentPreset>) ois.readObject();
componentPresetDao.addAll(list);
fileCount++;
presetCount+=list.size();
}
catch ( Exception ex ) {
throw new BugException(ex);
}
}
}
try {
SimpleFileFilter orcFilter = new SimpleFileFilter("", false, "orc");
iterator = new DirectoryIterator(
((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory(),
orcFilter,

View File

@ -0,0 +1,70 @@
package net.sf.openrocket.startup;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.List;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.file.iterator.DirectoryIterator;
import net.sf.openrocket.file.iterator.FileIterator;
import net.sf.openrocket.gui.util.SimpleFileFilter;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.xml.OpenRocketComponentLoader;
import net.sf.openrocket.util.Pair;
public class SerializePresets {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
Application.setPreferences( new SwingPreferences() );
ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase() {
@Override
protected void load() {
FileIterator iterator = DirectoryIterator.findDirectory("resources-src/datafiles/presets", new SimpleFileFilter("",false,"orc"));
if ( iterator == null ) {
throw new RuntimeException("Can't find resources-src/presets directory");
}
while( iterator.hasNext() ) {
Pair<String,InputStream> f = iterator.next();
String fileName = f.getU();
InputStream is = f.getV();
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
Collection<ComponentPreset> presets = loader.load(is, fileName);
this.addAll(presets);
}
}
};
componentPresetDao.startLoading();
List<ComponentPreset> list = componentPresetDao.listAll();
Application.getLogger().info("Total number of presets = " + list.size());
File outFile = new File("resources/datafiles/presets","system.ser");
FileOutputStream ofs = new FileOutputStream(outFile);
ObjectOutputStream oos = new ObjectOutputStream(ofs);
oos.writeObject(list);
ofs.flush();
ofs.close();
}
}