private void checkStartup( Map<String, ServiceData> map, List<ServiceData> start, ServiceData sd, Set<ServiceData> cyclic) { if (sd.after.isEmpty() || start.contains(sd)) return; if (cyclic.contains(sd)) { reporter.error("Cyclic dependency for " + sd.name); return; } cyclic.add(sd); for (String dependsOn : sd.after) { if (dependsOn.equals("boot")) continue; ServiceData deps = map.get(dependsOn); if (deps == null) { reporter.error("No such service " + dependsOn + " but " + sd.name + " depends on it"); } else { checkStartup(map, start, deps, cyclic); } } start.add(sd); }
/** * This is called when JPM runs in the background to start jobs * * @throws Exception */ public void daemon() throws Exception { Runtime.getRuntime() .addShutdownHook( new Thread("Daemon shutdown") { public void run() { for (Service service : startedByDaemon) { try { reporter.error("Stopping " + service); service.stop(); reporter.error("Stopped " + service); } catch (Exception e) { // Ignore } } } }); List<ServiceData> services = getServices(); Map<String, ServiceData> map = new HashMap<String, ServiceData>(); for (ServiceData d : services) { map.put(d.name, d); } List<ServiceData> start = new ArrayList<ServiceData>(); Set<ServiceData> set = new HashSet<ServiceData>(); for (ServiceData sd : services) { checkStartup(map, start, sd, set); } if (start.isEmpty()) reporter.warning("No services to start"); for (ServiceData sd : start) { try { Service service = getService(sd.name); reporter.trace("Starting " + service); String result = service.start(); if (result != null) reporter.error("Started error " + result); else startedByDaemon.add(service); reporter.trace("Started " + service); } catch (Exception e) { reporter.error("Cannot start daemon %s, due to %s", sd.name, e); } } while (true) { for (Service sd : startedByDaemon) { try { if (!sd.isRunning()) { reporter.error("Starting due to failure " + sd); String result = sd.start(); if (result != null) reporter.error("Started error " + result); } } catch (Exception e) { reporter.error("Cannot start daemon %s, due to %s", sd, e); } } Thread.sleep(10000); } }
@Override public void parameter(int p) { for (ClassDataCollector cd : shortlist) try { cd.parameter(p); } catch (Exception e) { reporter.error("Fail to class parameter on %s", cd); } }
@Override public void referTo(TypeRef typeRef, int modifiers) { for (ClassDataCollector cd : shortlist) try { cd.referTo(typeRef, modifiers); } catch (Exception e) { reporter.error("Fail to call referTo on %s", cd); } }
@Override public void referenceMethod(int access, TypeRef className, String method, String descriptor) { for (ClassDataCollector cd : shortlist) try { cd.referenceMethod(access, className, method, descriptor); } catch (Exception e) { reporter.error("Fail to call referenceMethod on %s", cd); } }
@Override public void version(int minor, int major) { for (ClassDataCollector cd : shortlist) try { cd.version(minor, major); } catch (Exception e) { reporter.error("Fail to call version on %s", cd); } }
@Override public void addReference(TypeRef ref) { for (ClassDataCollector cd : shortlist) try { cd.addReference(ref); } catch (Exception e) { reporter.error("Fail to class addReference on %s", cd); } }
@Override public void constant(Object object) { for (ClassDataCollector cd : shortlist) try { cd.constant(object); } catch (Exception e) { reporter.error("Fail to call constant on %s", cd); } }
@Override public void signature(String signature) { for (ClassDataCollector cd : shortlist) try { cd.signature(signature); } catch (Exception e) { reporter.error("Fail to call innerClass on %s", cd); } }
@Override public void enclosingMethod(TypeRef cName, String mName, String mDescriptor) { for (ClassDataCollector cd : shortlist) try { cd.enclosingMethod(cName, mName, mDescriptor); } catch (Exception e) { reporter.error("Fail to call enclosingMethod on %s", cd); } }
@Override public void deprecated() throws Exception { for (ClassDataCollector cd : shortlist) try { cd.deprecated(); } catch (Exception e) { reporter.error("Fail to call deprecated on %s", cd); } }
@Override public void field(FieldDef defined) { for (ClassDataCollector cd : shortlist) try { cd.field(defined); } catch (Exception e) { reporter.error("Fail to call field on %s", cd); } }
@Override public void classBegin(int access, TypeRef name) { for (ClassDataCollector cd : delegates) try { cd.classBegin(access, name); } catch (Exception e) { reporter.error("Fail to class classBegin on %s", cd); } }
@Override public void memberEnd() { for (ClassDataCollector cd : shortlist) try { cd.memberEnd(); } catch (Exception e) { reporter.error("Fail to call memberEnd on %s", cd); } }
@Override public void implementsInterfaces(TypeRef[] interfaces) throws Exception { for (ClassDataCollector cd : shortlist) try { cd.implementsInterfaces(interfaces); } catch (Exception e) { reporter.error("Fail to class implementsInterfaces on %s", cd); } }
@Override public void extendsClass(TypeRef zuper) throws Exception { for (ClassDataCollector cd : shortlist) try { cd.extendsClass(zuper); } catch (Exception e) { reporter.error("Fail to class extendsClass on %s", cd); } }
@Override public void annotation(Annotation annotation) { for (ClassDataCollector cd : shortlist) try { cd.annotation(annotation); } catch (Exception e) { reporter.error("Fail to class annotation on %s", cd); } }
@Override public void classEnd() throws Exception { for (ClassDataCollector cd : shortlist) try { cd.classEnd(); } catch (Exception e) { reporter.error("Fail to call classEnd on %s", cd); } shortlist.clear(); }
public void close() { for (ClassDataCollector cd : delegates) try { if (cd instanceof Closeable) ((Closeable) cd).close(); } catch (Exception e) { reporter.error("Fail to call close on %s", cd); } delegates.clear(); shortlist.clear(); }
@Override public void innerClass( TypeRef innerClass, TypeRef outerClass, String innerName, int innerClassAccessFlags) throws Exception { for (ClassDataCollector cd : shortlist) try { cd.innerClass(innerClass, outerClass, innerName, innerClassAccessFlags); } catch (Exception e) { reporter.error("Fail to call innerClass on %s", cd); } }
@Override public boolean classStart(Clazz clazz) { boolean start = false; for (ClassDataCollector cd : delegates) try { if (cd.classStart(clazz)) { shortlist.add(cd); start = true; } } catch (Exception e) { reporter.error("Fail to class classStart on %s", cd); } return start; }
@Override public void log(ServiceReference sr, int level, String message, Throwable exception) { switch (level) { case LogService.LOG_ERROR: reporter.error("%s:%s: %s", sr, exception, message); return; case LogService.LOG_WARNING: reporter.warning("%s:%s: %s", sr, exception, message); return; default: reporter.trace("%s:%s: %s", sr, exception, message); return; } }
@Override public void log(int level, String message) { if (level > this.level) return; switch (level) { case LogService.LOG_ERROR: reporter.error("%s", message); return; case LogService.LOG_WARNING: reporter.warning("%s", message); return; default: reporter.trace("%s", message); return; } }
public String verify(JarFile jar, String... algorithms) throws IOException { if (algorithms == null || algorithms.length == 0) algorithms = new String[] {"MD5", "SHA"}; else if (algorithms.length == 1 && algorithms[0].equals("-")) return null; try { Manifest m = jar.getManifest(); if (m.getEntries().isEmpty()) return "No name sections"; for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) { JarEntry je = e.nextElement(); if (MANIFEST_ENTRY.matcher(je.getName()).matches()) continue; Attributes nameSection = m.getAttributes(je.getName()); if (nameSection == null) return "No name section for " + je.getName(); for (String algorithm : algorithms) { try { MessageDigest md = MessageDigest.getInstance(algorithm); String expected = nameSection.getValue(algorithm + "-Digest"); if (expected != null) { byte digest[] = Base64.decodeBase64(expected); copy(jar.getInputStream(je), md); if (!Arrays.equals(digest, md.digest())) return "Invalid digest for " + je.getName() + ", " + expected + " != " + Base64.encodeBase64(md.digest()); } else reporter.error("could not find digest for " + algorithm + "-Digest"); } catch (NoSuchAlgorithmException nsae) { return "Missing digest algorithm " + algorithm; } } } } catch (Exception e) { return "Failed to verify due to exception: " + e.getMessage(); } return null; }
public String what(String key, boolean oneliner) throws Exception { byte[] sha; Matcher m = SHA_P.matcher(key); if (m.matches()) { sha = Hex.toByteArray(key); } else { m = URL_P.matcher(key); if (m.matches()) { URL url = new URL(key); sha = SHA1.digest(url.openStream()).digest(); } else { File jarfile = new File(key); if (!jarfile.exists()) { reporter.error("File does not exist: %s", jarfile.getCanonicalPath()); } sha = SHA1.digest(jarfile).digest(); } } reporter.trace("sha %s", Hex.toHexString(sha)); Revision revision = library.getRevision(sha); if (revision == null) { return null; } StringBuilder sb = new StringBuilder(); Formatter f = new Formatter(sb); Justif justif = new Justif(120, 20, 70, 20, 75); DateFormat dateFormat = DateFormat.getDateInstance(); try { if (oneliner) { f.format("%20s %s%n", Hex.toHexString(revision._id), createCoord(revision)); } else { f.format("Artifact: %s%n", revision.artifactId); if (revision.organization != null && revision.organization.name != null) { f.format(" (%s)", revision.organization.name); } f.format("%n"); f.format("Coordinates\t0: %s%n", createCoord(revision)); f.format("Created\t0: %s%n", dateFormat.format(new Date(revision.created))); f.format("Size\t0: %d%n", revision.size); f.format("Sha\t0: %s%n", Hex.toHexString(revision._id)); f.format("URL\t0: %s%n", createJpmLink(revision)); f.format("%n"); f.format("%s%n", revision.description); f.format("%n"); f.format("Dependencies\t0:%n"); boolean flag = false; Iterable<RevisionRef> closure = library.getClosure(revision._id, true); for (RevisionRef dep : closure) { f.format( " - %s \t2- %s \t3- %s%n", dep.name, createCoord(dep), dateFormat.format(new Date(dep.created))); flag = true; } if (!flag) { f.format(" None%n"); } f.format("%n"); } f.flush(); justif.wrap(sb); return sb.toString(); } finally { f.close(); } }
public void deinit(Appendable out, boolean force) throws Exception { Settings settings = new Settings(platform.getConfigFile()); if (!force) { Justif justify = new Justif(80, 40); StringBuilder sb = new StringBuilder(); Formatter f = new Formatter(sb); try { String list = listFiles(platform.getGlobal()); if (list != null) { f.format("In global default environment:%n"); f.format(list); } list = listFiles(platform.getLocal()); if (list != null) { f.format("In local default environment:%n"); f.format(list); } if (settings.containsKey(JPM_CACHE_GLOBAL)) { list = listFiles(IO.getFile(settings.get(JPM_CACHE_GLOBAL))); if (list != null) { f.format("In global configured environment:%n"); f.format(list); } } if (settings.containsKey(JPM_CACHE_LOCAL)) { list = listFiles(IO.getFile(settings.get(JPM_CACHE_LOCAL))); if (list != null) { f.format("In local configured environment:%n"); f.format(list); } } list = listSupportFiles(); if (list != null) { f.format("jpm support files:%n"); f.format(list); } f.format("%n%n"); f.format( "All files listed above will be deleted if deinit is run with the force flag set" + " (\"jpm deinit -f\" or \"jpm deinit --force\"%n%n"); f.flush(); justify.wrap(sb); out.append(sb.toString()); } finally { f.close(); } } else { // i.e. if(force) int count = 0; File[] caches = {platform.getGlobal(), platform.getLocal(), null, null}; if (settings.containsKey(JPM_CACHE_LOCAL)) { caches[2] = IO.getFile(settings.get(JPM_CACHE_LOCAL)); } if (settings.containsKey(JPM_CACHE_GLOBAL)) { caches[3] = IO.getFile(settings.get(JPM_CACHE_GLOBAL)); } ArrayList<File> toDelete = new ArrayList<File>(); for (File cache : caches) { if (cache == null || !cache.exists()) { continue; } listFiles(cache, toDelete); if (toDelete.size() > count) { count = toDelete.size(); if (!cache.canWrite()) { reporter.error(PERMISSION_ERROR + " (" + cache + ")"); return; } toDelete.add(cache); } } listSupportFiles(toDelete); for (File f : toDelete) { if (f.exists() && !f.canWrite()) { reporter.error(PERMISSION_ERROR + " (" + f + ")"); } } if (reporter.getErrors().size() > 0) { return; } for (File f : toDelete) { if (f.exists()) { IO.deleteWithException(f); } } } }
public CommandData parseCommandData(ArtifactData artifact) throws Exception { File source = new File(artifact.file); if (!source.isFile()) throw new FileNotFoundException(); CommandData data = new CommandData(); data.sha = artifact.sha; data.jpmRepoDir = repoDir.getCanonicalPath(); JarFile jar = new JarFile(source); try { reporter.trace("Parsing %s", source); Manifest m = jar.getManifest(); Attributes main = m.getMainAttributes(); data.name = data.bsn = main.getValue("Bundle-SymbolicName"); String version = main.getValue("Bundle-Version"); if (version == null) data.version = Version.LOWEST; else data.version = new Version(version); data.main = main.getValue("Main-Class"); data.description = main.getValue("Bundle-Description"); data.title = main.getValue("JPM-Name"); reporter.trace("name " + data.name + " " + data.main + " " + data.title); DependencyCollector path = new DependencyCollector(this); path.add(artifact); DependencyCollector bundles = new DependencyCollector(this); if (main.getValue("JPM-Classpath") != null) { Parameters requires = OSGiHeader.parseHeader(main.getValue("JPM-Classpath")); for (Map.Entry<String, Attrs> e : requires.entrySet()) { path.add(e.getKey(), e.getValue().get("name")); // coordinate } } else if (!artifact.local) { // No JPM-Classpath, falling back to // server's revision // Iterable<RevisionRef> closure = // library.getClosure(artifact.sha, // false); // System.out.println("getting closure " + artifact.url + " " + // Strings.join("\n",closure)); // if (closure != null) { // for (RevisionRef ref : closure) { // path.add(Hex.toHexString(ref.revision)); // } // } } if (main.getValue("JPM-Runbundles") != null) { Parameters jpmrunbundles = OSGiHeader.parseHeader(main.getValue("JPM-Runbundles")); for (Map.Entry<String, Attrs> e : jpmrunbundles.entrySet()) { bundles.add(e.getKey(), e.getValue().get("name")); } } reporter.trace("collect digests runpath"); data.dependencies.addAll(path.getDigests()); reporter.trace("collect digests bundles"); data.runbundles.addAll(bundles.getDigests()); Parameters command = OSGiHeader.parseHeader(main.getValue("JPM-Command")); if (command.size() > 1) reporter.error("Only one command can be specified"); for (Map.Entry<String, Attrs> e : command.entrySet()) { data.name = e.getKey(); Attrs attrs = e.getValue(); if (attrs.containsKey("jvmargs")) data.jvmArgs = attrs.get("jvmargs"); if (attrs.containsKey("title")) data.title = attrs.get("title"); if (data.title != null) data.title = data.name; } return data; } finally { jar.close(); } }