def safe_classpath(classpath, synthetic_jar_dir): """Bundles classpath into one synthetic jar that includes original classpath in its manifest. This is to ensure classpath length never exceeds platform ARG_MAX. :param list classpath: Classpath to be bundled. :param string synthetic_jar_dir: directory to store the synthetic jar, if `None` a temp directory will be provided and cleaned up upon process exit. Otherwise synthetic jar will remain in the supplied directory, only for debugging purpose. :returns: A classpath (singleton list with just the synthetic jar). :rtype: list of strings """ if synthetic_jar_dir: safe_mkdir(synthetic_jar_dir) else: synthetic_jar_dir = safe_mkdtemp() bundled_classpath = relativize_classpath(classpath, synthetic_jar_dir) manifest = Manifest() manifest.addentry(Manifest.CLASS_PATH, ' '.join(bundled_classpath)) with temporary_file(root_dir=synthetic_jar_dir, cleanup=False, suffix='.jar') as jar_file: with open_zip(jar_file, mode='w', compression=ZIP_STORED) as jar: jar.writestr(Manifest.PATH, manifest.contents()) return [jar_file.name]
def bundled_classpath(classpath): """Bundles classpath into one synthetic jar that includes original classpath in its manifest. See https://docs.oracle.com/javase/7/docs/technotes/guides/extensions/spec.html#bundled :param list classpath: Classpath to be bundled. :returns: A classpath (singleton list with just the synthetic jar). :rtype: list of strings """ def prepare_url(url): url_in_bundle = os.path.realpath(url) # append '/' for directories, those not ending with '/' are assumed to be jars if os.path.isdir(url): url_in_bundle += '/' return url_in_bundle bundled_classpath = [prepare_url(url) for url in classpath] manifest = Manifest() manifest.addentry(Manifest.CLASS_PATH, ' '.join(bundled_classpath)) with temporary_file(cleanup=False, suffix='.jar') as jar_file: with open_zip(jar_file, mode='w', compression=ZIP_STORED) as jar: jar.writestr(Manifest.PATH, manifest.contents()) yield [jar_file.name]
def safe_classpath(classpath, synthetic_jar_dir, custom_name=None): """Bundles classpath into one synthetic jar that includes original classpath in its manifest. This is to ensure classpath length never exceeds platform ARG_MAX. :param list classpath: Classpath to be bundled. :param string synthetic_jar_dir: directory to store the synthetic jar, if `None` a temp directory will be provided and cleaned up upon process exit. Otherwise synthetic jar will remain in the supplied directory, only for debugging purpose. :param custom_name: filename of the synthetic jar to be created. :returns: A classpath (singleton list with just the synthetic jar). :rtype: list of strings """ if synthetic_jar_dir: safe_mkdir(synthetic_jar_dir) else: synthetic_jar_dir = safe_mkdtemp() # Quote the paths so that if they contain reserved characters can be safely passed to JVM classloader. bundled_classpath = map(urllib.quote, relativize_classpath(classpath, synthetic_jar_dir)) manifest = Manifest() manifest.addentry(Manifest.CLASS_PATH, ' '.join(bundled_classpath)) with temporary_file(root_dir=synthetic_jar_dir, cleanup=False, suffix='.jar') as jar_file: with open_zip(jar_file, mode='w', compression=ZIP_STORED) as jar: jar.writestr(Manifest.PATH, manifest.contents()) if custom_name: custom_path = os.path.join(synthetic_jar_dir, custom_name) safe_concurrent_rename(jar_file.name, custom_path) return [custom_path] else: return [jar_file.name]
def safe_classpath(classpath, synthetic_jar_dir, custom_name=None): """Bundles classpath into one synthetic jar that includes original classpath in its manifest. This is to ensure classpath length never exceeds platform ARG_MAX. :param list classpath: Classpath to be bundled. :param string synthetic_jar_dir: directory to store the synthetic jar, if `None` a temp directory will be provided and cleaned up upon process exit. Otherwise synthetic jar will remain in the supplied directory, only for debugging purpose. :param custom_name: filename of the synthetic jar to be created. :returns: A classpath (singleton list with just the synthetic jar). :rtype: list of strings """ if synthetic_jar_dir: safe_mkdir(synthetic_jar_dir) else: synthetic_jar_dir = safe_mkdtemp() # Quote the paths so that if they contain reserved characters can be safely passed to JVM classloader. bundled_classpath = [parse.quote(cp) for cp in relativize_classpath(classpath, synthetic_jar_dir)] manifest = Manifest() manifest.addentry(Manifest.CLASS_PATH, ' '.join(bundled_classpath)) with temporary_file(root_dir=synthetic_jar_dir, cleanup=False, suffix='.jar') as jar_file: with open_zip(jar_file, mode='w', compression=ZIP_STORED) as jar: jar.writestr(Manifest.PATH, manifest.contents()) if custom_name: custom_path = os.path.join(synthetic_jar_dir, custom_name) safe_concurrent_rename(jar_file.name, custom_path) return [custom_path] else: return [jar_file.name]
def safe_classpath(classpath, synthetic_jar_dir): """Bundles classpath into one synthetic jar that includes original classpath in its manifest. This is to ensure classpath length never exceeds platform ARG_MAX. Original classpath are converted to URLs relative to synthetic jar path and saved in its manifest as attribute `Class-Path`. See https://docs.oracle.com/javase/7/docs/technotes/guides/extensions/spec.html#bundled :param list classpath: Classpath to be bundled. :param string synthetic_jar_dir: directory to store the synthetic jar, if `None` a temp directory will be provided and cleaned up upon process exit. Otherwise synthetic jar will remain in the supplied directory, only for debugging purpose. :returns: A classpath (singleton list with just the synthetic jar). :rtype: list of strings """ def prepare_url(url, root_dir): url_in_bundle = os.path.relpath(os.path.realpath(url), os.path.realpath(root_dir)) # append '/' for directories, those not ending with '/' are assumed to be jars if os.path.isdir(url): url_in_bundle += '/' return url_in_bundle if synthetic_jar_dir: safe_mkdir(synthetic_jar_dir) else: synthetic_jar_dir = safe_mkdtemp() bundled_classpath = [prepare_url(url, synthetic_jar_dir) for url in classpath] manifest = Manifest() manifest.addentry(Manifest.CLASS_PATH, ' '.join(bundled_classpath)) with temporary_file(root_dir=synthetic_jar_dir, cleanup=False, suffix='.jar') as jar_file: with open_zip(jar_file, mode='w', compression=ZIP_STORED) as jar: jar.writestr(Manifest.PATH, manifest.contents()) return [jar_file.name]
def test_isempty(self): manifest = Manifest() self.assertTrue(manifest.is_empty()) manifest.addentry('Header', 'value') self.assertFalse(manifest.is_empty())
def test_too_long_entry(self): manifest = Manifest() with self.assertRaises(ValueError): manifest.addentry( '1234567890123456789012345678901234567890' '12345678901234567890123456789', 'value')
def test_addentry(self): manifest = Manifest() manifest.addentry('Header', 'value') self.assertEqual(b'Header: value\n', manifest.contents())
def _write_agent_manifest(agent, jar): # TODO(John Sirois): refactor an agent model to support 'Boot-Class-Path' properly. manifest = Manifest() manifest.addentry(Manifest.MANIFEST_VERSION, '1.0') if agent.premain: manifest.addentry('Premain-Class', agent.premain) if agent.agent_class: manifest.addentry('Agent-Class', agent.agent_class) if agent.can_redefine: manifest.addentry('Can-Redefine-Classes', 'true') if agent.can_retransform: manifest.addentry('Can-Retransform-Classes', 'true') if agent.can_set_native_method_prefix: manifest.addentry('Can-Set-Native-Method-Prefix', 'true') jar.writestr(Manifest.PATH, manifest.contents())
def test_nonascii_char(self): manifest = Manifest() with self.assertRaises(UnicodeEncodeError): manifest.addentry("X-Copyright", "© 2015")
def test_addentry(self): manifest = Manifest() manifest.addentry('Header', 'value') self.assertEquals( 'Header: value\n', manifest.contents())
def write_agent_manifest(self, agent, jarfile): # TODO(John Sirois): refactor an agent model to suport 'Boot-Class-Path' properly. manifest = Manifest() manifest.addentry(Manifest.MANIFEST_VERSION, '1.0') if agent.premain: manifest.addentry('Premain-Class', agent.premain) if agent.agent_class: manifest.addentry('Agent-Class', agent.agent_class) if agent.can_redefine: manifest.addentry('Can-Redefine-Classes', 'true') if agent.can_retransform: manifest.addentry('Can-Retransform-Classes', 'true') if agent.can_set_native_method_prefix: manifest.addentry('Can-Set-Native-Method-Prefix', 'true') jarfile.writestr(Manifest.PATH, manifest.contents())
def test_addentry(self): manifest = Manifest() manifest.addentry("Header", "value") self.assertEqual(b"Header: value\n", manifest.contents())
def test_too_long_entry(self): manifest = Manifest() with self.assertRaises(ValueError): manifest.addentry( "1234567890123456789012345678901234567890" "12345678901234567890123456789", "value")
def test_isempty(self): manifest = Manifest() self.assertTrue(manifest.is_empty()) manifest.addentry("Header", "value") self.assertFalse(manifest.is_empty())
def test_nonascii_char(self): manifest = Manifest() with self.assertRaises(UnicodeEncodeError): manifest.addentry('X-Copyright', '© 2015')