1 | /* $Id: ZipFilePersister.java 19907 2012-12-30 13:06:01Z closettop_nightlybuild $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009-2012 Contributors - see below | |
4 | * All rights reserved. This program and the accompanying materials | |
5 | * are made available under the terms of the Eclipse Public License v1.0 | |
6 | * which accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * tfmorris | |
11 | * Michiel van der Wulp | |
12 | ***************************************************************************** | |
13 | * | |
14 | * Some portions of this file was previously release using the BSD License: | |
15 | */ | |
16 | ||
17 | // Copyright (c) 1996-2008 The Regents of the University of California. All | |
18 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
19 | // software and its documentation without fee, and without a written | |
20 | // agreement is hereby granted, provided that the above copyright notice | |
21 | // and this paragraph appear in all copies. This software program and | |
22 | // documentation are copyrighted by The Regents of the University of | |
23 | // California. The software program and documentation are supplied "AS | |
24 | // IS", without any accompanying services from The Regents. The Regents | |
25 | // does not warrant that the operation of the program will be | |
26 | // uninterrupted or error-free. The end-user understands that the program | |
27 | // was developed for research purposes and is advised not to rely | |
28 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
29 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
30 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
31 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
32 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
33 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
34 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
35 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
36 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
37 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
38 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
39 | ||
40 | package org.argouml.persistence; | |
41 | ||
42 | import java.io.BufferedOutputStream; | |
43 | import java.io.File; | |
44 | import java.io.FileNotFoundException; | |
45 | import java.io.FileOutputStream; | |
46 | import java.io.IOException; | |
47 | import java.io.InputStream; | |
48 | import java.io.OutputStream; | |
49 | import java.net.URL; | |
50 | import java.util.logging.Level; | |
51 | import java.util.logging.Logger; | |
52 | import java.util.zip.ZipEntry; | |
53 | import java.util.zip.ZipInputStream; | |
54 | import java.util.zip.ZipOutputStream; | |
55 | ||
56 | import org.argouml.i18n.Translator; | |
57 | import org.argouml.kernel.Project; | |
58 | import org.argouml.kernel.ProjectFactory; | |
59 | import org.argouml.kernel.ProjectManager; | |
60 | import org.argouml.kernel.ProjectMember; | |
61 | import org.argouml.model.Model; | |
62 | import org.xml.sax.InputSource; | |
63 | ||
64 | /** | |
65 | * To persist to and from zipped xmi file storage. | |
66 | * | |
67 | * @author Bob Tarling | |
68 | * @author Ludovic Maître | |
69 | */ | |
70 | class ZipFilePersister extends XmiFilePersister { | |
71 | /** | |
72 | * Logger. | |
73 | */ | |
74 | private static final Logger LOG = | |
75 | Logger.getLogger(ZipFilePersister.class.getName()); | |
76 | ||
77 | /** | |
78 | * The constructor. | |
79 | */ | |
80 | public ZipFilePersister() { | |
81 | } | |
82 | ||
83 | /* | |
84 | * @see org.argouml.persistence.AbstractFilePersister#getExtension() | |
85 | */ | |
86 | public String getExtension() { | |
87 |
1
1. getExtension : mutated return of Object value for org/argouml/persistence/ZipFilePersister::getExtension to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return "zip"; |
88 | } | |
89 | ||
90 | /* | |
91 | * @see org.argouml.persistence.AbstractFilePersister#getDesc() | |
92 | */ | |
93 | protected String getDesc() { | |
94 |
1
1. getDesc : mutated return of Object value for org/argouml/persistence/ZipFilePersister::getDesc to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return Translator.localize("combobox.filefilter.zip"); |
95 | } | |
96 | ||
97 | /* | |
98 | * @see org.argouml.persistence.XmiFilePersister#isSaveEnabled() | |
99 | */ | |
100 | public boolean isSaveEnabled() { | |
101 |
1
1. isSaveEnabled : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
102 | } | |
103 | ||
104 | /** | |
105 | * Save the project in ZIP format. | |
106 | * | |
107 | * @param file | |
108 | * The file to write. | |
109 | * @param project | |
110 | * the project to save | |
111 | * @throws SaveException | |
112 | * when anything goes wrong | |
113 | * | |
114 | * @see org.argouml.persistence.ProjectFilePersister#save( | |
115 | * org.argouml.kernel.Project, java.io.File) | |
116 | */ | |
117 | public void doSave(Project project, File file) throws SaveException { | |
118 | ||
119 | LOG.log(Level.INFO, "Receiving file {0}", file.getName()); | |
120 | ||
121 | /* Retain the previous project file even when the save operation | |
122 | * crashes in the middle. Also create a backup file after saving. */ | |
123 | boolean doSafeSaves = useSafeSaves(); | |
124 | ||
125 | File lastArchiveFile = new File(file.getAbsolutePath() + "~"); | |
126 | File tempFile = null; | |
127 | ||
128 |
1
1. doSave : negated conditional → NO_COVERAGE |
if (doSafeSaves) { |
129 | try { | |
130 | tempFile = createTempFile(file); | |
131 | } catch (FileNotFoundException e) { | |
132 | throw new SaveException(Translator.localize( | |
133 | "optionpane.save-project-exception-cause1"), e); | |
134 | } catch (IOException e) { | |
135 | throw new SaveException(Translator.localize( | |
136 | "optionpane.save-project-exception-cause2"), e); | |
137 | } | |
138 | } | |
139 | ||
140 | OutputStream bufferedStream = null; | |
141 | try { | |
142 | //project.setFile(file); | |
143 | ||
144 | ZipOutputStream stream = | |
145 | new ZipOutputStream(new FileOutputStream(file)); | |
146 | String fileName = file.getName(); | |
147 | ZipEntry xmiEntry = | |
148 | new ZipEntry(fileName.substring(0, fileName.lastIndexOf("."))); | |
149 |
1
1. doSave : removed call to java/util/zip/ZipOutputStream::putNextEntry → NO_COVERAGE |
stream.putNextEntry(xmiEntry); |
150 | bufferedStream = new BufferedOutputStream(stream); | |
151 | ||
152 | int size = project.getMembers().size(); | |
153 |
3
1. doSave : changed conditional boundary → NO_COVERAGE 2. doSave : Changed increment from 1 to -1 → NO_COVERAGE 3. doSave : negated conditional → NO_COVERAGE |
for (int i = 0; i < size; i++) { |
154 | ProjectMember projectMember = | |
155 | project.getMembers().get(i); | |
156 |
1
1. doSave : negated conditional → NO_COVERAGE |
if (projectMember.getType().equalsIgnoreCase("xmi")) { |
157 | LOG.log(Level.FINE, | |
158 | "Saving member of type: {0}", | |
159 | projectMember.getType()); | |
160 | ||
161 | MemberFilePersister persister | |
162 | = new ModelMemberFilePersister(); | |
163 |
1
1. doSave : removed call to org/argouml/persistence/MemberFilePersister::save → NO_COVERAGE |
persister.save(projectMember, bufferedStream); |
164 | } | |
165 | } | |
166 |
1
1. doSave : removed call to java/util/zip/ZipOutputStream::close → NO_COVERAGE |
stream.close(); |
167 | ||
168 |
1
1. doSave : negated conditional → NO_COVERAGE |
if (doSafeSaves) { |
169 | // if save did not raise an exception | |
170 | // and name+"#" exists move name+"#" to name+"~" | |
171 | // this is the correct backup file | |
172 |
1
1. doSave : negated conditional → NO_COVERAGE |
if (lastArchiveFile.exists()) { |
173 | lastArchiveFile.delete(); | |
174 | } | |
175 |
2
1. doSave : negated conditional → NO_COVERAGE 2. doSave : negated conditional → NO_COVERAGE |
if (tempFile.exists() && !lastArchiveFile.exists()) { |
176 | tempFile.renameTo(lastArchiveFile); | |
177 | } | |
178 |
1
1. doSave : negated conditional → NO_COVERAGE |
if (tempFile.exists()) { |
179 | tempFile.delete(); | |
180 | } | |
181 | } | |
182 | } catch (Exception e) { | |
183 | LOG.log(Level.SEVERE, "Exception occured during save attempt", e); | |
184 | try { | |
185 |
1
1. doSave : removed call to java/io/OutputStream::close → NO_COVERAGE |
bufferedStream.close(); |
186 | } catch (IOException ex) { | |
187 | // If we get a 2nd error, just ignore it | |
188 | } | |
189 | ||
190 |
1
1. doSave : negated conditional → NO_COVERAGE |
if (doSafeSaves) { |
191 | // frank: in case of exception | |
192 | // delete name and mv name+"#" back to name if name+"#" exists | |
193 | // this is the "rollback" to old file | |
194 | file.delete(); | |
195 | tempFile.renameTo(file); | |
196 | } | |
197 | // we have to give a message to user and set the system to unsaved! | |
198 | throw new SaveException(e); | |
199 | } | |
200 | ||
201 | try { | |
202 |
1
1. doSave : removed call to java/io/OutputStream::close → NO_COVERAGE |
bufferedStream.close(); |
203 | } catch (IOException ex) { | |
204 | LOG.log(Level.SEVERE, "Failed to close save output writer", ex); | |
205 | } | |
206 | } | |
207 | ||
208 | /* | |
209 | * @see org.argouml.persistence.ProjectFilePersister#doLoad(java.io.File) | |
210 | */ | |
211 | public Project doLoad(File file) | |
212 | throws OpenException { | |
213 | ||
214 | LOG.log(Level.INFO, "Receiving file {0}", file.getName()); | |
215 | ||
216 | try { | |
217 | Project p = ProjectFactory.getInstance().createProject(); | |
218 | String fileName = file.getName(); | |
219 | String extension = | |
220 | fileName.substring( | |
221 | fileName.indexOf('.'), | |
222 | fileName.lastIndexOf('.')); | |
223 | InputStream stream = openZipStreamAt(file.toURI().toURL(), | |
224 | extension); | |
225 | ||
226 | // TODO: What progressMgr is to be used here? Where does | |
227 | // it come from? | |
228 | InputSource is = | |
229 | new InputSource( | |
230 | new XmiInputStream(stream, this, 100000, null)); | |
231 |
1
1. doLoad : removed call to org/xml/sax/InputSource::setSystemId → NO_COVERAGE |
is.setSystemId(file.toURI().toURL().toExternalForm()); |
232 | ||
233 | ModelMemberFilePersister modelPersister = | |
234 | new ModelMemberFilePersister(); | |
235 | ||
236 |
1
1. doLoad : removed call to org/argouml/persistence/ModelMemberFilePersister::readModels → NO_COVERAGE |
modelPersister.readModels(is); |
237 | // TODO Handle multiple top level packages | |
238 | Object model = modelPersister.getCurModel(); | |
239 |
1
1. doLoad : removed call to org/argouml/model/UmlHelper::addListenersToModel → NO_COVERAGE |
Model.getUmlHelper().addListenersToModel(model); |
240 |
1
1. doLoad : removed call to org/argouml/kernel/Project::setUUIDRefs → NO_COVERAGE |
p.setUUIDRefs(modelPersister.getUUIDRefs()); |
241 |
1
1. doLoad : removed call to org/argouml/kernel/Project::addMember → NO_COVERAGE |
p.addMember(model); |
242 |
1
1. doLoad : removed call to org/argouml/persistence/ZipFilePersister::parseXmiExtensions → NO_COVERAGE |
parseXmiExtensions(p); |
243 |
1
1. doLoad : removed call to org/argouml/persistence/ModelMemberFilePersister::registerDiagrams → NO_COVERAGE |
modelPersister.registerDiagrams(p); |
244 | ||
245 |
1
1. doLoad : removed call to org/argouml/kernel/Project::setRoot → NO_COVERAGE |
p.setRoot(model); |
246 |
1
1. doLoad : removed call to org/argouml/kernel/Project::setRoots → NO_COVERAGE |
p.setRoots(modelPersister.getElementsRead()); |
247 |
1
1. doLoad : removed call to org/argouml/kernel/ProjectManager::setSaveEnabled → NO_COVERAGE |
ProjectManager.getManager().setSaveEnabled(false); |
248 |
1
1. doLoad : mutated return of Object value for org/argouml/persistence/ZipFilePersister::doLoad to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return p; |
249 | } catch (IOException e) { | |
250 | throw new OpenException(e); | |
251 | } | |
252 | ||
253 | } | |
254 | ||
255 | /** | |
256 | * Open a ZipInputStream to the first file found with a given extension. | |
257 | * | |
258 | * @param url | |
259 | * The URL of the zip file. | |
260 | * @param ext | |
261 | * The required extension. | |
262 | * @return the zip stream positioned at the required location. | |
263 | * @throws IOException | |
264 | * if there is a problem opening the file. | |
265 | */ | |
266 | private ZipInputStream openZipStreamAt(URL url, String ext) | |
267 | throws IOException { | |
268 | ZipInputStream zis = new ZipInputStream(url.openStream()); | |
269 | ZipEntry entry = zis.getNextEntry(); | |
270 |
2
1. openZipStreamAt : negated conditional → NO_COVERAGE 2. openZipStreamAt : negated conditional → NO_COVERAGE |
while (entry != null && !entry.getName().endsWith(ext)) { |
271 | entry = zis.getNextEntry(); | |
272 | } | |
273 |
1
1. openZipStreamAt : mutated return of Object value for org/argouml/persistence/ZipFilePersister::openZipStreamAt to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return zis; |
274 | } | |
275 | ||
276 | /** | |
277 | * Returns false. Only Argo specific files have an icon. | |
278 | * | |
279 | * @see org.argouml.persistence.AbstractFilePersister#hasAnIcon() | |
280 | */ | |
281 | @Override | |
282 | public boolean hasAnIcon() { | |
283 |
1
1. hasAnIcon : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
284 | } | |
285 | } | |
Mutations | ||
87 |
1.1 |
|
94 |
1.1 |
|
101 |
1.1 |
|
128 |
1.1 |
|
149 |
1.1 |
|
153 |
1.1 2.2 3.3 |
|
156 |
1.1 |
|
163 |
1.1 |
|
166 |
1.1 |
|
168 |
1.1 |
|
172 |
1.1 |
|
175 |
1.1 2.2 |
|
178 |
1.1 |
|
185 |
1.1 |
|
190 |
1.1 |
|
202 |
1.1 |
|
231 |
1.1 |
|
236 |
1.1 |
|
239 |
1.1 |
|
240 |
1.1 |
|
241 |
1.1 |
|
242 |
1.1 |
|
243 |
1.1 |
|
245 |
1.1 |
|
246 |
1.1 |
|
247 |
1.1 |
|
248 |
1.1 |
|
270 |
1.1 2.2 |
|
273 |
1.1 |
|
283 |
1.1 |