svn commit: r12780 - trunk/src_new/org/argouml/persistence

[email protected]
Newsgroups gmane.comp.lang.uml.argouml.cvs
Message-ID <[email protected]>
Author: tfmorris
Date: 2007-06-08 00:50:15-0700
New Revision: 12780

Modified:
   trunk/src_new/org/argouml/persistence/DiagramMemberFilePersister.java
   trunk/src_new/org/argouml/persistence/MemberFilePersister.java
   trunk/src_new/org/argouml/persistence/ModelMemberFilePersister.java
   trunk/src_new/org/argouml/persistence/OldZargoFilePersister.java
   trunk/src_new/org/argouml/persistence/TodoListMemberFilePersister.java
   trunk/src_new/org/argouml/persistence/UmlFilePersister.java
   trunk/src_new/org/argouml/persistence/XmiFilePersister.java
   trunk/src_new/org/argouml/persistence/XmlInputStream.java
   trunk/src_new/org/argouml/persistence/ZipFilePersister.java

Log:
Issue 4777 - Refactor XMI writer

Modified: trunk/src_new/org/argouml/persistence/DiagramMemberFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/DiagramMemberFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/DiagramMemberFilePersister.java&p2=trunk/src_new/org/argouml/persistence/DiagramMemberFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/DiagramMemberFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/DiagramMemberFilePersister.java	2007-06-08 00:50:15-0700
@@ -28,6 +28,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.Writer;
 
@@ -49,10 +50,7 @@
      */
     private static final String PGML_TEE = "/org/argouml/persistence/PGML.tee";
 
-    /*
-     * @see org.argouml.persistence.MemberFilePersister#load(org.argouml.kernel.Project,
-     *      java.io.InputStream)
-     */
+    @Override
     public void load(Project project, InputStream inputStream)
         throws OpenException {
 
@@ -75,20 +73,15 @@
         }
     }
 
-    /*
-     * @see org.argouml.persistence.MemberFilePersister#getMainTag()
-     */
+
+    @Override
     public String getMainTag() {
         return "pgml";
     }
 
-    /**
-     * Write the diagram to the given writer.
-     *
-     * @see org.argouml.persistence.MemberFilePersister#save(
-     *         org.argouml.kernel.ProjectMember, java.io.Writer,
-     *         java.lang.Integer)
-     */
+
+    @Override
+    @Deprecated
     public void save(ProjectMember member, Writer writer, boolean xmlFragment)
     	throws SaveException {
 
@@ -121,4 +114,30 @@
             }
         }
     }
+    
+
+    @Override
+    public void save(ProjectMember member, OutputStream outStream)
+        throws SaveException {
+
+        ProjectMemberDiagram diagramMember = (ProjectMemberDiagram) member;
+        OCLExpander expander;
+        try {
+            expander =
+                    new OCLExpander(
+                            TemplateReader.getInstance().read(PGML_TEE));
+        } catch (ExpansionException e) {
+            throw new SaveException(e);
+        }
+        PrintWriter pw = new PrintWriter(outStream);
+        try {
+            // WARNING: the OutputStream version of this doesn't work! - tfm
+            expander.expand(pw, diagramMember.getDiagram());
+        } catch (ExpansionException e) {
+            throw new SaveException(e);
+        } finally {
+            pw.flush();
+        }
+        
+    }
 }

Modified: trunk/src_new/org/argouml/persistence/MemberFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/MemberFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/MemberFilePersister.java&p2=trunk/src_new/org/argouml/persistence/MemberFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/MemberFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/MemberFilePersister.java	2007-06-08 00:50:15-0700
@@ -31,6 +31,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.Writer;
 
@@ -67,6 +68,7 @@
      * @param member The project member to save.
      * @param writer The Writer to which to save the XML.
      * @throws SaveException if the save fails
+     * @deprecated for 0.25.4 by tfmorris.
      */
     public void save(
             ProjectMember member,
@@ -75,19 +77,37 @@
     }
 
     /**
-     * Save the projectmember as XML to the given writer.
+     * Save the project member as XML to the given output stream.
+     * 
+     * @param member
+     *            The project member to save.
+     * @param stream
+     *            The OutputStream to write the contents to.
+     * @throws SaveException
+     *             if the save fails
+     * @since 0.25.4
+     */
+    public abstract void save(
+            ProjectMember member,
+            OutputStream stream) throws SaveException;
+    
+    /**
+     * Save the project member as XML to the given writer.
      *
      * @param member The project member to save.
      * @param writer The Writer to which to save the XML.
      * @param xmlFragment true if the XML saved is a fragment os some other
      *     XML file (ie part of .uml)
      * @throws SaveException if the save fails
+     * @deprecated for 0.25.4 by tfmorris. Use 
+     * {@link #save(ProjectMember, OutputStream, boolean)}.
      */
     public abstract void save(
             ProjectMember member,
             Writer writer,
             boolean xmlFragment) throws SaveException;
 
+    
     /**
      * Send an existing file of XML to the PrintWriter.
      * @param writer the PrintWriter.
@@ -122,4 +142,5 @@
             throw new SaveException(e);
         }
     }
+
 }

Modified: trunk/src_new/org/argouml/persistence/ModelMemberFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/ModelMemberFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/ModelMemberFilePersister.java&p2=trunk/src_new/org/argouml/persistence/ModelMemberFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/ModelMemberFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/ModelMemberFilePersister.java	2007-06-08 00:50:15-0700
@@ -24,12 +24,11 @@
 
 package org.argouml.persistence;
 
-import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStreamWriter;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.Writer;
 import java.net.URL;
@@ -123,7 +122,12 @@
      * @see org.argouml.persistence.MemberFilePersister#getMainTag()
      */
     public String getMainTag() {
-        return "XMI";
+        try {
+            return Model.getXmiReader().getTagName();
+        } catch (UmlException e) {
+            // Should never happen - something's really wrong
+            throw new RuntimeException(e);
+        }
     }
 
     /**
@@ -151,12 +155,9 @@
                 File tempFile = File.createTempFile("xmi", null);
                 tempFile.deleteOnExit();
 
-                Writer writer =
-                    new BufferedWriter(
-                        new OutputStreamWriter(
-                                new FileOutputStream(tempFile), "UTF-8"));
+                OutputStream stream = new FileOutputStream(tempFile);
                 XmiWriter xmiWriter = 
-                    Model.getXmiWriter(model, writer, 
+                    Model.getXmiWriter(model, stream, 
                             ApplicationVersion.getVersion() + "(" 
                             + UmlFilePersister.PERSISTENCE_VERSION + ")");
                 
@@ -179,6 +180,33 @@
     }
     
     /**
+     * Save the project model to XMI.
+     * 
+     * @see org.argouml.persistence.MemberFilePersister#save(org.argouml.kernel.ProjectMember, java.io.OutputStream, boolean)
+     */
+    public void save(ProjectMember member, OutputStream outStream)
+        throws SaveException {
+
+        ProjectMemberModel pmm = (ProjectMemberModel) member;
+        Object model = pmm.getModel();
+
+        try {
+            XmiWriter xmiWriter = 
+                Model.getXmiWriter(model, outStream, 
+                        ApplicationVersion.getVersion() + "(" 
+                        + UmlFilePersister.PERSISTENCE_VERSION + ")");
+
+            xmiWriter.write();
+            outStream.flush();
+        } catch (UmlException e) {
+            throw new SaveException(e);
+        } catch (IOException e) {
+            throw new SaveException(e);
+        }
+
+    }
+    
+    /**
      * Get a MemberFilePersister based on a given ProjectMember.
      *
      * @param pm the project member

Modified: trunk/src_new/org/argouml/persistence/OldZargoFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/OldZargoFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/OldZargoFilePersister.java&p2=trunk/src_new/org/argouml/persistence/OldZargoFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/OldZargoFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/OldZargoFilePersister.java	2007-06-08 00:50:15-0700
@@ -168,8 +168,8 @@
                     stream.putNextEntry(new ZipEntry(name));
                     MemberFilePersister persister =
                         getMemberFilePersister(projectMember);
-                    persister.save(projectMember, writer, false);
-                    writer.flush();
+                    persister.save(projectMember, stream);
+                    stream.flush();
                     stream.closeEntry();
                 }
             }
@@ -187,7 +187,8 @@
                             new ZipEntry(projectMember.getZipName()));
                     OldModelMemberFilePersister persister =
                         new OldModelMemberFilePersister();
-                    persister.save(projectMember, writer, false);
+                    persister.save(projectMember, stream);
+                    stream.flush();
                 }
             }
             

Modified: trunk/src_new/org/argouml/persistence/TodoListMemberFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/TodoListMemberFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/TodoListMemberFilePersister.java&p2=trunk/src_new/org/argouml/persistence/TodoListMemberFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/TodoListMemberFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/TodoListMemberFilePersister.java	2007-06-08 00:50:15-0700
@@ -29,6 +29,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.Writer;
@@ -81,14 +82,8 @@
         return "todo";
     }
 
-    /**
-     *
-     * Throws InvalidArgumentException if no writer specified.
-     *
-     * @see org.argouml.persistence.MemberFilePersister#save(
-     *         org.argouml.kernel.ProjectMember, java.io.Writer,
-     *         boolean)
-     */
+
+    @Deprecated
     public void save(ProjectMember member, Writer writer, boolean xmlFragment)
     	throws SaveException {
 
@@ -133,4 +128,33 @@
 
         LOG.debug("Done saving TO DO LIST!!!");
     }
+    
+    public void save(ProjectMember member, OutputStream outStream)
+        throws SaveException {
+
+        OCLExpander expander;
+        try {
+            expander =
+                    new OCLExpander(TemplateReader.getInstance()
+                            .read(TO_DO_TEE));
+        } catch (ExpansionException e) {
+            throw new SaveException(e);
+        }
+
+        PrintWriter pw = new PrintWriter(outStream);
+        try {
+            Designer.disableCritiquing();
+            // WARNING: The GEF implementation of the OutputStream version of this
+            // method doesn't work - tfm - 20070531
+            expander.expand(pw, member);
+        } catch (ExpansionException e) {
+            throw new SaveException(e);
+        } finally {
+            pw.flush();
+//            pw.close();
+            Designer.enableCritiquing();
+        }
+
+    }
+
 }

Modified: trunk/src_new/org/argouml/persistence/UmlFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/UmlFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/UmlFilePersister.java&p2=trunk/src_new/org/argouml/persistence/UmlFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/UmlFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/UmlFilePersister.java	2007-06-08 00:50:15-0700
@@ -29,6 +29,7 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
@@ -38,8 +39,16 @@
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
 import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.xml.transform.Result;
 import javax.xml.transform.Transformer;
@@ -54,6 +63,7 @@
 import org.argouml.i18n.Translator;
 import org.argouml.kernel.Project;
 import org.argouml.kernel.ProjectMember;
+import org.argouml.model.UmlException;
 import org.argouml.uml.ProjectMemberModel;
 import org.argouml.uml.cognitive.ProjectMemberTodoList;
 import org.argouml.uml.diagram.ProjectMemberDiagram;
@@ -63,6 +73,7 @@
 import org.tigris.gef.ocl.TemplateReader;
 import org.xml.sax.SAXException;
 
+
 /**
  * To persist to and from argo (xml file) storage.
  *
@@ -151,8 +162,7 @@
             project.setVersion(ApplicationVersion.getVersion());
             project.setPersistenceVersion(PERSISTENCE_VERSION);
 
-            FileOutputStream stream =
-                new FileOutputStream(file);
+            OutputStream stream = new FileOutputStream(file);
 
             writeProject(project, stream, progressMgr);
 
@@ -215,18 +225,21 @@
      * @throws InterruptedException     if the thread is interrupted
      */
     void writeProject(Project project, 
-            OutputStream stream, 
+            OutputStream oStream, 
             ProgressMgr progressMgr) throws SaveException, 
             InterruptedException {
         OutputStreamWriter outputStreamWriter;
         try {
-            outputStreamWriter = new OutputStreamWriter(stream, "UTF-8");
+            outputStreamWriter =
+                    new OutputStreamWriter(oStream, Argo.getEncoding());
         } catch (UnsupportedEncodingException e) {
             throw new SaveException(e);
         }
         PrintWriter writer =
             new PrintWriter(new BufferedWriter(outputStreamWriter));
 
+        XmlFilterOutputStream filteredStream =
+                new XmlFilterOutputStream(oStream, Argo.getEncoding());
         try {
             writer.println("<?xml version = \"1.0\" "
                     + "encoding = \"" 
@@ -241,6 +254,7 @@
             } catch (ExpansionException e) {
                 throw new SaveException(e);
             }
+            writer.flush();
 
             // Write out XMI section first
             int size = project.getMembers().size();
@@ -255,7 +269,13 @@
                     }
                     MemberFilePersister persister
                         = getMemberFilePersister(projectMember);
-                    persister.save(projectMember, writer, true);
+                    filteredStream.startEntry();
+                    persister.save(projectMember, filteredStream);
+                    try {
+                        filteredStream.flush();
+                    } catch (IOException e) {
+                        throw new SaveException(e);
+                    }
                 }
             }
 
@@ -275,7 +295,13 @@
                     }
                     MemberFilePersister persister
                         = getMemberFilePersister(projectMember);
-                    persister.save(projectMember, writer, true);
+                    filteredStream.startEntry();
+                    persister.save(projectMember, filteredStream);
+                    try {
+                        filteredStream.flush();
+                    } catch (IOException e) {
+                        throw new SaveException(e);
+                    }
                 }
             }
 
@@ -284,6 +310,11 @@
             writer.flush();
         } finally {
             writer.close();
+            try {
+                filteredStream.reallyClose();
+            } catch (IOException e) {
+                throw new SaveException(e);
+            }
         }
     }
 
@@ -369,7 +400,20 @@
                 LOG.info("Loading member with "
                         + persister.getClass().getName());
                 inputStream.reopen(persister.getMainTag());
-                persister.load(p, inputStream);
+                try {
+                    persister.load(p, inputStream);
+                } catch (OpenException e) {
+                    // UML 2.x files don't have XMI as their outer
+                    // tag.  Try again with uml:Model
+                    if ("XMI".equals(persister.getMainTag()) 
+                            && e.getCause() instanceof UmlException 
+                            && e.getCause().getCause() instanceof IOException) {
+                        inputStream.reopen("uml:Model");
+                        persister.load(p, inputStream);
+                    } else {
+                        throw e;
+                    }
+                }
             }
             
             // let's update the progress
@@ -598,4 +642,152 @@
     public boolean hasAnIcon() {
         return true;
     }
+    
+    /**
+     * Class to filter XML declaration and DOCTYPE declaration from
+     * an output stream to allow use as nested XML files.
+     * 
+     * @author Tom Morris
+     */
+    class XmlFilterOutputStream extends FilterOutputStream {
+
+        private CharsetDecoder decoder;
+
+        private boolean headerProcessed = false;
+
+        private static final int BUFFER_SIZE = 120;
+        
+        private byte[] bytes = new byte[BUFFER_SIZE * 2];
+        private ByteBuffer outBB = ByteBuffer.wrap(bytes);
+        // An input view of the same bytes that we can read from
+        private ByteBuffer inBB = ByteBuffer.wrap(bytes);
+
+        private CharBuffer outCB = CharBuffer.allocate(BUFFER_SIZE);
+        
+        // Backslashes are doubled up - one for Java, one for Regex
+        private final Pattern pattern = Pattern.compile(
+                "\\s*<\\?xml.*\\?>\\s*(<!DOCTYPE.*>\\s*)?");
+
+        public XmlFilterOutputStream(OutputStream outputStream,
+                String charsetName) {
+            this(outputStream, Charset.forName(charsetName));
+        }
+
+        public XmlFilterOutputStream(OutputStream outputStream, 
+                Charset charset) {
+            super(outputStream);
+            decoder = charset.newDecoder();
+            decoder.onMalformedInput(CodingErrorAction.REPORT);
+            decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+            startEntry();
+        }  
+        
+        public void startEntry() {
+            headerProcessed = false;
+            resetBuffers();
+        }
+
+        private void resetBuffers() {
+            inBB.limit(0);
+            outBB.position(0);
+            outCB.position(0);
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
+                throw new IndexOutOfBoundsException();
+
+            if (headerProcessed) {
+                out.write(b, off, len);
+            } else {
+                // TODO: Make this more efficient for large I/Os
+                for (int i = 0; i < len; i++) {
+                    write(b[off + i]);
+                }                
+            }
+
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+
+            if (headerProcessed) {
+                out.write(b);
+            } else {
+                outBB.put((byte) b);
+                inBB.limit(outBB.position());
+                // Convert from bytes back to characters
+                CoderResult result = decoder.decode(inBB, outCB, false);
+                if (result.isError()) {
+                    throw new RuntimeException(
+                            "Unknown character decoding error");
+                }
+                // This will have problems if the smallest possible
+                // data segment is smaller than the size of the buffer
+                // needed for regex matching
+
+                if (outCB.position() == outCB.limit()) {
+                    processHeader();
+                }
+
+            }
+        }
+
+        private void processHeader() throws IOException {
+            headerProcessed = true;
+            outCB.position(0); // rewind our character buffer
+            
+            Matcher matcher = pattern.matcher(outCB);
+            String headerString = matcher.replaceAll("");
+            
+            ByteBuffer bb = decoder.charset().encode(headerString);
+            
+            byte[] outBytes = new byte[bb.limit()];
+            bb.get(outBytes);
+            out.write(outBytes, 0, outBytes.length);
+
+            // Write any left over bytes from a partial character
+            if (inBB.remaining() > 0) {
+                out.write(inBB.array(), inBB.position(), 
+                        inBB.remaining());
+                inBB.position(0);
+                inBB.limit(0);
+            }
+        }
+
+
+        /**
+         * This method has no effect to keep sub-writers from closing it
+         * accidently. The master can use the method {@link #reallyClose()} to
+         * actually close the underlying stream.
+         */
+        @Override
+        public void close() throws IOException {
+            flush();
+        }
+        
+        /**
+         * Close the stream.
+         * 
+         * @throws IOException
+         */
+        public void reallyClose() throws IOException {
+            out.close();
+        }
+
+        /**
+         * Flush the stream.  This will throw an IllegalStateException if the
+         * stream is flushed before the header is completely processed.
+         */
+        @Override
+        public void flush() throws IOException {
+            if (!headerProcessed) {
+                throw new IllegalStateException(
+                        "Attempted flush while still processing header");
+            }
+            out.flush();
+        }
+        
+    }
 }

Modified: trunk/src_new/org/argouml/persistence/XmiFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/XmiFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/XmiFilePersister.java&p2=trunk/src_new/org/argouml/persistence/XmiFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/XmiFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/XmiFilePersister.java	2007-06-08 00:50:15-0700
@@ -177,40 +177,26 @@
             OutputStream stream, 
             ProgressMgr progressMgr) throws SaveException, 
             InterruptedException {
-        OutputStreamWriter outputStreamWriter;
-        try {
-            outputStreamWriter = new OutputStreamWriter(stream, "UTF-8");
-        } catch (UnsupportedEncodingException e) {
-            throw new SaveException(e);
-        }
-        PrintWriter writer =
-            new PrintWriter(new BufferedWriter(outputStreamWriter));
 
-        try {
-            int size = project.getMembers().size();
-            for (int i = 0; i < size; i++) {
-                ProjectMember projectMember =
-                    (ProjectMember) project.getMembers().get(i);
-                if (projectMember.getType().equalsIgnoreCase(getExtension())) {
-                    if (LOG.isInfoEnabled()) {
-                        LOG.info("Saving member of type: "
-                              + ((ProjectMember) project.getMembers()
+        int size = project.getMembers().size();
+        for (int i = 0; i < size; i++) {
+            ProjectMember projectMember =
+                (ProjectMember) project.getMembers().get(i);
+            if (projectMember.getType().equalsIgnoreCase(getExtension())) {
+                if (LOG.isInfoEnabled()) {
+                    LOG.info("Saving member of type: "
+                            + ((ProjectMember) project.getMembers()
                                     .get(i)).getType());
-                    }
-                    MemberFilePersister persister
-                        = new ModelMemberFilePersister();
-                    persister.save(projectMember, writer);
                 }
+                MemberFilePersister persister = new ModelMemberFilePersister();
+                persister.save(projectMember, stream);
             }
-            
-            if (progressMgr != null) {
-                progressMgr.nextPhase();
-            }
+        }
 
-            writer.flush();
-        } finally {
-            writer.close();
+        if (progressMgr != null) {
+            progressMgr.nextPhase();
         }
+
     }
 
 

Modified: trunk/src_new/org/argouml/persistence/XmlInputStream.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/XmlInputStream.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/XmlInputStream.java&p2=trunk/src_new/org/argouml/persistence/XmlInputStream.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/XmlInputStream.java	(original)
+++ trunk/src_new/org/argouml/persistence/XmlInputStream.java	2007-06-08 00:50:15-0700
@@ -43,6 +43,11 @@
  * to the matching end tag or it can search for the first
  * occurence of a named tag and read on the child tags.
  * The tag is not expected to be an empty tag.
+ * 
+ * TODO: This is hardwired to assume a fixed single byte
+ * character encoding.  It probably needs to be updated to
+ * handle multi-byte encodings. - tfm 20070607
+ * 
  * @author Bob Tarling
  */
 class XmlInputStream extends BufferedInputStream {
@@ -134,7 +139,7 @@
         if (endStream) {
             return -1;
         }
-        int ch = superRead();
+        int ch = super.read();
         endStream = isLastTag(ch);
         return ch;
     }
@@ -185,7 +190,14 @@
             currentTag.setLength(0);
         } else if (ch == '>') {
             inTag = false;
-            if (currentTag.toString().equals(endTagName)) {
+            String tag = currentTag.toString();
+            if (tag.equals(endTagName)
+                    // TODO: The below is not strictly correct, but should
+                    // cover the case we deal with.  Using a real XML parser
+                    // would be better.
+                    // Look for XML document has just a single root element
+                    || (currentTag.charAt(currentTag.length() - 1) == '/' && tag
+                            .startsWith(tagName))) {
                 return true;
             }
         } else if (inTag) {
@@ -219,7 +231,8 @@
             // Compare each following character to see
             // that it matches the tag we want
             for (i = 0; i < tagName.length(); ++i) {
-                if (realRead() != searchChars[i]) {
+                int c = realRead();
+                if (c != searchChars[i]) {
                     found = false;
                     break;
                 }
@@ -359,14 +372,11 @@
     }
 
     private int realRead() throws IOException {
-        int read = superRead();
+        int read = super.read();
         if (read == -1) {
             throw new IOException("Tag " + tagName + " not found");
         }
         return read;
     }
 
-    private int superRead() throws IOException {
-        return super.read();
-    }
 }

Modified: trunk/src_new/org/argouml/persistence/ZipFilePersister.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src_new/org/argouml/persistence/ZipFilePersister.java?view=diff&rev=12780&p1=trunk/src_new/org/argouml/persistence/ZipFilePersister.java&p2=trunk/src_new/org/argouml/persistence/ZipFilePersister.java&r1=12779&r2=12780
==============================================================================
--- trunk/src_new/org/argouml/persistence/ZipFilePersister.java	(original)
+++ trunk/src_new/org/argouml/persistence/ZipFilePersister.java	2007-06-08 00:50:15-0700
@@ -31,14 +31,12 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.OutputStreamWriter;
 import java.net.URL;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
 import org.apache.log4j.Logger;
-import org.argouml.application.api.Argo;
 import org.argouml.i18n.Translator;
 import org.argouml.kernel.Project;
 import org.argouml.kernel.ProjectManager;
@@ -120,7 +118,7 @@
                     "Failed to archive the previous file version", e);
         }
 
-        OutputStreamWriter writer = null;
+        OutputStream bufferedStream = null;
         try {
             //project.setFile(file);
 
@@ -130,9 +128,7 @@
             ZipEntry xmiEntry =
                 new ZipEntry(fileName.substring(0, fileName.lastIndexOf(".")));
             stream.putNextEntry(xmiEntry);
-            OutputStream bout = new BufferedOutputStream(stream);
-            writer = new OutputStreamWriter(bout, 
-                    Argo.getEncoding());
+            bufferedStream = new BufferedOutputStream(stream);
 
             int size = project.getMembers().size();
             for (int i = 0; i < size; i++) {
@@ -146,7 +142,7 @@
                     }
                     MemberFilePersister persister
                         = new ModelMemberFilePersister();
-                    persister.save(projectMember, writer, false);
+                    persister.save(projectMember, bufferedStream);
                 }
             }
             stream.close();
@@ -165,8 +161,10 @@
         } catch (Exception e) {
             LOG.error("Exception occured during save attempt", e);
             try {
-                writer.close();
-            } catch (IOException ex) { }
+                bufferedStream.close();
+            } catch (IOException ex) {
+                // If we get a 2nd error, just ignore it
+            }
 
             // frank: in case of exception
             // delete name and mv name+"#" back to name if name+"#" exists
@@ -178,7 +176,7 @@
         }
 
         try {
-            writer.close();
+            bufferedStream.close();
         } catch (IOException ex) {
             LOG.error("Failed to close save output writer", ex);
         }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.