/** Extracts specified entries from JAR file. */ void extract(InputStream in, String files[]) throws IOException { ZipInputStream zis = new ZipInputStream(in); ZipEntry e; // Set of all directory entries specified in archive. Disallows // null entries. Disallows all entries if using pre-6.0 behavior. Set<ZipEntry> dirs = newDirSet(); while ((e = zis.getNextEntry()) != null) { if (files == null) { dirs.add(extractFile(zis, e)); } else { String name = e.getName(); for (String file : files) { if (name.startsWith(file)) { dirs.add(extractFile(zis, e)); break; } } } } // Update timestamps of directories specified in archive with their // timestamps as given in the archive. We do this after extraction, // instead of during, because creating a file in a directory changes // that directory's timestamp. updateLastModifiedTime(dirs); }
/** * Parse a repository document. * * @param url * @throws IOException * @throws XmlPullParserException * @throws Exception */ void parseDocument(URL url) throws IOException, XmlPullParserException, Exception { if (!visited.contains(url)) { visited.add(url); try { System.out.println("Visiting: " + url); InputStream in = null; if (url.getPath().endsWith(".zip")) { ZipInputStream zin = new ZipInputStream(url.openStream()); ZipEntry entry = zin.getNextEntry(); while (entry != null) { if (entry.getName().equals("repository.xml")) { in = zin; break; } entry = zin.getNextEntry(); } } else { in = url.openStream(); } Reader reader = new InputStreamReader(in); XmlPullParser parser = new KXmlParser(); parser.setInput(reader); parseRepository(parser); } catch (MalformedURLException e) { System.out.println("Cannot create connection to url"); } } }
/** * Expands list of files to process into full list of all files that can be found by recursively * descending directories. */ void expand(File dir, String[] files, boolean isUpdate) { if (files == null) { return; } for (int i = 0; i < files.length; i++) { File f; if (dir == null) { f = new File(files[i]); } else { f = new File(dir, files[i]); } if (f.isFile()) { if (entries.add(f)) { if (isUpdate) entryMap.put(entryName(f.getPath()), f); } } else if (f.isDirectory()) { if (entries.add(f)) { if (isUpdate) { String dirPath = f.getPath(); dirPath = (dirPath.endsWith(File.separator)) ? dirPath : (dirPath + File.separator); entryMap.put(entryName(dirPath), f); } expand(f, f.list(), isUpdate); } } else { error(formatMsg("error.nosuch.fileordir", String.valueOf(f))); ok = false; } } }
/** * Parse the repository. * * @param parser * @throws Exception */ private void parseRepository(XmlPullParser parser) throws Exception { try { parser.require(XmlPullParser.START_DOCUMENT, null, null); parser.nextTag(); if (parser.getName().equals("bundles")) parseOscar(parser); else { parser.require(XmlPullParser.START_TAG, null, "repository"); date = parser.getAttributeValue(null, "lastmodified"); name = parser.getAttributeValue(null, "name"); if (name == null) name = "Untitled"; while (parser.nextTag() == XmlPullParser.START_TAG) { if (parser.getName().equals("resource")) { ResourceImpl resource = new ResourceImpl(this, parser); resources.add(resource); } else if (parser.getName().equals("referral")) referral(parser); else throw new IllegalArgumentException( "Invalid tag in repository: " + url + " " + parser.getName()); } parser.require(XmlPullParser.END_TAG, null, "repository"); } } catch (XmlPullParserException e) { e.printStackTrace(); throw new IllegalArgumentException( "XML unregognized around: " + e.getLineNumber() + " " + e.getMessage()); } }
/** * Refresh the repository from the URL. * * @throws Exception */ public boolean refresh() { exception = null; try { resources.clear(); parseDocument(url); visited = null; return true; } catch (Exception e) { e.printStackTrace(); exception = e; } return false; }
/** Extracts specified entries from JAR file, via ZipFile. */ void extract(String fname, String files[]) throws IOException { ZipFile zf = new ZipFile(fname); Set<ZipEntry> dirs = newDirSet(); Enumeration<? extends ZipEntry> zes = zf.entries(); while (zes.hasMoreElements()) { ZipEntry e = zes.nextElement(); InputStream is; if (files == null) { dirs.add(extractFile(zf.getInputStream(e), e)); } else { String name = e.getName(); for (String file : files) { if (name.startsWith(file)) { dirs.add(extractFile(zf.getInputStream(e), e)); break; } } } } zf.close(); updateLastModifiedTime(dirs); }
/** * Parse an old style OBR repository. * * <p><dtd-version>1.0</dtd-version> <repository> <name>Oscar Bundle Repository</name> * <url>http://oscar-osgi.sourceforge.net/</url> <date>Fri May 07 16:45:07 CEST 2004</date> * <extern-repositories> * <!-- * Stefano Lenzi ([email protected]) --> * <url>http://domoware.isti.cnr.it/osgi-obr/niche-osgi-obr.xml</url> * <!--Manuel Palencia ([email protected]) --> * <!-- * <url>http://jmood.forge.os4os.org/repository.xml</url> --> * <!-- Enrique * Rodriguez ([email protected]) --> * <url>http://update.cainenable.org/repository.xml</url> </extern-repositories> </repository> * <bundle> <bundle-name>Bundle Repository</bundle-name> <bundle-description> A bundle repository * service for Oscar. </bundle-description> <bundle-updatelocation> * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository.jar </bundle-updatelocation> * <bundle-sourceurl> http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository-src.jar * </bundle-sourceurl> <bundle-version>1.1.3</bundle-version> <bundle-docurl> * http://oscar-osgi.sf.net/repo/bundlerepository/ </bundle-docurl> * <bundle-category>General</bundle-category> <import-package package="org.osgi.framework"/> * <export-package package="org.ungoverned.osgi.service.bundlerepository" * specification-version="1.1.0"/> </bundle> * */ private void parseOscar(XmlPullParser parser) throws Exception { parser.require(XmlPullParser.START_TAG, null, "bundles"); while (true) { int event = parser.next(); // Error .. if (event == XmlPullParser.TEXT) event = parser.next(); if (event != XmlPullParser.START_TAG) break; ResourceImpl resource = new ResourceImpl(this); if (parser.getName().equals("bundle")) { while (parser.nextTag() == XmlPullParser.START_TAG) { String key = parser.getName(); if (key.equals("import-package")) { RequirementImpl requirement = new RequirementImpl("package"); requirement.setOptional(false); requirement.setMultiple(false); String p = parser.getAttributeValue(null, "package"); StringBuffer sb = new StringBuffer(); sb.append("(&(package="); sb.append(p); sb.append(")"); String version = parser.getAttributeValue(null, "specification-version"); VersionRange v = new VersionRange("0"); if (version != null) { sb.append("(version="); sb.append(v = new VersionRange(version)); sb.append(")"); } sb.append(")"); requirement.setFilter(sb.toString()); requirement.setComment("Import-Package: " + p + ";" + v); resource.addRequirement(requirement); parser.nextTag(); } else if (key.equals("export-package")) { CapabilityImpl capability = new CapabilityImpl("package"); capability.addProperty("package", parser.getAttributeValue(null, "package")); String version = parser.getAttributeValue(null, "specification-version"); if (version != null) { capability.addProperty("version", new VersionRange(version)); } resource.addCapability(capability); parser.nextTag(); } else { String value = parser.nextText().trim(); if (key.equals("bundle-sourceurl")) resource.setSource(new URL(value)); else if (key.equals("bundle-docurl")) resource.setDocumentation(new URL(value)); else if (key.equals("bundle-updatelocation")) resource.setURL(new URL(value)); else if (key.equals("bundle-description")) resource.setDescription(value); else if (key.equals("bundle-category")) resource.addCategory(value); else if (key.equals("bundle-name")) { resource.setName(value); resource.setPresentationName(value); } else if (key.equals("bundle-version")) resource.setVersion(new VersionRange(value)); else { resource.put(key, value); } } } resources.add(resource); parser.require(XmlPullParser.END_TAG, null, "bundle"); } else if (parser.getName().equals("repository")) { parser.require(XmlPullParser.START_TAG, null, "repository"); while (parser.nextTag() == XmlPullParser.START_TAG) { String tag = parser.getName(); if (tag.equals("name")) { String name = parser.nextText(); if (this.name == null) this.name = name.trim(); } else if (tag.equals("url")) parser.nextText().trim(); else if (tag.equals("date")) parser.nextText().trim(); else if (tag.equals("extern-repositories")) { parser.require(XmlPullParser.START_TAG, null, "extern-repositories"); while (parser.nextTag() == XmlPullParser.START_TAG) { if (parser.getName().equals("url")) parseDocument(new URL(parser.nextText().trim())); else throw new IllegalArgumentException( "Invalid tag in repository while parsing extern repositories: " + url + " " + parser.getName()); } parser.require(XmlPullParser.END_TAG, null, "extern-repositories"); } else throw new IllegalArgumentException( "Invalid tag in repository: " + url + " " + parser.getName()); } parser.require(XmlPullParser.END_TAG, null, "repository"); } else if (parser.getName().equals("dtd-version")) { parser.nextText(); } else throw new IllegalArgumentException( "Invalid tag in repository: " + url + " " + parser.getName()); } parser.require(XmlPullParser.END_TAG, null, "bundles"); }
/** Updates an existing jar file. */ boolean update(InputStream in, OutputStream out, InputStream newManifest, JarIndex jarIndex) throws IOException { ZipInputStream zis = new ZipInputStream(in); ZipOutputStream zos = new JarOutputStream(out); ZipEntry e = null; boolean foundManifest = false; boolean updateOk = true; if (jarIndex != null) { addIndex(jarIndex, zos); } // put the old entries first, replace if necessary while ((e = zis.getNextEntry()) != null) { String name = e.getName(); boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME); if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME)) || (Mflag && isManifestEntry)) { continue; } else if (isManifestEntry && ((newManifest != null) || (ename != null) || (pname != null))) { foundManifest = true; if (newManifest != null) { // Don't read from the newManifest InputStream, as we // might need it below, and we can't re-read the same data // twice. FileInputStream fis = new FileInputStream(mname); boolean ambiguous = isAmbiguousMainClass(new Manifest(fis)); fis.close(); if (ambiguous) { return false; } } // Update the manifest. Manifest old = new Manifest(zis); if (newManifest != null) { old.read(newManifest); } if (!updateManifest(old, zos)) { return false; } } else { if (!entryMap.containsKey(name)) { // copy the old stuff // do our own compression ZipEntry e2 = new ZipEntry(name); e2.setMethod(e.getMethod()); e2.setTime(e.getTime()); e2.setComment(e.getComment()); e2.setExtra(e.getExtra()); if (e.getMethod() == ZipEntry.STORED) { e2.setSize(e.getSize()); e2.setCrc(e.getCrc()); } zos.putNextEntry(e2); copy(zis, zos); } else { // replace with the new files File f = entryMap.get(name); addFile(zos, f); entryMap.remove(name); entries.remove(f); } } } // add the remaining new files for (File f : entries) { addFile(zos, f); } if (!foundManifest) { if (newManifest != null) { Manifest m = new Manifest(newManifest); updateOk = !isAmbiguousMainClass(m); if (updateOk) { if (!updateManifest(m, zos)) { updateOk = false; } } } else if (ename != null || pname != null) { if (!updateManifest(new Manifest(), zos)) { updateOk = false; } } } zis.close(); zos.close(); return updateOk; }
/** Parses command line arguments. */ boolean parseArgs(String args[]) { /* Preprocess and expand @file arguments */ try { args = CommandLine.parse(args); } catch (FileNotFoundException e) { fatalError(formatMsg("error.cant.open", e.getMessage())); return false; } catch (IOException e) { fatalError(e); return false; } /* parse flags */ int count = 1; try { String flags = args[0]; if (flags.startsWith("-")) { flags = flags.substring(1); } for (int i = 0; i < flags.length(); i++) { switch (flags.charAt(i)) { case 'c': if (xflag || tflag || uflag || iflag) { usageError(); return false; } cflag = true; break; case 'u': if (cflag || xflag || tflag || iflag) { usageError(); return false; } uflag = true; break; case 'x': if (cflag || uflag || tflag || iflag) { usageError(); return false; } xflag = true; break; case 't': if (cflag || uflag || xflag || iflag) { usageError(); return false; } tflag = true; break; case 'M': Mflag = true; break; case 'v': vflag = true; break; case 'f': fname = args[count++]; break; case 'm': mname = args[count++]; break; case '0': flag0 = true; break; case 'i': if (cflag || uflag || xflag || tflag) { usageError(); return false; } // do not increase the counter, files will contain rootjar rootjar = args[count++]; iflag = true; break; case 'e': ename = args[count++]; break; case 'p': pname = args[count++]; break; default: error(formatMsg("error.illegal.option", String.valueOf(flags.charAt(i)))); usageError(); return false; } } } catch (ArrayIndexOutOfBoundsException e) { usageError(); return false; } if (!cflag && !tflag && !xflag && !uflag && !iflag) { error(getMsg("error.bad.option")); usageError(); return false; } /* parse file arguments */ int n = args.length - count; if (n > 0) { int k = 0; String[] nameBuf = new String[n]; try { for (int i = count; i < args.length; i++) { if (args[i].equals("-C")) { /* change the directory */ String dir = args[++i]; dir = (dir.endsWith(File.separator) ? dir : (dir + File.separator)); dir = dir.replace(File.separatorChar, '/'); while (dir.indexOf("//") > -1) { dir = dir.replace("//", "/"); } paths.add(dir.replace(File.separatorChar, '/')); nameBuf[k++] = dir + args[++i]; } else { nameBuf[k++] = args[i]; } } } catch (ArrayIndexOutOfBoundsException e) { usageError(); return false; } files = new String[k]; System.arraycopy(nameBuf, 0, files, 0, k); } else if (cflag && (mname == null)) { error(getMsg("error.bad.cflag")); usageError(); return false; } else if (uflag) { if ((mname != null) || (ename != null) || (pname != null)) { /* just want to update the manifest */ return true; } else { error(getMsg("error.bad.uflag")); usageError(); return false; } } return true; }