1 36 37 package jnlp.sample.jardiff; 38 39 import java.io.*; 40 import java.util.*; 41 import java.net.URL ; 42 import java.util.jar.*; 43 import java.util.zip.*; 44 45 54 public class JarDiffPatcher implements JarDiffConstants, Patcher { 55 private static final int DEFAULT_READ_SIZE = 2048; 56 private static byte[] newBytes = new byte[DEFAULT_READ_SIZE]; 57 private static byte[] oldBytes = new byte[DEFAULT_READ_SIZE]; 58 private static ResourceBundle _resources = JarDiff.getResources(); 59 60 public static ResourceBundle getResources() { 61 return JarDiff.getResources(); 62 } 63 64 public void applyPatch(Patcher.PatchDelegate delegate, String oldJarPath, 65 String jarDiffPath, OutputStream result) throws IOException { 66 File oldFile = new File(oldJarPath); 67 File diffFile = new File(jarDiffPath); 68 JarOutputStream jos = new JarOutputStream(result); 69 JarFile oldJar = new JarFile(oldFile); 70 JarFile jarDiff = new JarFile(diffFile); 71 Set ignoreSet = new HashSet(); 72 Map renameMap = new HashMap(); 73 74 75 determineNameMapping(jarDiff, ignoreSet, renameMap); 76 77 Object [] keys = renameMap.keySet().toArray(); 79 80 81 Set oldjarNames = new HashSet(); 83 84 Enumeration oldEntries = oldJar.entries(); 85 if (oldEntries != null) { 86 while (oldEntries.hasMoreElements()) { 87 oldjarNames.add(((JarEntry)oldEntries.nextElement()).getName()); 88 } 89 } 90 91 double size = oldjarNames.size() + keys.length + jarDiff.size(); 98 double currentEntry = 0; 99 100 oldjarNames.removeAll(ignoreSet); 102 size -= ignoreSet.size(); 103 104 105 Enumeration entries = jarDiff.entries(); 107 if (entries != null) { 108 while (entries.hasMoreElements()) { 109 JarEntry entry = (JarEntry)entries.nextElement(); 110 111 112 113 if (!INDEX_NAME.equals(entry.getName())) { 114 115 updateDelegate(delegate, currentEntry, size); 116 currentEntry++; 117 118 writeEntry(jos, entry, jarDiff); 119 120 boolean wasInOld = oldjarNames.remove(entry.getName()); 123 124 if (wasInOld) size--; 127 128 } 129 else { 130 size--; 132 } 133 } 134 } 135 136 137 138 for (int j = 0; j < keys.length; j++) { 140 141 142 143 String newName = (String )keys[j]; 145 String oldName = (String )renameMap.get(newName); 146 147 JarEntry oldEntry = oldJar.getJarEntry(oldName); 149 150 if (oldEntry == null) { 151 String moveCmd = MOVE_COMMAND + oldName + " " + newName; 152 handleException("jardiff.error.badmove", moveCmd); 153 } 154 155 JarEntry newEntry = new JarEntry(newName); 157 newEntry.setTime(oldEntry.getTime()); 158 newEntry.setSize(oldEntry.getSize()); 159 newEntry.setCompressedSize(oldEntry.getCompressedSize()); 160 newEntry.setCrc(oldEntry.getCrc()); 161 newEntry.setMethod(oldEntry.getMethod()); 162 newEntry.setExtra(oldEntry.getExtra()); 163 newEntry.setComment(oldEntry.getComment()); 164 165 166 updateDelegate(delegate, currentEntry, size); 167 currentEntry++; 168 169 writeEntry(jos, newEntry, oldJar.getInputStream(oldEntry)); 170 171 boolean wasInOld = oldjarNames.remove(oldName); 174 175 if (wasInOld) size--; 178 179 } 180 181 Iterator iEntries = oldjarNames.iterator(); 183 if (iEntries != null) { 184 while (iEntries.hasNext()) { 185 186 String name = (String )iEntries.next(); 187 JarEntry entry = oldJar.getJarEntry(name); 188 189 updateDelegate(delegate, currentEntry, size); 190 currentEntry++; 191 192 writeEntry(jos, entry, oldJar); 193 } 194 } 195 196 updateDelegate(delegate, currentEntry, size); 197 198 jos.finish(); 199 } 200 201 private void updateDelegate(Patcher.PatchDelegate delegate, double currentSize, double size) { 202 if (delegate != null) { 203 delegate.patching((int)(currentSize/size)); 204 } 205 } 206 207 private void determineNameMapping(JarFile jarDiff, Set ignoreSet, 208 Map renameMap) throws IOException { 209 InputStream is = jarDiff.getInputStream(jarDiff.getEntry(INDEX_NAME)); 210 211 if (is == null) { 212 handleException("jardiff.error.noindex", null); 213 214 } 215 LineNumberReader indexReader = new LineNumberReader 216 (new InputStreamReader(is, "UTF-8")); 217 String line = indexReader.readLine(); 218 219 if (line == null || !line.equals(VERSION_HEADER)) { 220 handleException("jardiff.error.badheader", line); 221 222 } 223 224 while ((line = indexReader.readLine()) != null) { 225 if (line.startsWith(REMOVE_COMMAND)) { 226 List sub = getSubpaths(line.substring(REMOVE_COMMAND. 227 length())); 228 229 if (sub.size() != 1) { 230 handleException("jardiff.error.badremove", line); 231 232 } 233 ignoreSet.add(sub.get(0)); 234 } 235 else if (line.startsWith(MOVE_COMMAND)) { 236 List sub = getSubpaths(line.substring(MOVE_COMMAND.length())); 237 238 if (sub.size() != 2) { 239 handleException("jardiff.error.badmove", line); 240 241 } 242 if (renameMap.put(sub.get(1), sub.get(0)) != null) { 244 handleException("jardiff.error.badmove", line); 246 } 247 } 248 else if (line.length() > 0) { 249 handleException("jardiff.error.badcommand", line); 250 251 } 252 } 253 } 254 255 private void handleException(String errorMsg, String line) throws IOException { 256 try { 257 throw new IOException(getResources().getString(errorMsg) + " " + line); 258 } catch (MissingResourceException mre) { 259 System.err.println("Fatal error: " + errorMsg); 260 new Throwable ().printStackTrace(System.err); 261 System.exit(-1); 262 } 263 } 264 265 private List getSubpaths(String path) { 266 int index = 0; 267 int length = path.length(); 268 ArrayList sub = new ArrayList(); 269 270 while (index < length) { 271 while (index < length && Character.isWhitespace 272 (path.charAt(index))) { 273 index++; 274 } 275 if (index < length) { 276 int start = index; 277 int last = start; 278 String subString = null; 279 280 while (index < length) { 281 char aChar = path.charAt(index); 282 if (aChar == '\\' && (index + 1) < length && 283 path.charAt(index + 1) == ' ') { 284 285 if (subString == null) { 286 subString = path.substring(last, index); 287 } 288 else { 289 subString += path.substring(last, index); 290 } 291 last = ++index; 292 } 293 else if (Character.isWhitespace(aChar)) { 294 break; 295 } 296 index++; 297 } 298 if (last != index) { 299 if (subString == null) { 300 subString = path.substring(last, index); 301 } 302 else { 303 subString += path.substring(last, index); 304 } 305 } 306 sub.add(subString); 307 } 308 } 309 return sub; 310 } 311 312 private void writeEntry(JarOutputStream jos, JarEntry entry, 313 JarFile file) throws IOException { 314 writeEntry(jos, entry, file.getInputStream(entry)); 315 } 316 317 private void writeEntry(JarOutputStream jos, JarEntry entry, 318 InputStream data) throws IOException { 319 jos.putNextEntry(new ZipEntry(entry.getName())); 321 322 int size = data.read(newBytes); 324 325 while (size != -1) { 326 jos.write(newBytes, 0, size); 327 size = data.read(newBytes); 328 } 329 data.close(); 330 } 331 } 332 333 334 | Popular Tags |