@@ -31,115 +31,109 @@ def setDatabase(connectionString):
3131 jneqsim .util .database .NeqSimDataBase .setCreateTemporaryTables (True )
3232
3333
34- def save_neqsim (javaobject , filename ):
35- """
36- Serialize a Java object (such as a NEQSim ProcessSystem) to XML
37- using XStream, then compress and save it as a .gz file.
38-
39- Args:
40- javaobject: A Java object that XStream can serialize (e.g., neqsim.process.processmodel.ProcessSystem).
41- filename (str): The path (including filename) to write the compressed XML file.
42- For clarity, you can use a .xml.gz extension, for example "myProcess.xml.gz".
43-
44- Returns:
45- bool: True if the file is successfully written.
46-
47- Raises:
48- Any exception raised by XStream serialization, file I/O, or gzip operations
49- will propagate unless caught by the caller.
50-
51- Usage Example:
52- # 1. Ensure JPype has started the JVM and XStream is on the classpath:
53- # if not jpype.isJVMStarted():
54- # jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", f"-Djava.class.path=path/to/xstream.jar")
55-
56- # 2. Acquire or build the NEQSim process object (javaobject).
57- # process = ... # your neqsim.process.processmodel.ProcessSystem
58-
59- # 3. Call save_neqsim:
60- # save_neqsim(process, "myProcess.xml.gz")
61- """
62- # Instantiate XStream from the Java packages
63- xstream = jpype .JPackage ("com.thoughtworks.xstream" ).XStream ()
64-
65- # Convert the Java object to an XML string (java.lang.String)
66- xml_java_string = xstream .toXML (javaobject )
67-
68- # Convert java.lang.String to a native Python string
69- xml_python_string = str (xml_java_string )
70-
71- # Compress and save the string as UTF-8 bytes in a .gz file
72- with gzip .open (filename , "wb" ) as f :
73- f .write (xml_python_string .encode ("utf-8" ))
74-
75- return True
76-
77-
7834def open_neqsim (filename , allow_all = True , wildcard_permission = None ):
7935 """
80- Decompress and deserialize a Java object (e.g., a NEQSim ProcessSystem)
81- from a gzipped XStream XML file.
36+ Open and deserialize a NEQSim Java object from either a .gz or .zip XStream-serialized XML file.
8237
83- Args:
84- filename (str): Path to the gzipped file (e.g. 'process.neqsim').
85- allow_all (bool): If True, uses AnyTypePermission to allow all classes
86- during deserialization. This is simple but not recommended for
87- production security.
88- wildcard_permission (list of str, optional):
89- A list of wildcard patterns for XStream to allow. For example,
90- ['neqsim.**'] would allow classes under 'neqsim'.
38+ Supports:
39+ - GZipped XML: .xml.gz
40+ - Zipped XML: .zip (must contain a file named 'process.xml')
9141
9242 Returns:
93- object: The deserialized Java object (e.g., a NEQSim ProcessSystem),
94- or None if an error occurs.
95-
96- Raises:
97- Any exceptions raised by file I/O, gzip, XStream, or JPype will
98- propagate unless caught by the caller.
99-
100- Usage Example:
101- # Ensure the JVM is started and the XStream JAR is on the classpath.
102- # jpype.startJVM(..., classpath=[...])
103-
104- # open_neqsim("myProcess.neqsim", allow_all=True)
43+ object: The deserialized Java object.
10544 """
106- # 1. Create an XStream instance
107- xstream_cls = jpype .JPackage ("com.thoughtworks.xstream" ).XStream
108- xstream = xstream_cls ()
45+ import os
46+
47+ # Instantiate XStream
48+ XStream = jpype .JClass ("com.thoughtworks.xstream.XStream" )
49+ xstream = XStream ()
10950
110- # 2. Configure security permissions
51+ # Configure security
11152 security_pkg = jpype .JPackage ("com.thoughtworks.xstream.security" )
11253 if allow_all :
113- # Allow everything (not recommended in production)
114- anyTypePermission_cls = security_pkg .AnyTypePermission
115- xstream .addPermission (anyTypePermission_cls .ANY )
54+ xstream .addPermission (security_pkg .AnyTypePermission .ANY )
11655 elif wildcard_permission is not None :
117- # e.g. wildcard_permission = ["neqsim.**"]
118- wildcard_cls = security_pkg .WildcardTypePermission
119- xstream .addPermission (wildcard_cls (wildcard_permission ))
120- else :
121- # By default, XStream might reject many classes.
122- # The user can add more specific permissions here.
123- pass
124-
125- # 3. Read and decompress the file
56+ xstream .addPermission (security_pkg .WildcardTypePermission (wildcard_permission ))
57+
58+ # Detect file format by extension
59+ ext = os .path .splitext (filename )[- 1 ].lower ()
60+
12661 try :
127- with gzip .open (filename , "rb" ) as f :
128- xml_bytes = f .read ()
129- xml_str = xml_bytes .decode ("utf-8" )
62+ if ext == ".gz" :
63+ with gzip .open (filename , "rb" ) as f :
64+ xml_bytes = f .read ()
65+ elif ext == ".zip" :
66+ import zipfile
67+ with zipfile .ZipFile (filename , 'r' ) as zf :
68+ with zf .open ('process.xml' ) as f :
69+ xml_bytes = f .read ()
70+ else :
71+ raise ValueError (f"Unsupported file extension: { ext } " )
13072 except Exception as e :
131- print (f"[open_neqsim] Failed to read/decompress file: { e } " )
73+ print (f"[open_neqsim] Failed to read/compress/ decompress file: { e } " )
13274 return None
13375
134- # 4. Deserialize using XStream
76+ # Deserialize
13577 try :
78+ xml_str = xml_bytes .decode ("utf-8" )
13679 java_object = xstream .fromXML (xml_str )
13780 return java_object
13881 except Exception as e :
13982 print (f"[open_neqsim] Failed to deserialize object: { e } " )
14083 return None
14184
14285
86+ def save_neqsim (javaobject , filename ):
87+ """
88+ Serialize a Java object (e.g., NEQSim ProcessSystem) to XML using XStream,
89+ and save it as a compressed ZIP file containing one XML file.
90+
91+ Args:
92+ javaobject: A Java object that XStream can serialize.
93+ filename (str): The path to the ZIP file to write (e.g., "myProcess.zip").
94+
95+ Returns:
96+ bool: True if the file is successfully written, False otherwise.
97+ """
98+ if not jpype .isJVMStarted ():
99+ raise RuntimeError ("JVM is not started. Please start the JVM with the correct classpath." )
100+
101+ try :
102+ # Java imports
103+ XStream = jpype .JClass ("com.thoughtworks.xstream.XStream" )
104+ FileOutputStream = jpype .JClass ("java.io.FileOutputStream" )
105+ BufferedOutputStream = jpype .JClass ("java.io.BufferedOutputStream" )
106+ ZipOutputStream = jpype .JClass ("java.util.zip.ZipOutputStream" )
107+ ZipEntry = jpype .JClass ("java.util.zip.ZipEntry" )
108+ OutputStreamWriter = jpype .JClass ("java.io.OutputStreamWriter" )
109+ File = jpype .JClass ("java.io.File" )
110+
111+ # Create XStream instance and configure security
112+ xstream = XStream ()
113+ xstream .allowTypesByWildcard (["neqsim.**" ])
114+
115+ # Setup output stream and ZIP structure
116+ file = File (filename )
117+ fout = BufferedOutputStream (FileOutputStream (file ))
118+ zout = ZipOutputStream (fout )
119+
120+ # Use a fixed name for the XML inside the ZIP
121+ entry = ZipEntry ("process.xml" )
122+ zout .putNextEntry (entry )
123+
124+ writer = OutputStreamWriter (zout , "UTF-8" )
125+ xstream .toXML (javaobject , writer )
126+ writer .flush ()
127+ zout .closeEntry ()
128+ writer .close ()
129+ zout .close ()
130+
131+ return True
132+ except Exception as e :
133+ print (f"Error saving NEQSim object to ZIP: { e } " )
134+ return False
135+
136+
143137def save_xml (javaobject , filename ):
144138 xstream = jpype .JPackage ("com.thoughtworks.xstream" )
145139 streamer = xstream .XStream ()
0 commit comments