def buildLarchJar(outputStream,
                  additionalFilesAsNameBytesPairs,
                  filterFn=None,
                  larchJarURL=None):
    """
	Build a JAR from an existing Larch JAR, along with additional files to make a packaged program

	:param outputStream: The output stream to which the JAR is to be written
	:param additionalFilesAsNameBytesPairs: Additional files in the form of a sequence of tuples consisting of (path, bytes)
	:param filterFn: (optional) A filter function that can be used to exclude files from the existing Larch JAR; takes the form of function(name) -> boolean, should return True if file should be included
	:param larchJarURL: (optional) A URL at which the existing Larch JAR can be obtained. If None, it will use the JAR from which Larch was started. Raises an error if no URL provided and Larch was not started from a JAR
	"""
    if larchJarURL is None:
        larchJarURL = _larchJarURL

    if larchJarURL is None:
        raise RuntimeError, 'Larch was not loaded from a JAR file and no Larch JAR file was provided'

    jarIn = JarInputStream(larchJarURL.openStream())

    manifestIn = jarIn.getManifest()
    manifestOut = Manifest(manifestIn)

    jarOut = JarOutputStream(outputStream, manifestOut)

    bytesBuffer = jarray.zeros(_BYTES_BUFFER_SIZE, 'b')

    entryIn = jarIn.getNextJarEntry()
    while entryIn is not None:
        name = entryIn.getName()

        if filterFn is None or filterFn(name):
            bufferStream = ByteArrayOutputStream()
            while True:
                bytesRead = jarIn.read(bytesBuffer, 0, _BYTES_BUFFER_SIZE)
                if bytesRead == -1:
                    break
                bufferStream.write(bytesBuffer, 0, bytesRead)

            entryOut = ZipEntry(name)
            entryOut.setSize(bufferStream.size())
            jarOut.putNextEntry(entryOut)
            bufferStream.writeTo(jarOut)
            jarOut.closeEntry()

        entryIn = jarIn.getNextJarEntry()

    for name, bytes in additionalFilesAsNameBytesPairs:
        size = len(bytes)
        entryOut = ZipEntry(name)
        entryOut.setSize(size)
        jarOut.putNextEntry(entryOut)
        jarOut.write(bytes, 0, size)
        jarOut.closeEntry()

    jarOut.finish()
Ejemplo n.º 2
0
    def generate(self, xmldata, output_type='pdf', sign_keyname=None, sign_reason=None, metadata=None):
        """Generate Output with JasperReports."""
        start = time.time()
        xmldata_utf8 = xmldata.encode('utf-8')
        xmlpath = os.path.join(TMPDIR, 'xml')
        outputpath = os.path.join(TMPDIR, 'output')
        oid = "%s-%s" % (hashlib.md5(xmldata_utf8).hexdigest(), uuid.uuid1())
        ensure_dirs([xmlpath, outputpath])
        xmlfile = os.path.join(xmlpath, oid + '.xml')
        fdesc = open(xmlfile, 'w')
        fdesc.write(xmldata_utf8)
        fdesc.close()

        output_filename = os.path.abspath(os.path.join(outputpath, oid + '.' + output_type))
        datasource = JRXmlDataSource(xmlfile, self.xpath)

        # convert to a java.util.Map so it can be passed as parameters
        map = JMap()
        for i in self.compiled_design:
            map[i] = self.compiled_design[i]

        # add the original xml document source so subreports can make a new datasource.
        map['XML_FILE'] = xmlfile

        jasper_print = JasperFillManager.fillReport(self.compiled_design['main'], map, datasource)

        if output_type == 'pdf':
            # Get PDF content from JasperReports
            stream = ByteArrayOutputStream()
            JasperExportManager.exportReportToPdfStream(jasper_print, stream)

            # Add metadata
            if metadata:
                try:
                    inputstream = ByteArrayInputStream(stream.toByteArray())
                    stream = self.addMetadata(inputstream, metadata)
                except:
                    raise

            # Try to sign the PDF file if a keyname is given
            if sign_keyname:
                try:
                    inputstream = ByteArrayInputStream(stream.toByteArray())
                    stream = self.sign(inputstream, sign_keyname, sign_reason)
                except ValueError:
                    raise

            # Write PDF to output file
            output_file = open(output_filename, 'wb')
            stream.writeTo(output_file)
            output_file.close()

        elif output_type == 'xml':
            output_file = open(output_filename, 'w')
            JasperExportManager.exportReportToXmlStream(jasper_print, output_file)
            output_file.close()
        elif output_type == 'rtf':
            self.generate_rtf(jasper_print, output_filename)
        elif output_type == 'xls':
            self._generate_xls(jasper_print, output_filename)
        elif output_type == 'csv':
            self._generate_csv(jasper_print, output_filename)
        elif output_type == 'text':
            self._generate_text(jasper_print, output_filename)
        elif output_type == 'html':
            self._generate_html(jasper_print, output_filename)
        else:
            raise RuntimeError("Unknown output type %r" % (output_type))
        delta = time.time() - start
        sys.stderr.write('report %r generated in %.3f seconds\n' % (output_filename, delta))
        return open(output_filename, 'rb').read()