/** * @see com.liferay.modulesadmin.portlet.ModulesAdminPortlet#getBundle( BundleContext, * InputStream) */ public Bundle getBundle(BundleContext bundleContext, InputStream inputStream) throws PortalException { try { if (inputStream.markSupported()) { // 1 megabyte is more than enough for even the largest manifest // file inputStream.mark(1024 * 1000); } JarInputStream jarInputStream = new JarInputStream(inputStream); Manifest manifest = jarInputStream.getManifest(); if (inputStream.markSupported()) { inputStream.reset(); } Attributes attributes = manifest.getMainAttributes(); String bundleSymbolicNameAttributeValue = attributes.getValue(Constants.BUNDLE_SYMBOLICNAME); Parameters parameters = OSGiHeader.parseHeader(bundleSymbolicNameAttributeValue); Set<String> bundleSymbolicNameSet = parameters.keySet(); Iterator<String> bundleSymbolicNameIterator = bundleSymbolicNameSet.iterator(); String bundleSymbolicName = bundleSymbolicNameIterator.next(); String bundleVersionAttributeValue = attributes.getValue(Constants.BUNDLE_VERSION); Version bundleVersion = Version.parseVersion(bundleVersionAttributeValue); for (Bundle bundle : bundleContext.getBundles()) { Version curBundleVersion = Version.parseVersion(String.valueOf(bundle.getVersion())); if (bundleSymbolicName.equals(bundle.getSymbolicName()) && bundleVersion.equals(curBundleVersion)) { return bundle; } } return null; } catch (IOException ioe) { throw new PortalException(ioe); } }
private String getConfigInfoFromManifest(String configType, IPath portalDir) { File implJar = portalDir.append("/WEB-INF/lib/portal-impl.jar").toFile(); String version = null; String serverInfo = null; if (implJar.exists()) { try (JarFile jar = new JarFile(implJar)) { Manifest manifest = jar.getManifest(); Attributes attributes = manifest.getMainAttributes(); version = attributes.getValue("Liferay-Portal-Version"); serverInfo = attributes.getValue("Liferay-Portal-Server-Info"); if (CoreUtil.compareVersions(Version.parseVersion(version), MANIFEST_VERSION_REQUIRED) < 0) { version = null; serverInfo = null; } } catch (IOException e) { LiferayServerCore.logError(e); } } if (configType.equals(CONFIG_TYPE_VERSION)) { return version; } if (configType.equals(CONFIG_TYPE_SERVER)) { return serverInfo; } return null; }
/** * Display package name and version information for javax.mail.internet. * * <p>This example is a bit artificial, since examining the version of a jar from Sun Microsystems * is unusual. * * @return _more_ * @throws IOException _more_ */ private static HashMap<String, String> getBuildInfo() throws IOException { GribVariableRenamer renamer = new GribVariableRenamer(); HashMap<String, String> buildInfo = new HashMap<String, String>(); Enumeration<URL> resources = renamer.getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); while (resources.hasMoreElements()) { try { Manifest manifest = new Manifest(resources.nextElement().openStream()); Attributes attrs = manifest.getMainAttributes(); if (attrs != null) { String implTitle = attrs.getValue("Implementation-Title"); if ((implTitle != null) && (implTitle.contains("ncIdv"))) { buildInfo.put("version", attrs.getValue("Implementation-Version")); String strDate = attrs.getValue("Built-On"); CalendarDate cd = CalendarDate.parseISOformat(null, strDate); buildInfo.put("buildDate", cd.toString()); break; } } } catch (IOException e) { e.printStackTrace(); } } return buildInfo; }
// assuming that application was packaged according to the rules // we must have application jar, i.e. jar where we embed launcher // and have main application class listed as main class! // If there are more than one, or none - it will be treated as deployment error // // Note we look for both JavaFX executable jars and regular executable jars // As long as main "application" entry point is the same it is main class // (i.e. for FX jar we will use JavaFX manifest entry ...) public String getMainApplicationJar() { if (mainJar != null) { return mainJar; } if (appResources == null || applicationClass == null) { return null; } File srcdir = appResources.getBaseDirectory(); for (String fname : appResources.getIncludedFiles()) { JarFile jf; try { jf = new JarFile(new File(srcdir, fname)); Manifest m = jf.getManifest(); Attributes attrs = (m != null) ? m.getMainAttributes() : null; if (attrs != null) { boolean javaMain = applicationClass.equals(attrs.getValue(Attributes.Name.MAIN_CLASS)); boolean fxMain = applicationClass.equals(attrs.getValue(PackagerLib.MANIFEST_JAVAFX_MAIN)); if (javaMain || fxMain) { useFXPackaging = fxMain; mainJar = fname; mainJarClassPath = attrs.getValue(Attributes.Name.CLASS_PATH); return mainJar; } } } catch (IOException ex) { } } return null; }
public void start() { vlog.debug("start called"); if (version == null || build == null) { ClassLoader cl = this.getClass().getClassLoader(); InputStream stream = cl.getResourceAsStream("com/tigervnc/vncviewer/timestamp"); try { Manifest manifest = new Manifest(stream); Attributes attributes = manifest.getMainAttributes(); version = attributes.getValue("Version"); build = attributes.getValue("Build"); } catch (java.io.IOException e) { } } nViewers++; if (firstApplet) { alwaysShowServerDialog.setParam(true); Configuration.readAppletParams(this); String host = getCodeBase().getHost(); if (vncServerName.getValue() == null && vncServerPort.getValue() != 0) { int port = vncServerPort.getValue(); vncServerName.setParam( host + ((port >= 5900 && port <= 5999) ? (":" + (port - 5900)) : ("::" + port))); } } thread = new Thread(this); thread.start(); }
static { final Enumeration<URL> resources; String jarName = "(unknown)"; String versionString = "(unknown)"; try { final ClassLoader classLoader = Main.class.getClassLoader(); resources = classLoader == null ? ModuleClassLoader.getSystemResources("META-INF/MANIFEST.MF") : classLoader.getResources("META-INF/MANIFEST.MF"); while (resources.hasMoreElements()) { final URL url = resources.nextElement(); try { final InputStream stream = url.openStream(); if (stream != null) try { final Manifest manifest = new Manifest(stream); final Attributes mainAttributes = manifest.getMainAttributes(); if (mainAttributes != null && "JBoss Modules".equals(mainAttributes.getValue("Specification-Title"))) { jarName = mainAttributes.getValue("Jar-Name"); versionString = mainAttributes.getValue("Jar-Version"); } } finally { StreamUtil.safeClose(stream); } } catch (IOException ignored) { } } } catch (IOException ignored) { } JAR_NAME = jarName; VERSION_STRING = versionString; }
public static String getVersion(ServletContext application) { String defaultVersion = ""; try { InputStream inputStream = application.getResourceAsStream("/META-INF/MANIFEST.MF"); Manifest manifest = new Manifest(inputStream); Attributes attributes = manifest.getMainAttributes(); String version = attributes.getValue("Application-Version"); String builtTime = attributes.getValue("HudsonBuildId"); String revision = attributes.getValue("HudsonBuildNumber"); if (version != null && version != "" && builtTime != null && builtTime != "" && revision != null && revision != "") { String versionTmp = ""; if (version.contains("SNAPSHOT")) { versionTmp = version.substring(0, version.indexOf("-")); } else { versionTmp = version; } return versionTmp + " Build " + builtTime.substring(0, 10) + " Rev:" + revision; } } catch (IOException e) { } return defaultVersion; }
/** Validate whether the jar file has a valid manifest, throw exception if invalid */ static void validateJarManifest(final Attributes mainAttributes) throws InvalidManifestException { final String value1 = mainAttributes.getValue(RUNDECK_PLUGIN_ARCHIVE); final String plugvers = mainAttributes.getValue(RUNDECK_PLUGIN_VERSION); final String plugclassnames = mainAttributes.getValue(RUNDECK_PLUGIN_CLASSNAMES); if (null == value1) { throw new InvalidManifestException( "Jar plugin manifest attribute missing: " + RUNDECK_PLUGIN_ARCHIVE); } else if (!"true".equals(value1)) { throw new InvalidManifestException(RUNDECK_PLUGIN_ARCHIVE + " was not 'true': " + value1); } if (null == plugvers) { throw new InvalidManifestException( "Jar plugin manifest attribute missing: " + RUNDECK_PLUGIN_VERSION); } final VersionCompare pluginVersion = VersionCompare.forString(plugvers); if (!pluginVersion.atLeast(LOWEST_JAR_PLUGIN_VERSION)) { throw new InvalidManifestException( "Unsupported plugin version: " + RUNDECK_PLUGIN_VERSION + ": " + plugvers); } if (null == plugclassnames) { throw new InvalidManifestException( "Jar plugin manifest attribute missing: " + RUNDECK_PLUGIN_CLASSNAMES); } }
BundleCapability(Attributes attrs) { super("bundle"); this.manifestVersion = attrs.getValue(Constants.BUNDLE_MANIFESTVERSION); this.presentationName = attrs.getValue(Constants.BUNDLE_NAME); this.symbolicName = attrs.getValue(Constants.BUNDLE_SYMBOLICNAME); this.version = attrs.getValue(Constants.BUNDLE_VERSION); }
// {{{ getMfValue() method private static String getMfValue( Attributes sectionAttrs, Attributes mainAttrs, Attributes.Name name) { String value = null; if (sectionAttrs != null) value = sectionAttrs.getValue(name); else if (mainAttrs != null) { value = mainAttrs.getValue(name); } return value; }
public static final Version find(final ClassLoader clz) { try { final Manifest mf = findManifest(clz, "jcurl-"); final Attributes main = mf.getMainAttributes(); return create(main.getValue("Bundle-Version"), main.getValue("Built-Time")); } catch (final Exception e) { return null; } }
/** * Extracts the version information data from the manifest's attributes and puts them into a * VersionInfo instance. * * @param manifest the manifest information * @return the version information from the manifest */ protected static VersionInfo createVersionInfo(Manifest manifest) { final VersionInfo versionInfo = new VersionInfo(); final Attributes mainAttributes = manifest.getMainAttributes(); versionInfo.setFromManifest(true); versionInfo.setProductID(mainAttributes.getValue("Implementation-ProductID")); // $NON-NLS-1$ versionInfo.setTitle(mainAttributes.getValue("Implementation-Title")); // $NON-NLS-1$ versionInfo.setVersion(mainAttributes.getValue("Implementation-Version")); // $NON-NLS-1$ return versionInfo; }
public JarInfo(String key, Attributes mainAttributes) { jar = key; if (null != mainAttributes.getValue(MANIFEST_VERSION)) { manifestVersion = String.valueOf(mainAttributes.getValue(MANIFEST_VERSION)); } if (null != mainAttributes.getValue(CREATED_BY)) { createdBy = String.valueOf(mainAttributes.getValue(CREATED_BY)); } }
private void fix(Attributes atts, List<PluginWrapper.Dependency> optionalDependencies) { // don't fix the dependency for yourself, or else we'll have a cycle String yourName = atts.getValue("Short-Name"); if (shortName.equals(yourName)) return; // some earlier versions of maven-hpi-plugin apparently puts "null" as a literal in Hudson-Version. watch out for them. String jenkinsVersion = atts.getValue("Jenkins-Version"); if (jenkinsVersion==null) jenkinsVersion = atts.getValue("Hudson-Version"); if (jenkinsVersion == null || jenkinsVersion.equals("null") || new VersionNumber(jenkinsVersion).compareTo(splitWhen) <= 0) optionalDependencies.add(new PluginWrapper.Dependency(shortName+':'+requireVersion)); }
/** @param attrs */ private void setBuildJdk(Attributes attrs) { String buildJdk = attrs.getValue("Build-Jdk"); if (buildJdk != null) { _buildJdk = buildJdk; } else { buildJdk = attrs.getValue("Created-By"); if (buildJdk != null) { _buildJdk = buildJdk; } else { _buildJdk = "-1"; } } }
private String getAttribute( Attributes.Name name, Attributes packageAttributes, Attributes mainAttributes) { if (packageAttributes != null) { String value = packageAttributes.getValue(name); if (value != null) { return value; } } if (mainAttributes != null) { return mainAttributes.getValue(name); } return null; }
/* * Returns true if the specified package name is sealed according to the * given manifest. */ private boolean _isSealed(String name, Manifest man) { String path = name.replace('.', '/').concat("/"); Attributes attr = man.getAttributes(path); String sealed = null; if (attr != null) { sealed = attr.getValue(Attributes.Name.SEALED); } if (sealed == null) { if ((attr = man.getMainAttributes()) != null) { sealed = attr.getValue(Attributes.Name.SEALED); } } return "true".equalsIgnoreCase(sealed); }
/** * Get OAR attributes from the Manifest * * @param manifest A Manifest to the oar * @throws OARException If the manifest cannot be read * @throws IllegalArgumentException If the manifest is null */ private void getManifestAttributes(Manifest manifest) throws OARException { if (manifest == null) throw new IllegalArgumentException("manifest cannot be null"); Attributes attrs = manifest.getMainAttributes(); if (attrs == null) throw new OARException("Unable to process the OAR, " + "it has no manifest attributes"); name = attrs.getValue(OAR_NAME); if (name == null) fillInAndThrow(OAR_NAME); version = attrs.getValue(OAR_VERSION); opStringName = attrs.getValue(OAR_OPSTRING); if (opStringName == null) fillInAndThrow(OAR_OPSTRING); activationType = attrs.getValue(OAR_ACTIVATION); if (activationType == null) fillInAndThrow(OAR_ACTIVATION); artifacts = attrs.getValue(OAR_ARTIFACTS); }
/* * Check for all declared required extensions in the jar file * manifest. */ protected boolean checkExtensions(JarFile jar) throws ExtensionInstallationException { Manifest man; try { man = jar.getManifest(); } catch (IOException e) { return false; } if (man == null) { // The applet does not define a manifest file, so // we just assume all dependencies are satisfied. return true; } boolean result = true; Attributes attr = man.getMainAttributes(); if (attr != null) { // Let's get the list of declared dependencies String value = attr.getValue(Name.EXTENSION_LIST); if (value != null) { StringTokenizer st = new StringTokenizer(value); // Iterate over all declared dependencies while (st.hasMoreTokens()) { String extensionName = st.nextToken(); debug("The file " + jar.getName() + " appears to depend on " + extensionName); // Sanity Check String extName = extensionName + "-" + Name.EXTENSION_NAME.toString(); if (attr.getValue(extName) == null) { debug( "The jar file " + jar.getName() + " appers to depend on " + extensionName + " but does not define the " + extName + " attribute in its manifest "); } else { if (!checkExtension(extensionName, attr)) { debug("Failed installing " + extensionName); result = false; } } } } else { debug("No dependencies for " + jar.getName()); } } return result; }
private void readManifestInfo() { try { Attributes attributes = Path.manifest().getMainAttributes(); String versionString = attributes.getValue("Bundle-Version"); String progNameString = attributes.getValue("Bundle-Name"); ProgramName programName = progNameString.equals("Umlet") ? ProgramName.UMLET : ProgramName.PLOTLET; Program.init(programName, versionString); } catch (Exception e) { // log.error(null, e); e.printStackTrace(); // Logger is not initialized here } }
public static void indexTargetPlatform( OutputStream outputStream, List<File> additionalJarFiles, long stopWaitTimeout, String... dirNames) throws Exception { Framework framework = null; Path tempPath = Files.createTempDirectory(null); ClassLoader classLoader = TargetPlatformIndexerUtil.class.getClassLoader(); try (InputStream inputStream = classLoader.getResourceAsStream("META-INF/system.packages.extra.mf")) { Map<String, String> properties = new HashMap<>(); properties.put(Constants.FRAMEWORK_STORAGE, tempPath.toString()); Manifest extraPackagesManifest = new Manifest(inputStream); Attributes attributes = extraPackagesManifest.getMainAttributes(); properties.put( Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, attributes.getValue("Export-Package")); ServiceLoader<FrameworkFactory> serviceLoader = ServiceLoader.load(FrameworkFactory.class); FrameworkFactory frameworkFactory = serviceLoader.iterator().next(); framework = frameworkFactory.newFramework(properties); framework.init(); BundleContext bundleContext = framework.getBundleContext(); Bundle systemBundle = bundleContext.getBundle(0); TargetPlatformIndexer targetPlatformIndexer = new TargetPlatformIndexer(systemBundle, additionalJarFiles, dirNames); targetPlatformIndexer.index(outputStream); } finally { framework.stop(); FrameworkEvent frameworkEvent = framework.waitForStop(stopWaitTimeout); if (frameworkEvent.getType() == FrameworkEvent.WAIT_TIMEDOUT) { throw new Exception( "OSGi framework event " + frameworkEvent + " triggered after a " + stopWaitTimeout + "ms timeout"); } PathUtil.deltree(tempPath); } }
/** * Creates the classloader that can load all the specified jar files and delegate to the given parent. */ protected ClassLoader createClassLoader(List<File> paths, ClassLoader parent, Attributes atts) throws IOException { if (atts != null) { String usePluginFirstClassLoader = atts.getValue( "PluginFirstClassLoader" ); if (Boolean.valueOf( usePluginFirstClassLoader )) { PluginFirstClassLoader classLoader = new PluginFirstClassLoader(); classLoader.setParentFirst( false ); classLoader.setParent( parent ); classLoader.addPathFiles( paths ); return classLoader; } } if(useAntClassLoader) { // using AntClassLoader with Closeable so that we can predictably release jar files opened by URLClassLoader AntClassLoader2 classLoader = new AntClassLoader2(parent); classLoader.addPathFiles(paths); return classLoader; } else { // Tom reported that AntClassLoader has a performance issue when Hudson keeps trying to load a class that doesn't exist, // so providing a legacy URLClassLoader support, too List<URL> urls = new ArrayList<URL>(); for (File path : paths) urls.add(path.toURI().toURL()); return new URLClassLoader(urls.toArray(new URL[urls.size()]),parent); } }
@SuppressWarnings("resource") private InitStep loadInitStep(Path jar) { try { URLClassLoader pluginLoader = new URLClassLoader( new URL[] {jar.toUri().toURL()}, InitPluginStepsLoader.class.getClassLoader()); try (JarFile jarFile = new JarFile(jar.toFile())) { Attributes jarFileAttributes = jarFile.getManifest().getMainAttributes(); String initClassName = jarFileAttributes.getValue("Gerrit-InitStep"); if (initClassName == null) { return null; } @SuppressWarnings("unchecked") Class<? extends InitStep> initStepClass = (Class<? extends InitStep>) pluginLoader.loadClass(initClassName); return getPluginInjector(jar).getInstance(initStepClass); } catch (ClassCastException e) { ui.message( "WARN: InitStep from plugin %s does not implement %s (Exception: %s)\n", jar.getFileName(), InitStep.class.getName(), e.getMessage()); return null; } catch (NoClassDefFoundError e) { ui.message( "WARN: Failed to run InitStep from plugin %s (Missing class: %s)\n", jar.getFileName(), e.getMessage()); return null; } } catch (Exception e) { ui.message( "WARN: Cannot load and get plugin init step for %s (Exception: %s)\n", jar, e.getMessage()); return null; } }
/** * Writes out the attribute information of the specified manifest to the specified {@code * OutputStream} * * @param manifest the manifest to write out. * @param out The {@code OutputStream} to write to. * @throws IOException If an error occurs writing the {@code Manifest}. */ static void write(Manifest manifest, OutputStream out) throws IOException { CharsetEncoder encoder = ThreadLocalCache.utf8Encoder.get(); ByteBuffer buffer = ThreadLocalCache.byteBuffer.get(); String version = manifest.mainAttributes.getValue(Attributes.Name.MANIFEST_VERSION); if (version != null) { writeEntry(out, Attributes.Name.MANIFEST_VERSION, version, encoder, buffer); Iterator<?> entries = manifest.mainAttributes.keySet().iterator(); while (entries.hasNext()) { Attributes.Name name = (Attributes.Name) entries.next(); if (!name.equals(Attributes.Name.MANIFEST_VERSION)) { writeEntry(out, name, manifest.mainAttributes.getValue(name), encoder, buffer); } } } out.write(LINE_SEPARATOR); Iterator<String> i = manifest.getEntries().keySet().iterator(); while (i.hasNext()) { String key = i.next(); writeEntry(out, NAME_ATTRIBUTE, key, encoder, buffer); Attributes attrib = manifest.entries.get(key); Iterator<?> entries = attrib.keySet().iterator(); while (entries.hasNext()) { Attributes.Name name = (Attributes.Name) entries.next(); writeEntry(out, name, attrib.getValue(name), encoder, buffer); } out.write(LINE_SEPARATOR); } }
/** * Gets the build teimstamp from the jar manifest * * @return build timestamp */ private static String getManifestBuildTimestamp() { JarURLConnection connection = null; JarFile jarFile = null; URL url = Commons.class.getClassLoader().getResource("jaligner"); try { // Get jar connection connection = (JarURLConnection) url.openConnection(); // Get the jar file jarFile = connection.getJarFile(); // Get the manifest Manifest manifest = jarFile.getManifest(); // Get the manifest entries Attributes attributes = manifest.getMainAttributes(); Attributes.Name name = new Attributes.Name(BUILD_TIMESTAMP); return attributes.getValue(name); } catch (Exception e) { String message = "Failed getting the current release info: " + e.getMessage(); logger.log(Level.WARNING, message); } return null; }
@Override public String getVersion() { Class<BricketApplication> clazz = BricketApplication.class; String classPath = clazz.getResource(clazz.getSimpleName() + ".class").toString(); if (!classPath.startsWith("jar")) { // class not from JAR return UNKNOWN_VERSION; } try { String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF"; Manifest manifest = new Manifest(new URL(manifestPath).openStream()); Attributes attr = manifest.getMainAttributes(); String version = attr.getValue(Name.IMPLEMENTATION_VERSION); return version != null ? version : UNKNOWN_VERSION; } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return UNKNOWN_VERSION; }
/** * Returns the manifest of the jar which contains one of the specified extensions. The provided * ClassLoader is used for resource loading. * * @param cl A ClassLoader which should find the manifest. * @param extensions The values of many 'Extension-Name's jar-manifest attribute; used to identify * the manifest. Matching is applied in decreasing order, i.e. first element is favored over * the second, etc. * @return the requested manifest or null when not found. */ public static Manifest getManifest(ClassLoader cl, String[] extensions) { final Manifest[] extManifests = new Manifest[extensions.length]; try { Enumeration<URL> resources = cl.getResources("META-INF/MANIFEST.MF"); while (resources.hasMoreElements()) { final InputStream is = resources.nextElement().openStream(); final Manifest manifest; try { manifest = new Manifest(is); } finally { IOUtil.close(is, false); } Attributes attributes = manifest.getMainAttributes(); if (attributes != null) { for (int i = 0; i < extensions.length && null == extManifests[i]; i++) { final String extension = extensions[i]; if (extension.equals(attributes.getValue(Attributes.Name.EXTENSION_NAME))) { if (0 == i) { return manifest; // 1st one has highest prio - done } extManifests[i] = manifest; } } } } } catch (IOException ex) { throw new RuntimeException("Unable to read manifest.", ex); } for (int i = 1; i < extManifests.length; i++) { if (null != extManifests[i]) { return extManifests[i]; } } return null; }
@Nullable public static String getMainClassName(URL url) throws IOException { @NotNull URL u = new URL("jar", "", url + "!/"); @NotNull JarURLConnection uc = (JarURLConnection) u.openConnection(); Attributes attr = uc.getMainAttributes(); return (attr != null) ? attr.getValue(Attributes.Name.MAIN_CLASS) : null; }
/** * Extract the dependent libs and return the extracted jar files * * @return the collection of extracted files */ private Collection<File> extractDependentLibs(final File cachedir) throws IOException { final Attributes attributes = getMainAttributes(); if (null == attributes) { debug("no manifest attributes"); return null; } final ArrayList<File> files = new ArrayList<File>(); final String libs = attributes.getValue(RUNDECK_PLUGIN_LIBS); if (null != libs) { debug("jar libs listed: " + libs + " for file: " + pluginJar); if (!cachedir.isDirectory()) { if (!cachedir.mkdirs()) { debug("Failed to create cachedJar dir for dependent libs: " + cachedir); } } final String[] libsarr = libs.split(" "); extractJarContents(libsarr, cachedir); for (final String s : libsarr) { File libFile = new File(cachedir, s); libFile.deleteOnExit(); files.add(libFile); } } else { debug("no jar libs listed in manifest: " + pluginJar); } return files; }
void printAttrib(PrintStream out, String tag, String key) { String val = attribs.getValue(key); if (val == null) { val = ""; } out.println(" <" + tag + ">" + val + "</" + tag + ">"); }