text:
package hostport

import (
	"testing"

	mesos "github.com/mesos/mesos-go/mesosproto"
	"github.com/mesos/mesos-go/mesosutil"
	"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/resources"
	"k8s.io/kubernetes/pkg/api"
)

func TestDefaultHostPortMatching(t *testing.T) {
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "foo",
			Namespace: "default",
		},
	}

	offer := &mesos.Offer{
		Resources: []*mesos.Resource{
			resources.NewPorts("*", 1, 1),
		},
	}
	mapping, err := FixedMapper(pod, []string{"*"}, offer)
	if err != nil {
		t.Fatal(err)
	}
	if len(mapping) > 0 {
		t.Fatalf("Found mappings for a pod without ports: %v", pod)
	}

	//--
	pod.Spec = api.PodSpec{
		Containers: []api.Container{{
			Ports: []api.ContainerPort{{
				HostPort: 123,
			}, {
				HostPort: 123,
			}},
		}},
	}
	_, err = FixedMapper(pod, []string{"*"}, offer)
	if err, _ := err.(*DuplicateError); err == nil {
		t.Fatal("Expected duplicate port error")
	} else if err.m1.OfferPort != 123 {
		t.Fatal("Expected duplicate host port 123")
	}
}

func TestWildcardHostPortMatching(t *testing.T) {
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "foo",
			Namespace: "default",
		},
	}

	offer := &mesos.Offer{}
	mapping, err := WildcardMapper(pod, []string{"*"}, offer)
	if err != nil {
		t.Fatal(err)
	}
	if len(mapping) > 0 {
		t.Fatalf("Found mappings for an empty offer and a pod without ports: %v", pod)
	}

	//--
	offer = &mesos.Offer{
		Resources: []*mesos.Resource{
			resources.NewPorts("*", 1, 1),
		},
	}
	mapping, err = WildcardMapper(pod, []string{"*"}, offer)
	if err != nil {
		t.Fatal(err)
	}
	if len(mapping) > 0 {
		t.Fatalf("Found mappings for a pod without ports: %v", pod)
	}

	//--
	pod.Spec = api.PodSpec{
		Containers: []api.Container{{
			Ports: []api.ContainerPort{{
				HostPort: 123,
			}},
		}},
	}
	mapping, err = WildcardMapper(pod, []string{"*"}, offer)
	if err == nil {
		t.Fatalf("expected error instead of mappings: %#v", mapping)
	} else if err, _ := err.(*PortAllocationError); err == nil {
		t.Fatal("Expected port allocation error")
	} else if !(len(err.Ports) == 1 && err.Ports[0] == 123) {
		t.Fatal("Expected port allocation error for host port 123")
	}

	//--
	pod.Spec = api.PodSpec{
		Containers: []api.Container{{
			Ports: []api.ContainerPort{{
				HostPort: 0,
			}, {
				HostPort: 123,
			}},
		}},
	}
	mapping, err = WildcardMapper(pod, []string{"*"}, offer)
	if err, _ := err.(*PortAllocationError); err == nil {
		t.Fatal("Expected port allocation error")
	} else if !(len(err.Ports) == 1 && err.Ports[0] == 123) {
		t.Fatal("Expected port allocation error for host port 123")
	}

	//--
	pod.Spec = api.PodSpec{
		Containers: []api.Container{{
			Ports: []api.ContainerPort{{
				HostPort: 0,
			}, {
				HostPort: 1,
			}},
		}},
	}
	mapping, err = WildcardMapper(pod, []string{"*"}, offer)
	if err, _ := err.(*PortAllocationError); err == nil {
		t.Fatal("Expected port allocation error")
	} else if len(err.Ports) != 0 {
		t.Fatal("Expected port allocation error for wildcard port")
	}

	//--
	offer = &mesos.Offer{
		Resources: []*mesos.Resource{
			resources.NewPorts("*", 1, 2),
		},
	}
	mapping, err = WildcardMapper(pod, []string{"*"}, offer)
	if err != nil {
		t.Fatal(err)
	} else if len(mapping) != 2 {
		t.Fatal("Expected both ports allocated")
	}
	valid := 0
	for _, entry := range mapping {
		if entry.ContainerIdx == 0 && entry.PortIdx == 0 && entry.OfferPort == 2 {
			valid++
		}
		if entry.ContainerIdx == 0 && entry.PortIdx == 1 && entry.OfferPort == 1 {
			valid++
		}
	}
	if valid < 2 {
		t.Fatalf("Expected 2 valid port mappings, not %d", valid)
	}

	//-- port mapping in case of multiple discontinuous port ranges in mesos offer
	pod.Spec = api.PodSpec{
		Containers: []api.Container{{
			Ports: []api.ContainerPort{{
				HostPort: 0,
			}, {
				HostPort: 0,
			}},
		}},
	}
	offer = &mesos.Offer{
		Resources: []*mesos.Resource{
			mesosutil.NewRangesResource("ports", []*mesos.Value_Range{mesosutil.NewValueRange(1, 1), mesosutil.NewValueRange(3, 5)}),
		},
	}
	mapping, err = WildcardMapper(pod, []string{"*"}, offer)
	if err != nil {
		t.Fatal(err)
	} else if len(mapping) != 2 {
		t.Fatal("Expected both ports allocated")
	}
	valid = 0
	for _, entry := range mapping {
		if entry.ContainerIdx == 0 && entry.PortIdx == 0 && entry.OfferPort == 1 {
			valid++
		}
		if entry.ContainerIdx == 0 && entry.PortIdx == 1 && entry.OfferPort == 3 {
			valid++
		}
	}
	if valid < 2 {
		t.Fatalf("Expected 2 valid port mappings, not %d", valid)
	}
}


text:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class GoogleHandler extends CI_Controller
{
	function __construct()
	{
		parent::__construct();

		$this->load->library('lc');
		$this->load->library('g_cal');
		$this->load->library('session');

		$this->userDatabase = null;

		// _show($_COOKIE, 1);

		$url = PROTOCOL_STRING.$_COOKIE['subdomain'].'.'.FULL_DOMAIN_NAME;
		//$url = 'http://local.devleadclock.com';

		// _show($_SERVER);
		// _show($_SESSION);

		// echo '
';
		// echo 'URL from cookie: '.$url;
		// die();

		// $this->g_cal->check_in();

	    header("Access-Control-Allow-Origin: ".$url);
	    header("Access-Control-Allow-Credentials: true");
	    header("Access-Control-Allow-Headers: X-Requested-With");

	    // --- todo: should remove all access to the g_cal library in this controller and put it all into event model?

	}

	function index(){

	}

	private function check_for_google_redirect(){
		$g_cal = $this->g_cal->check_in();
		$j_g_cal = json_decode($g_cal);
		// _show($j_g_cal, 1);
		if (!empty($j_g_cal->redirect)) {
			echo $g_cal;
			die();
		}
	}

	private function set_account_db($databaseName){
		$this->userDatabase = $databaseName;
	}

	private function test_account_credentials($cook){
		//debug_print_backtrace();
		// echo 'this is where the problem is';
		// _show($cook);
		// echo 'not sending cookies here';
		// die();
		$ret = false;
		$error = '';
		if (empty($cook['subdomain'])) {
			$error = '
Error. Cookie did not send subdomain.
';
			//throw new Exception("Error. Cookie did not send subdomain.", 1);

		}
		if (empty($cook['api_key'])) {
			$error = '
Error. Account does not have an API key. If this is your first time setting up, you must go to "Settings->Generate API Key"
';
			//throw new Exception('Error. Account does not have an API key. If this is your first time setting up, you must go to "Settings->Generate API Key', 1);

		}
		if (!empty($error)) {
			// echo $error;
			_ajax_json(array('failure' => true, 'error' => $error));
			return false;
		}
		else {
			$accountName = $cook['subdomain'];
			$api_key = $cook['api_key'];

			$CI =& get_instance();

			$globaldb = $CI->load->database('global', true);
			$globaldb->select('accountDBName');
			$globaldb->where('accountURL', $accountName);
			$q = $globaldb->get('accounts');
			$a = $q->result();

			if (!empty($a[0]->accountDBName)) {
				$accountDBName = $a[0]->accountDBName;
				$CI->db->db_select($accountDBName);
				$CI->load->model('APIKey');

				$ret = $CI->APIKey->check($api_key);

				if (!$ret) {
					//$error .= 'Error. Account API Key has been revoked. Please generate a new API key.';
					throw new Exception('Error. Account API Key has been revoked. Please generate a new API key.', 1);

				}
			}
		}
		// if (!empty($error)) {
		// 	_ajax_json(array('failure' => true, 'error' => $error));
		// }
		// else {
		// 	_ajax_json(array('success' => true));
		// }
		return $ret;
	}

	/*function test_gcal_callback(){

		$cookie = $this->input->cookie();

		if($this->test_account_credentials($cookie)){
			echo 'success! account and api_key are valid!';
			echo '
Click here to do the callback uri thing';
		}
	}*/

	function list_all_gcal_calendars(){
		$cookie = $this->input->cookie();
		if($this->test_account_credentials($cookie)){
			$this->check_for_google_redirect();
			$calendarList     = $this->g_cal->list_all_calendars();
			$res = array();
			foreach ($calendarList['modelData']['items'] as $cal) {
				$res[] = $cal;
			}
			$res = json_encode($res);

			$filename = $this->lc->save_tmp_file($res, 'cals');

			echo $filename;

			$this->lc->save_a_cookie('g_cals_tmp_file', $filename);
			redirect($cookie['redir_url']);
		}

	}

	function add_new_tracked_calendar(){
		$cookie = $this->input->cookie();

		if($this->test_account_credentials($cookie)){
			//add other logic and redirect
			$this->check_for_google_redirect();
			$details = array(
				'userId' => $cookie['user_id'],
				'summary' => $this->input->cookie('summary'),
				'calendarId' => $this->input->cookie('calendarId'),
				'timeZone' => $this->input->cookie('timeZone'),
				'isPublic' => (!empty($this->input->cookie('isPublic')) ? $this->input->cookie('isPublic') : false )
				);
			$this->Event->add_new_tracked_calendar($details, $this->userDatabase);
			redirect($cookie['redir_url']);
		}

	}

	/***
	 *    _________ _______  _______  _
	 *    \__    _/(  ____ \(  ___  )( (    /|
	 *       )  (  | (    \/| (   ) ||  \  ( |
	 *       |  |  | (_____ | |   | ||   \ | |
	 *       |  |  (_____  )| |   | || (\ \) |
	 *       |  |        ) || |   | || | \   |
	 *    |\_)  )  /\____) || (___) || )  \  |
	 *    (____/   \_______)(_______)|/    )_)
	 *
	 */

	function get_tracked_calendar_events(){
		// debug_print_backtrace();
		$cookie = $this->input->cookie();
		//_show($cookie, 1);
		if(empty($cookie['start'])){
			// $this->lc->save_a_cookie('start', date('2015-01-01'));
			$cookie['start'] = date('2015-01-01');
		}
		if(empty($cookie['end'])){
			$end = date('Y-m-d',strtotime(date("Y-m-d", time()) . " + 365 day"));
			// $this->lc->save_a_cookie('end', $end);
			$cookie['end'] = $end;
		}
		// _show($cookie, 1);
		// if(empty($cookie['timezone'])){
		// 	$this->lc->save_a_cookie('timezone', $this->lc->get_timezone());
		// 	$cookie['timezone'] = $this->lc->get_timezone();
		// }
		// _show($cookie, 1);
		if ((isset($_SESSION['loggingIn'])) && ($_SESSION['loggingIn']=="true")) {
			// _show($cookie, 1);
			// die();
			if (!empty($cookie['redir_url'])) {
				$redir_url = $cookie['redir_url'];
			}
			else {
				$redir_url = PROTOCOL_STRING.$cookie['subdomain'].'.'.FULL_DOMAIN_NAME.'/';
			}
			// echo $redir_url;
			// _show($_SESSION);
			// _show($_SERVER);
			// _show($cookie, 1);
			$this->lc->save_a_cookie('redir_url', $redir_url);
			unset($_SESSION['loggingIn']);
			$url1=$_SERVER['REQUEST_URI'];
	    	header("Refresh: 0; URL=$url1");
		}
		elseif($this->test_account_credentials($cookie)){
			// _show($cookie, 1);
			$this->check_for_google_redirect();
			$blocks = $this->Event->get_only_tracked($cookie['user_id'], $this->userDatabase, $cookie['start'], $cookie['end']);

			//getting data working fine

			//save data for retrival not working:
			//-cannot send through session, session does not persist to subdomains
			// $_SESSION['blocks'] = json_encode($blocks);
			//-cannot send through cookie, cookie max filesize is 4k - google events much larger
			//$this->lc->save_cookie(array('blocks' => json_encode($blocks)));
			//going to try to write to file
			//1- create random file name
			// $filename = 'events.txt';
			$filename = $this->lc->save_tmp_file(json_encode($blocks), 'events');
			//2- save json encoded blocks into file
			//3- store file in tmp folder on server
			//4- save filename/path into cookie
			$this->lc->save_cookie(array('g_events_tmp_file' => $filename));
			//5- redirect
			// echo 'CLICK ME';
			redirect($cookie['redir_url']);
		}
		else {
			_show($cookie, 1);
		}
	}

	function AJAX_delete_event(){

		$cookie = $this->input->cookie();

		if($this->test_account_credentials($cookie)){
			$this->check_for_google_redirect();
			//_show($cookie);

			$deletedEvent = array (
				'localEventId' => $this->input->cookie('localEventId'),
				'googleCalendarId' => $this->input->cookie('googleCalendarId'),
				'googleEventId' => $this->input->cookie('googleEventId')
			);
			$this->Event->delete_gcal($deletedEvent);

			delete_cookie('eventId');
			delete_cookie('calendarId');
			delete_cookie('googleEventId');

			//echo 'CLICK ME';
			redirect($cookie['redir_url']);
		}

	}

	function AJAX_check_in(){
		//does nothing but load the constructor which triggers the g_cal check in

	}

	function AJAX_get_google_event_details(){

		$cookie = $this->input->cookie();
		//_show($this->input->cookie());
		if($this->test_account_credentials($cookie)){
			$this->check_for_google_redirect();
			$eventId = $cookie['eventId'];
			$calendarFullId = $cookie['calendarFullId'];

			$eventDetails = $this->g_cal->get_event($eventId, $calendarFullId);

			$event = new stdClass();
			$event->eventId = $eventDetails->id;
			$event->eventDescription = $eventDetails->summary;
			$event->startDate = (empty($eventDetails->start['dateTime']) ? $eventDetails->start['date'] : $eventDetails->start['dateTime']);
			$event->endDate = (empty($eventDetails->end['dateTime']) ? $eventDetails->end['date'] : $eventDetails->end['dateTime']);
			$event->eventTypeId = EV_MEETING;
			$event->location = null;
			$event->googleEventId = $eventDetails->id;
			$event->calendarId = $calendarFullId;

			delete_cookie('eventId');
			delete_cookie('calendarFullId');
			$this->lc->save_a_cookie('eventDetails', json_encode($event));
			//echo 'CLICK ME';
			redirect($cookie['redir_url']);
		}

	}

	function AJAX_add_new_event(){
		$cookie = $this->input->cookie();
		if($this->test_account_credentials($cookie)){
			$this->check_for_google_redirect();
			$eventId = $cookie['eventId'];
			$newEvent = json_decode($cookie['eventDetails']);

			//_show($newEvent);

			//need to rebuild the event because of json encode/decode chain
			$builtEvent = array(
				'summary' => $newEvent->summary,
				'description' => $newEvent->description,
				'start' => array(
					'dateTime' => $newEvent->start->dateTime,
					'timeZone' => $newEvent->start->timeZone
				),
				'end' => array(
					'dateTime' => $newEvent->end->dateTime,
					'timeZone' => $newEvent->end->timeZone
				)
			);

			$googleEventId = $this->g_cal->add_event_to_google($builtEvent);

			$conn = array(
                'eventId' => $eventId,
                'googleEventId' => $googleEventId,
                'googleCalendarId' => $newEvent->calendarId
            );

            $this->Event->connect_to_google($conn, $this->userDatabase);

			delete_cookie('eventId');
			delete_cookie('eventDetails');

			// echo 'CLICK ME';
			redirect($cookie['redir_url']);

		}
	}

	function AJAX_add_batch_events(){
		$cookie = $this->input->cookie();
		if($this->test_account_credentials($cookie)){
			$this->check_for_google_redirect();
			$moreEvents = true;
			$i=0;
			while ($moreEvents) {
				$eventId = $cookie['eventId-'.$i];
				$newEvent = json_decode($cookie['eventDetails-'.$i]);

				//_show($newEvent);

				//need to rebuild the event because of json encode/decode chain
				$builtEvent = array(
					'summary' => $newEvent->summary,
					'description' => $newEvent->description,
					'start' => array(
						'dateTime' => $newEvent->start->dateTime,
						'timeZone' => $newEvent->start->timeZone
					),
					'end' => array(
						'dateTime' => $newEvent->end->dateTime,
						'timeZone' => $newEvent->end->timeZone
					)
				);

				$googleEventId = $this->g_cal->add_event_to_google($builtEvent);

				$conn = array(
	                'eventId' => $eventId,
	                'googleEventId' => $googleEventId,
	                'googleCalendarId' => $newEvent->calendarId
	            );

	            $this->Event->connect_to_google($conn, $this->userDatabase);

				delete_cookie('eventId-'.$i);
				delete_cookie('eventDetails-'.$i);

				$i++;
				if (empty($cookie['eventId-'.$i])) {
					$moreEvents = false;
				}
			}
			// echo 'CLICK ME';
			redirect($cookie['redir_url']);
		}
	}

	function AJAX_delete_batch_events(){
		$cookie = $this->input->cookie();
		_show($cookie, 1);
		if($this->test_account_credentials($cookie)){
			$this->check_for_google_redirect();
			$moreEvents = true;
			$i=0;
			while ($moreEvents) {
				$deletedEvent = array (
					'googleCalendarId' => $cookie['googleCalendarId-'.$i],
					'googleEventId' => $cookie['googleEventId-'.$i]
				);
				$this->Event->delete_gcal($deletedEvent);
				delete_cookie('localEventId-'.$i);
				delete_cookie('googleCalendarId-'.$i);
				delete_cookie('googleEventId-'.$i);
				$i++;
				if (empty($cookie['localEventId-'.$i])) {
					$moreEvents = false;
				}
			}
			redirect($cookie['redir_url']);
		}

	}

	function AJAX_edit_event(){
		$cookie = $this->input->cookie();
		if($this->test_account_credentials($cookie)){
			$this->check_for_google_redirect();
			//_show($cookie);
			$eventId = $cookie['eventId'];
			$updatedEvent = json_decode($cookie['eventDetails']);

			$buildEvent = array(
				'startDate' => $updatedEvent->startDate,
				'endDate' => $updatedEvent->endDate,
				'eventDescription' => $updatedEvent->eventDescription,
				'eventId' => $eventId,
				'googleEventId' => $updatedEvent->googleEventId,
				'googleCalendarId' => $updatedEvent->googleCalendarId
			);

			$this->Event->update_gcal($eventId, $buildEvent);

			delete_cookie('eventId');
			delete_cookie('eventDetails');
			//echo 'CLICK ME';
			redirect($cookie['redir_url']);
		}
	}

}

redpajama_set_name: RedPajamaGithub


text:
import * as React from 'react';
import BadgeUnstyled, {
  BadgeUnstyledBadgeSlotProps,
  BadgeUnstyledRootSlotProps,
} from '@mui/base/BadgeUnstyled';
import { expectType } from '@mui/types';

const Root = React.forwardRef(function Root(
  props: BadgeUnstyledRootSlotProps,
  ref: React.ForwardedRef<HTMLSpanElement>,
) {
  const { ownerState, ...other } = props;
  return ;
});

const Badge = React.forwardRef(function Badge(
  props: BadgeUnstyledBadgeSlotProps,
  ref: React.ForwardedRef<HTMLSpanElement>,
) {
  const { ownerState, ...other } = props;
  return ;
});

const styledBadge = <BadgeUnstyled slots={{ root: Root, badge: Badge }} />;

const polymorphicComponentTest = () => {
  const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
    function CustomComponent() {
      return
;
    };

  return (

      {/* @ts-expect-error */}
      <BadgeUnstyled invalidProp={0} />

      <BadgeUnstyled component="a" href="#" />

      <BadgeUnstyled component={CustomComponent} stringProp="test" numberProp={0} />
      {/* @ts-expect-error */}
      <BadgeUnstyled component={CustomComponent} />

      <BadgeUnstyled
        component="button"
        onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.currentTarget.checkValidity()}
      />

      <BadgeUnstyled<'button'>
        component="button"
        ref={(elem) => {
          expectType<HTMLButtonElement | null, typeof elem>(elem);
        }}
        onClick={(e) => {
          expectType<React.MouseEvent<HTMLButtonElement, MouseEvent>, typeof e>(e);
          e.currentTarget.checkValidity();
        }}
      />

  );
};


text:
namespace clover {
namespace visual {

ParticleMgr::ParticleMgr(){
	listenForEvent(global::Event::OnParticleSourceActivation);

	/// @todo Replace this by ResourceCache loading
	ParticleType& smoke_type= typeMap["Smoke"];
	smoke_type.name= "Smoke";
	smoke_type.programPath= "shaders/opencl/smoke.cl";
	smoke_type.material= &global::g_env.resCache->getResource<visual::Material>("smoke");
	manifoldMap["Smoke"].create(smoke_type);
}

void ParticleMgr::onEvent(global::Event& e){
	switch(e.getType()){
		case global::Event::OnParticleSourceActivation:

			// ParticleSourceEntity takes care of not sending same event multiple times
			if (e(global::Event::Active).getI())
				sources.pushBack( e(global::Event::Object).getPtr<ParticleSourceEntityLogic>() );
			else
				sources.erase(sources.find( e(global::Event::Object).getPtr<ParticleSourceEntityLogic>() ));

		break;

		default: break;
	}
}

void ParticleMgr::update(){
	for (auto& m : sources){
		//ensure(m->isActive());

		/// @todo Don't update or spawn if too far from the camera
		m->update();

		if (m->hasParticlesForSpawning()){

			auto it= manifoldMap.find(m->getParticleTypeName());

			ensure(it != manifoldMap.end());

			auto spawn_data= std::move(m->popSpawnData());
			it->second.spawn(spawn_data);

		}
	}

	for (auto& m : manifoldMap){
		m.second.update();
	}
}

ParticleManifold& ParticleMgr::getManifold(const util::Str8& name){
	auto it= manifoldMap.find(name);
	ensure(it != manifoldMap.end());
	return it->second;
}

} // visual
} // clover


text:
package com.ibm.streamsx.topology.internal.context.remote;

import static com.ibm.streamsx.topology.internal.context.remote.DeployKeys.keepArtifacts;
import static com.ibm.streamsx.topology.internal.graph.GraphKeys.CONFIG;
import static com.ibm.streamsx.topology.internal.graph.GraphKeys.graph;
import static com.ibm.streamsx.topology.internal.graph.GraphKeys.splAppName;
import static com.ibm.streamsx.topology.internal.graph.GraphKeys.splAppNamespace;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.jstring;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.object;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.objectArray;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

import com.google.gson.JsonObject;
import com.ibm.streamsx.topology.context.remote.RemoteContext;
import com.ibm.streamsx.topology.internal.gson.GsonUtilities;
import com.ibm.streamsx.topology.internal.process.CompletedFuture;

public class ZippedToolkitRemoteContext extends ToolkitRemoteContext {

	private final boolean keepBuildArchive;

	public ZippedToolkitRemoteContext() {
        this.keepBuildArchive = false;
    }

    public ZippedToolkitRemoteContext(boolean keepBuildArchive) {
        this.keepBuildArchive = keepBuildArchive;
    }

	@Override
    public Type getType() {
        return Type.BUILD_ARCHIVE;
    }

    @Override
    public Future<File> _submit(JsonObject submission) throws Exception {
        final File toolkitRoot = super._submit(submission).get();
        return createCodeArchive(toolkitRoot, submission);
    }

    public Future<File> createCodeArchive(File toolkitRoot, JsonObject submission) throws IOException, URISyntaxException {

        String tkName = toolkitRoot.getName();

        Path zipOutPath = pack(toolkitRoot.toPath(), graph(submission), tkName);

        if (keepBuildArchive || keepArtifacts(submission)) {
        	final JsonObject submissionResult = GsonUtilities.objectCreate(submission, RemoteContext.SUBMISSION_RESULTS);
        	submissionResult.addProperty(SubmissionResultsKeys.ARCHIVE_PATH, zipOutPath.toString());
        }

        JsonObject deployInfo = object(submission, SUBMISSION_DEPLOY);
        deleteToolkit(toolkitRoot, deployInfo);

        return new CompletedFuture<File>(zipOutPath.toFile());
    }

    private static Path pack(final Path folder, JsonObject graph, String tkName) throws IOException, URISyntaxException {
        String namespace = splAppNamespace(graph);
        String name = splAppName(graph);

        Path zipFilePath = Paths.get(folder.toAbsolutePath().toString() + ".zip");
        String workingDir = zipFilePath.getParent().toString();

        Path topologyToolkit = TkInfo.getTopologyToolkitRoot().getAbsoluteFile().toPath();

        // Paths to copy into the toolkit
        Map<Path, String> paths = new HashMap<>();

        // tkManifest is the list of toolkits contained in the archive
        try (PrintWriter tkManifest = new PrintWriter("manifest_tk.txt", "UTF-8")) {
            tkManifest.println(tkName);
            tkManifest.println("com.ibm.streamsx.topology");

            JsonObject configSpl = object(graph, CONFIG, "spl");
            if (configSpl != null) {
                objectArray(configSpl, "toolkits",
                        tk -> {
                            File tkRoot = new File(jstring(tk, "root"));
                            String tkRootName = tkRoot.getName();
                            tkManifest.println(tkRootName);
                            paths.put(tkRoot.toPath(), tkRootName);
                            }
                        );
            }
        }

        // mainComposite is a string of the namespace and the main composite.
        // This is used by the Makefile
        try (PrintWriter mainComposite = new PrintWriter("main_composite.txt", "UTF-8")) {
            mainComposite.print(namespace + "::" + name);
        }

        Path manifest = Paths.get(workingDir, "manifest_tk.txt");
        Path mainComp = Paths.get(workingDir, "main_composite.txt");
        Path makefile = topologyToolkit.resolve(Paths.get("opt", "python", "templates", "common", "Makefile.template"));

        paths.put(topologyToolkit, topologyToolkit.getFileName().toString());
        paths.put(manifest, "manifest_tk.txt");
        paths.put(mainComp, "main_composite.txt");
        paths.put(makefile, "Makefile");
        paths.put(folder, folder.getFileName().toString());

        addAllToZippedArchive(paths, zipFilePath);
        manifest.toFile().delete();
        mainComp.toFile().delete();

        return zipFilePath;
    }

    private static void addAllToZippedArchive(Map<Path, String> starts, Path zipFilePath) throws IOException {
        try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(zipFilePath.toFile())) {
            for (Path start : starts.keySet()) {
                final String rootEntryName = starts.get(start);
                Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        // Skip pyc files.
                        if (file.getFileName().toString().endsWith(".pyc"))
                            return FileVisitResult.CONTINUE;

                        String entryName = rootEntryName;
                        String relativePath = start.relativize(file).toString();
                        // If empty, file is the start file.
                        if(!relativePath.isEmpty()){
                            entryName = entryName + "/" + relativePath;
                        }
                        // Zip uses forward slashes
                        entryName = entryName.replace(File.separatorChar, '/');

                        ZipArchiveEntry entry = new ZipArchiveEntry(file.toFile(), entryName);
                        if (Files.isExecutable(file))
                            entry.setUnixMode(0100770);
                        else
                            entry.setUnixMode(0100660);

                        zos.putArchiveEntry(entry);
                        Files.copy(file, zos);
                        zos.closeArchiveEntry();
                        return FileVisitResult.CONTINUE;
                    }

                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                        final String dirName = dir.getFileName().toString();
                        // Don't include pyc files or .toolkit
                        if (dirName.equals("__pycache__"))
                            return FileVisitResult.SKIP_SUBTREE;

                        ZipArchiveEntry dirEntry = new ZipArchiveEntry(dir.toFile(), rootEntryName + "/" + start.relativize(dir).toString().replace(File.separatorChar, '/') + "/");
                        zos.putArchiveEntry(dirEntry);
                        zos.closeArchiveEntry();
                        return FileVisitResult.CONTINUE;
                    }
                });
            }
        }
    }
}


text:
SYNONYM

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Syst. mycol. (Lundae) 2(1): 188 (1822)

#### Original name
Cenangium ericae Niessl, 1870

### Remarks
null


text:
/* $Id$ */

package org.apache.fop.render.java2d;

// Java
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.util.UnitConv;

import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactoryConfig;
import org.apache.fop.area.CTM;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.extensions.prepress.PageBoundaries;
import org.apache.fop.render.extensions.prepress.PageScale;
import org.apache.fop.render.pdf.CTMHelper;
import org.apache.fop.util.CharUtilities;
import org.apache.fop.util.ColorUtil;

import static org.apache.fop.render.java2d.Java2DRendererOption.JAVA2D_TRANSPARENT_PAGE_BACKGROUND;

/**
 * The Java2DRenderer class provides the abstract technical
 * foundation for all rendering with the Java2D API. Renderers like
 * AWTRenderer subclass it and provide the concrete output paths.
 *

 * A lot of the logic is performed by AbstractRenderer. The
 * class-variables currentIPPosition and
 * currentBPPosition hold the position of the currently rendered
 * area.
 *

 * Java2DGraphicsState state holds the Graphics2D,
 * which is used along the whole rendering. state also acts as a
 * stack (state.push() and state.pop()).
 *

 * The rendering process is basically always the same:
 *

 * void renderXXXXX(Area area) {
 *    //calculate the currentPosition
 *    state.updateFont(name, size, null);
 *    state.updateColor(ct, false, null);
 *    state.getGraph.draw(new Shape(args));
 * }
 *
 */
public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implements Printable {

    /** The scale factor for the image size, values: ]0 ; 1] */
    protected double scaleFactor = 1;

    /** The page width in pixels */
    protected int pageWidth;

    /** The page height in pixels */
    protected int pageHeight;

    /** List of Viewports */
    protected List pageViewportList = new java.util.ArrayList();

    /** The 0-based current page number */
    private int currentPageNumber;

    /** true if anti-aliasing is set */
    protected boolean antialiasing = true;

    /** true if qualityRendering is set */
    protected boolean qualityRendering = true;

    /** false: paints a non-transparent white background, true: for a transparent background */
    protected boolean transparentPageBackground;

    /** The current state, holds a Graphics2D and its context */
    protected Java2DGraphicsState state;

    private final Stack stateStack = new Stack();

    /** true if the renderer has finished rendering all the pages */
    private boolean renderingDone;

    private GeneralPath currentPath;

    /**
     * Default constructor
     *
     * @param userAgent the user agent that contains configuration details. This cannot be null.
     */
    public Java2DRenderer(FOUserAgent userAgent) {
        super(userAgent);

        // MH: necessary? the caller has access to FOUserAgent
        userAgent.setRendererOverride(this); // for document regeneration

        String s = (String) userAgent.getRendererOption(JAVA2D_TRANSPARENT_PAGE_BACKGROUND);
        if (s != null) {
            this.transparentPageBackground = "true".equalsIgnoreCase(s);
        }
    }

    /** @return the FOUserAgent */
    public FOUserAgent getUserAgent() {
        return userAgent;
    }

    /** {@inheritDoc} */
    public void setupFontInfo(FontInfo inFontInfo) {
        //Don't call super.setupFontInfo() here! Java2D needs a special font setup
        // create a temp Image to test font metrics on
        this.fontInfo = inFontInfo;
        final Java2DFontMetrics java2DFontMetrics = new Java2DFontMetrics();

        FontManager fontManager = userAgent.getFontManager();

        FontCollection[] fontCollections = new FontCollection[] {
                new Base14FontCollection(java2DFontMetrics),
                new InstalledFontCollection(java2DFontMetrics),
                new ConfiguredFontCollection(fontManager.getResourceResolver(), getFontList(),
                        userAgent.isComplexScriptFeaturesEnabled())
        };
        fontManager.setup(getFontInfo(), fontCollections);
    }

    /** {@inheritDoc} */
    public Graphics2DAdapter getGraphics2DAdapter() {
        return new Java2DGraphics2DAdapter();
    }

    /**
     * Sets the new scale factor.
     * @param newScaleFactor ]0 ; 1]
     */
    public void setScaleFactor(double newScaleFactor) {
        this.scaleFactor = newScaleFactor;
    }

    /** @return the scale factor */
    public double getScaleFactor() {
        return this.scaleFactor;
    }

    /** {@inheritDoc} */
    public void startRenderer(OutputStream out) throws IOException {
        super.startRenderer(out);
        // do nothing by default
    }

    /** {@inheritDoc} */
    public void stopRenderer() throws IOException {
        log.debug("Java2DRenderer stopped");
        renderingDone = true;
        int numberOfPages = currentPageNumber;
        // TODO set all vars to null for gc
    }

    /** @return true if the renderer is not currently processing */
    public boolean isRenderingDone() {
        return this.renderingDone;
    }

    /**
     * @return The 0-based current page number
     */
    public int getCurrentPageNumber() {
        return currentPageNumber;
    }

    /**
     * @param c the 0-based current page number
     */
    public void setCurrentPageNumber(int c) {
        this.currentPageNumber = c;
    }

    /**
     * Returns the number of pages available. This method is also part of the Pageable interface.
     * @return The 0-based total number of rendered pages
     * @see java.awt.print.Pageable
     */
    public int getNumberOfPages() {
        return pageViewportList.size();
    }

    /**
     * Clears the ViewportList.
     * Used if the document is reloaded.
     */
    public void clearViewportList() {
        pageViewportList.clear();
        setCurrentPageNumber(0);
    }

    /**
     * This method override only stores the PageViewport in a List. No actual
     * rendering is performed here. A renderer override renderPage() to get the
     * freshly produced PageViewport, and render them on the fly (producing the
     * desired BufferedImages by calling getPageImage(), which lazily starts the
     * rendering process).
     *
     * @param pageViewport the PageViewport object supplied by
     * the Area Tree
     * @throws IOException In case of an I/O error
     * @throws FOPException if cloning of pageViewport is not supported
     * @see org.apache.fop.render.Renderer
     */
    public void renderPage(PageViewport pageViewport) throws IOException, FOPException {
        try {
            rememberPage((PageViewport)pageViewport.clone());
        } catch (CloneNotSupportedException e) {
            throw new FOPException(e);
        }
        //The clone() call is necessary as we store the page for later. Otherwise, the
        //RenderPagesModel calls PageViewport.clear() to release memory as early as possible.
        currentPageNumber++;
    }

    /**
     * Stores the pageViewport in a list of page viewports so they can be rendered later.
     * Subclasses can override this method to filter pages, for example.
     * @param pageViewport the page viewport
     */
    protected void rememberPage(PageViewport pageViewport) {
        assert pageViewport.getPageIndex() >= 0;
        pageViewportList.add(pageViewport);
    }

    /**
     * Generates a desired page from the renderer's page viewport list.
     *
     * @param pageViewport the PageViewport to be rendered
     * @return the java.awt.image.BufferedImage corresponding to
     * the page or null if the page doesn't exist.
     */
    public BufferedImage getPageImage(PageViewport pageViewport) {

        this.currentPageViewport = pageViewport;
        try {
            PageBoundaries boundaries = new PageBoundaries(
                    pageViewport.getViewArea().getSize(), pageViewport.getForeignAttributes());
            Rectangle bounds = boundaries.getCropBox();
            Rectangle bleedBox = boundaries.getBleedBox();
            this.pageWidth = (int) Math.round(bounds.getWidth() / 1000f);
            this.pageHeight = (int) Math.round(bounds.getHeight() / 1000f);

            log.info(
                    "Rendering Page " + pageViewport.getPageNumberString()
                            + " (pageWidth " + pageWidth + ", pageHeight "
                            + pageHeight + ")");

            // set scale factor
            double scaleX = scaleFactor;
            double scaleY = scaleFactor;
            String scale = currentPageViewport.getForeignAttributes().get(
                    PageScale.EXT_PAGE_SCALE);
            Point2D scales = PageScale.getScale(scale);
            if (scales != null) {
                scaleX *= scales.getX();
                scaleY *= scales.getY();
            }

            scaleX = scaleX
                    * (UnitConv.IN2MM / FopFactoryConfig.DEFAULT_TARGET_RESOLUTION)
                / userAgent.getTargetPixelUnitToMillimeter();
            scaleY = scaleY
                    * (UnitConv.IN2MM / FopFactoryConfig.DEFAULT_TARGET_RESOLUTION)
                / userAgent.getTargetPixelUnitToMillimeter();
            int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5);
            int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5);

            BufferedImage currentPageImage = getBufferedImage(bitmapWidth, bitmapHeight);

            Graphics2D graphics = currentPageImage.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                    RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            if (antialiasing) {
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            }
            if (qualityRendering) {
                graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
                        RenderingHints.VALUE_RENDER_QUALITY);
            }
            graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                    RenderingHints.VALUE_STROKE_PURE);

            // transform page based on scale factor supplied
            AffineTransform at = graphics.getTransform();
            at.scale(scaleX, scaleY);
            at.translate(bounds.getMinX() / -1000f, bounds.getMinY() / -1000f);
            graphics.setTransform(at);

            // draw page frame
            if (!transparentPageBackground) {
                graphics.setColor(Color.white);
                graphics.fillRect(
                        (int)Math.round(bleedBox.getMinX() / 1000f),
                        (int)Math.round(bleedBox.getMinY() / 1000f),
                        (int)Math.round(bleedBox.getWidth() / 1000f),
                        (int)Math.round(bleedBox.getHeight() / 1000f));
            }
            /* why did we have this???
            graphics.setColor(Color.black);
            graphics.drawRect(-1, -1, pageWidth + 2, pageHeight + 2);
            graphics.drawLine(pageWidth + 2, 0, pageWidth + 2, pageHeight + 2);
            graphics.drawLine(pageWidth + 3, 1, pageWidth + 3, pageHeight + 3);
            graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2);
            graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3);
            */

            state = new Java2DGraphicsState(graphics, this.fontInfo, at);
            try {
                // reset the current Positions
                currentBPPosition = 0;
                currentIPPosition = 0;

                // this toggles the rendering of all areas
                renderPageAreas(pageViewport.getPage());
            } finally {
                state = null;
            }

            return currentPageImage;
        } finally {
            this.currentPageViewport = null;
        }
    }

    /**
     * Returns a specific BufferedImage to paint a page image on. This method can
     * be overridden in subclasses to produce different image formats (ex. grayscale or b/w).
     * @param bitmapWidth width of the image in pixels
     * @param bitmapHeight heigth of the image in pixels
     * @return the newly created BufferedImage
     */
    protected BufferedImage getBufferedImage(int bitmapWidth, int bitmapHeight) {
       return new BufferedImage(
                bitmapWidth, bitmapHeight, BufferedImage.TYPE_INT_ARGB);
    }

    /**
     * Returns a page viewport.
     * @param pageIndex the page index (zero-based)
     * @return the requested PageViewport instance
     * @exception FOPException If the page is out of range.
     */
    public PageViewport getPageViewport(int pageIndex) throws FOPException {
        if (pageIndex < 0 || pageIndex >= pageViewportList.size()) {
            throw new FOPException("Requested page number is out of range: " + pageIndex
                     + "; only " + pageViewportList.size()
                     + " page(s) available.");
        }
        return (PageViewport) pageViewportList.get(pageIndex);
    }

    /**
     * Generates a desired page from the renderer's page viewport list.
     *
     * @param pageNum the 0-based page number to generate
     * @return the java.awt.image.BufferedImage corresponding to
     * the page or null if the page doesn't exist.
     * @throws FOPException If there's a problem preparing the page image
     */
    public BufferedImage getPageImage(int pageNum) throws FOPException {
        return getPageImage(getPageViewport(pageNum));
    }

    /** Saves the graphics state of the rendering engine. */
    protected void saveGraphicsState() {
        // push (and save) the current graphics state
        stateStack.push(state);
        state = new Java2DGraphicsState(state);
    }

    /** Restores the last graphics state of the rendering engine. */
    protected void restoreGraphicsState() {
        state.dispose();
        state = (Java2DGraphicsState)stateStack.pop();
    }

    /** {@inheritDoc} */
    protected void concatenateTransformationMatrix(AffineTransform at) {
        state.transform(at);
    }

    /** {@inheritDoc} */
    protected void startVParea(CTM ctm, Rectangle clippingRect) {

        saveGraphicsState();

        if (clippingRect != null) {
            clipRect((float)clippingRect.getX() / 1000f,
                    (float)clippingRect.getY() / 1000f,
                    (float)clippingRect.getWidth() / 1000f,
                    (float)clippingRect.getHeight() / 1000f);
        }

        // Set the given CTM in the graphics state
        //state.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
        state.transform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
    }

    /** {@inheritDoc} */
    protected void endVParea() {
        restoreGraphicsState();
    }

    /** {@inheritDoc} */
    protected void startLayer(String layer) {
    }

    /** {@inheritDoc} */
    protected void endLayer() {
    }

    /** {@inheritDoc} */
    protected List breakOutOfStateStack() {
        log.debug("Block.FIXED --> break out");
        List breakOutList;
        breakOutList = new java.util.ArrayList();
        while (!stateStack.isEmpty()) {
            breakOutList.add(0, state);
            //We only pop, we don't dispose, because we can use the instances again later
            state = (Java2DGraphicsState)stateStack.pop();
        }
        return breakOutList;
    }

    /** {@inheritDoc} */
    protected void restoreStateStackAfterBreakOut(List breakOutList) {
        log.debug("Block.FIXED --> restoring context after break-out");

        for (Object aBreakOutList : breakOutList) {
            Java2DGraphicsState s = (Java2DGraphicsState) aBreakOutList;
            stateStack.push(state);
            this.state = s;
        }
    }

    /** {@inheritDoc} */
    protected void updateColor(Color col, boolean fill) {
        state.updateColor(col);
    }

    /** {@inheritDoc} */
    protected void clip() {
        if (currentPath == null) {
            throw new IllegalStateException("No current path available!");
        }
        state.updateClip(currentPath);
        currentPath = null;
    }

    /** {@inheritDoc} */
    protected void closePath() {
        currentPath.closePath();
    }

    /** {@inheritDoc} */
    protected void lineTo(float x, float y) {
        if (currentPath == null) {
            currentPath = new GeneralPath();
        }
        currentPath.lineTo(x, y);
    }

    /** {@inheritDoc} */
    protected void moveTo(float x, float y) {
        if (currentPath == null) {
            currentPath = new GeneralPath();
        }
        currentPath.moveTo(x, y);
    }

    /** {@inheritDoc} */
    protected void clipRect(float x, float y, float width, float height) {
        state.updateClip(new Rectangle2D.Float(x, y, width, height));
    }

    /** {@inheritDoc} */
    protected void fillRect(float x, float y, float width, float height) {
        state.getGraph().fill(new Rectangle2D.Float(x, y, width, height));
    }

    /** {@inheritDoc} */
    protected void drawBorderLine(float x1, float y1, float x2, float y2,
            boolean horz, boolean startOrBefore, int style, Color col) {
        Graphics2D g2d = state.getGraph();
        float width = x2 - x1;
        float height = y2 - y1;
        drawBorderLine(new Rectangle2D.Float(x1, y1, width, height),
                horz, startOrBefore, style, col, g2d);
    }

    /**
     * Draw a border segment of an XSL-FO style border.
     * @param lineRect the line defined by its bounding rectangle
     * @param horz true for horizontal border segments, false for vertical border segments
     * @param startOrBefore true for border segments on the start or before edge,
     *                      false for end or after.
     * @param style the border style (one of Constants.EN_DASHED etc.)
     * @param col the color for the border segment
     * @param g2d the Graphics2D instance to paint to
     */
    public static void drawBorderLine(Rectangle2D.Float lineRect,
            boolean horz, boolean startOrBefore, int style, Color col, Graphics2D g2d) {
        float x1 = lineRect.x;
        float y1 = lineRect.y;
        float x2 = x1 + lineRect.width;
        float y2 = y1 + lineRect.height;
        float w = lineRect.width;
        float h = lineRect.height;
        if ((w < 0) || (h < 0)) {
            log.error("Negative extent received. Border won't be painted.");
            return;
        }
        switch (style) {
            case Constants.EN_DASHED:
                g2d.setColor(col);
                if (horz) {
                    float unit = Math.abs(2 * h);
                    int rep = (int)(w / unit);
                    if (rep % 2 == 0) {
                        rep++;
                    }
                    unit = w / rep;
                    float ym = y1 + (h / 2);
                    BasicStroke s = new BasicStroke(h, BasicStroke.CAP_BUTT,
                            BasicStroke.JOIN_MITER, 10.0f, new float[] {unit}, 0);
                    g2d.setStroke(s);
                    g2d.draw(new Line2D.Float(x1, ym, x2, ym));
                } else {
                    float unit = Math.abs(2 * w);
                    int rep = (int)(h / unit);
                    if (rep % 2 == 0) {
                        rep++;
                    }
                    unit = h / rep;
                    float xm = x1 + (w / 2);
                    BasicStroke s = new BasicStroke(w, BasicStroke.CAP_BUTT,
                            BasicStroke.JOIN_MITER, 10.0f, new float[] {unit}, 0);
                    g2d.setStroke(s);
                    g2d.draw(new Line2D.Float(xm, y1, xm, y2));
                }
                break;
            case Constants.EN_DOTTED:
                g2d.setColor(col);
                if (horz) {
                    float unit = Math.abs(2 * h);
                    int rep = (int)(w / unit);
                    if (rep % 2 == 0) {
                        rep++;
                    }
                    unit = w / rep;
                    float ym = y1 + (h / 2);
                    BasicStroke s = new BasicStroke(h, BasicStroke.CAP_ROUND,
                            BasicStroke.JOIN_MITER, 10.0f, new float[] {0, unit}, 0);
                    g2d.setStroke(s);
                    g2d.draw(new Line2D.Float(x1, ym, x2, ym));
                } else {
                    float unit = Math.abs(2 * w);
                    int rep = (int)(h / unit);
                    if (rep % 2 == 0) {
                        rep++;
                    }
                    unit = h / rep;
                    float xm = x1 + (w / 2);
                    BasicStroke s = new BasicStroke(w, BasicStroke.CAP_ROUND,
                            BasicStroke.JOIN_MITER, 10.0f, new float[] {0, unit}, 0);
                    g2d.setStroke(s);
                    g2d.draw(new Line2D.Float(xm, y1, xm, y2));
                }
                break;
            case Constants.EN_DOUBLE:
                g2d.setColor(col);
                if (horz) {
                    float h3 = h / 3;
                    float ym1 = y1 + (h3 / 2);
                    float ym2 = ym1 + h3 + h3;
                    BasicStroke s = new BasicStroke(h3);
                    g2d.setStroke(s);
                    g2d.draw(new Line2D.Float(x1, ym1, x2, ym1));
                    g2d.draw(new Line2D.Float(x1, ym2, x2, ym2));
                } else {
                    float w3 = w / 3;
                    float xm1 = x1 + (w3 / 2);
                    float xm2 = xm1 + w3 + w3;
                    BasicStroke s = new BasicStroke(w3);
                    g2d.setStroke(s);
                    g2d.draw(new Line2D.Float(xm1, y1, xm1, y2));
                    g2d.draw(new Line2D.Float(xm2, y1, xm2, y2));
                }
                break;
            case Constants.EN_GROOVE:
            case Constants.EN_RIDGE:
                float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f);
                if (horz) {
                    Color uppercol = ColorUtil.lightenColor(col, -colFactor);
                    Color lowercol = ColorUtil.lightenColor(col, colFactor);
                    float h3 = h / 3;
                    float ym1 = y1 + (h3 / 2);
                    g2d.setStroke(new BasicStroke(h3));
                    g2d.setColor(uppercol);
                    g2d.draw(new Line2D.Float(x1, ym1, x2, ym1));
                    g2d.setColor(col);
                    g2d.draw(new Line2D.Float(x1, ym1 + h3, x2, ym1 + h3));
                    g2d.setColor(lowercol);
                    g2d.draw(new Line2D.Float(x1, ym1 + h3 + h3, x2, ym1 + h3 + h3));
                } else {
                    Color leftcol = ColorUtil.lightenColor(col, -colFactor);
                    Color rightcol = ColorUtil.lightenColor(col, colFactor);
                    float w3 = w / 3;
                    float xm1 = x1 + (w3 / 2);
                    g2d.setStroke(new BasicStroke(w3));
                    g2d.setColor(leftcol);
                    g2d.draw(new Line2D.Float(xm1, y1, xm1, y2));
                    g2d.setColor(col);
                    g2d.draw(new Line2D.Float(xm1 + w3, y1, xm1 + w3, y2));
                    g2d.setColor(rightcol);
                    g2d.draw(new Line2D.Float(xm1 + w3 + w3, y1, xm1 + w3 + w3, y2));
                }
                break;
            case Constants.EN_INSET:
            case Constants.EN_OUTSET:
                colFactor = (style == EN_OUTSET ? 0.4f : -0.4f);
                if (horz) {
                    col = ColorUtil.lightenColor(col, (startOrBefore ? 1 : -1) * colFactor);
                    g2d.setStroke(new BasicStroke(h));
                    float ym1 = y1 + (h / 2);
                    g2d.setColor(col);
                    g2d.draw(new Line2D.Float(x1, ym1, x2, ym1));
                } else {
                    col = ColorUtil.lightenColor(col, (startOrBefore ? 1 : -1) * colFactor);
                    float xm1 = x1 + (w / 2);
                    g2d.setStroke(new BasicStroke(w));
                    g2d.setColor(col);
                    g2d.draw(new Line2D.Float(xm1, y1, xm1, y2));
                }
                break;
            case Constants.EN_HIDDEN:
                break;
            default:
                g2d.setColor(col);
                if (horz) {
                    float ym = y1 + (h / 2);
                    g2d.setStroke(new BasicStroke(h));
                    g2d.draw(new Line2D.Float(x1, ym, x2, ym));
                } else {
                    float xm = x1 + (w / 2);
                    g2d.setStroke(new BasicStroke(w));
                    g2d.draw(new Line2D.Float(xm, y1, xm, y2));
                }
        }
    }

    /** {@inheritDoc} */
    public void renderText(TextArea text) {
        renderInlineAreaBackAndBorders(text);

        int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
        int bl = currentBPPosition + text.getBlockProgressionOffset() + text.getBaselineOffset();
        int saveIP = currentIPPosition;

        Font font = getFontFromArea(text);
        state.updateFont(font.getFontName(), font.getFontSize());
        saveGraphicsState();
        AffineTransform at = new AffineTransform();
        at.translate(rx / 1000f, bl / 1000f);
        state.transform(at);
        renderText(text, state.getGraph(), font);
        restoreGraphicsState();

        currentIPPosition = saveIP + text.getAllocIPD();
        //super.renderText(text);

        // rendering text decorations
        Typeface tf = fontInfo.getFonts().get(font.getFontName());
        int fontsize = text.getTraitAsInteger(Trait.FONT_SIZE);
        renderTextDecoration(tf, fontsize, text, bl, rx);
    }

    /**
     * Renders a TextArea to a Graphics2D instance. Adjust the coordinate system so that the
     * start of the baseline of the first character is at coordinate (0,0).
     * @param text the TextArea
     * @param g2d the Graphics2D to render to
     * @param font the font to paint with
     */
    public static void renderText(TextArea text, Graphics2D g2d, Font font) {

        Color col = (Color) text.getTrait(Trait.COLOR);
        g2d.setColor(col);

        float textCursor = 0;

        for (Object child : text.getChildAreas()) {
            if (child instanceof WordArea) {
                WordArea word = (WordArea) child;
                String s = word.getWord();
                int[] letterAdjust = word.getLetterAdjustArray();
                GlyphVector gv = g2d.getFont().createGlyphVector(g2d.getFontRenderContext(), s);
                double additionalWidth = 0.0;
                if (letterAdjust == null
                        && text.getTextLetterSpaceAdjust() == 0
                        && text.getTextWordSpaceAdjust() == 0) {
                    //nop
                } else {
                    int[] offsets = getGlyphOffsets(s, font, text, letterAdjust);
                    float cursor = 0.0f;
                    for (int i = 0; i < offsets.length; i++) {
                        Point2D pt = gv.getGlyphPosition(i);
                        pt.setLocation(cursor, pt.getY());
                        gv.setGlyphPosition(i, pt);
                        cursor += offsets[i] / 1000f;
                    }
                    additionalWidth = cursor - gv.getLogicalBounds().getWidth();
                }
                g2d.drawGlyphVector(gv, textCursor, 0);
                textCursor += gv.getLogicalBounds().getWidth() + additionalWidth;
            } else if (child instanceof SpaceArea) {
                SpaceArea space = (SpaceArea) child;
                String s = space.getSpace();
                char sp = s.charAt(0);
                int tws = (space.isAdjustable()
                        ? text.getTextWordSpaceAdjust()
                        + 2 * text.getTextLetterSpaceAdjust()
                        : 0);

                textCursor += (font.getCharWidth(sp) + tws) / 1000f;
            } else {
                throw new IllegalStateException("Unsupported child element: " + child);
            }
        }
    }

    private static int[] getGlyphOffsets(String s, Font font, TextArea text,
            int[] letterAdjust) {
        int textLen = s.length();
        int[] offsets = new int[textLen];
        for (int i = 0; i < textLen; i++) {
            final char c = s.charAt(i);
            final char mapped = font.mapChar(c);
            int wordSpace;

            if (CharUtilities.isAdjustableSpace(mapped)) {
                wordSpace = text.getTextWordSpaceAdjust();
            } else {
                wordSpace = 0;
            }
            int cw = font.getWidth(mapped);
            int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0);
            int tls = (i < textLen - 1 ? text.getTextLetterSpaceAdjust() : 0);
            offsets[i] = cw + ladj + tls + wordSpace;
        }
        return offsets;
    }

    /**
     * Render leader area. This renders a leader area which is an area with a
     * rule.
     *
     * @param area the leader area to render
     */
    public void renderLeader(Leader area) {
        renderInlineAreaBackAndBorders(area);

        // TODO leader-length: 25%, 50%, 75%, 100% not working yet
        // TODO Colors do not work on Leaders yet

        float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f;
        float starty = ((currentBPPosition + area.getBlockProgressionOffset()) / 1000f);
        float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart()
                + area.getIPD()) / 1000f;

        Color col = (Color) area.getTrait(Trait.COLOR);
        state.updateColor(col);

        Line2D line = new Line2D.Float();
        line.setLine(startx, starty, endx, starty);
        float ruleThickness = area.getRuleThickness() / 1000f;

        int style = area.getRuleStyle();
        switch (style) {
        case EN_SOLID:
        case EN_DASHED:
        case EN_DOUBLE:
            drawBorderLine(startx, starty, endx, starty + ruleThickness,
                    true, true, style, col);
            break;
        case EN_DOTTED:
            //TODO Dots should be shifted to the left by ruleThickness / 2
            state.updateStroke(ruleThickness, style);
            float rt2 = ruleThickness / 2f;
            line.setLine(line.getX1(), line.getY1() + rt2, line.getX2(), line.getY2() + rt2);
            state.getGraph().draw(line);
            break;
        case EN_GROOVE:
        case EN_RIDGE:
            float half = area.getRuleThickness() / 2000f;

            state.updateColor(ColorUtil.lightenColor(col, 0.6f));
            moveTo(startx, starty);
            lineTo(endx, starty);
            lineTo(endx, starty + 2 * half);
            lineTo(startx, starty + 2 * half);
            closePath();
            state.getGraph().fill(currentPath);
            currentPath = null;
            state.updateColor(col);
            if (style == EN_GROOVE) {
                moveTo(startx, starty);
                lineTo(endx, starty);
                lineTo(endx, starty + half);
                lineTo(startx + half, starty + half);
                lineTo(startx, starty + 2 * half);
            } else {
                moveTo(endx, starty);
                lineTo(endx, starty + 2 * half);
                lineTo(startx, starty + 2 * half);
                lineTo(startx, starty + half);
                lineTo(endx - half, starty + half);
            }
            closePath();
            state.getGraph().fill(currentPath);
            currentPath = null;
            break;

        case EN_NONE:
            // No rule is drawn
            break;
        default:
            break;
        } // end switch

        super.renderLeader(area);
    }

    /** {@inheritDoc} */
    public void renderImage(Image image, Rectangle2D pos) {
        // endTextObject();
        String url = image.getURL();
        drawImage(url, pos);
    }

    private static final ImageFlavor[] FLAVOURS = new ImageFlavor[]
                                                  {ImageFlavor.GRAPHICS2D,
                                                      ImageFlavor.BUFFERED_IMAGE,
                                                      ImageFlavor.RENDERED_IMAGE,
                                                      ImageFlavor.XML_DOM};

    /** {@inheritDoc} */
    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {

        int x = currentIPPosition + (int)Math.round(pos.getX());
        int y = currentBPPosition + (int)Math.round(pos.getY());
        uri = URISpecification.getURL(uri);

        ImageManager manager = getUserAgent().getImageManager();
        ImageInfo info = null;
        try {
            ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
            info = manager.getImageInfo(uri, sessionContext);
            Map hints = ImageUtil.getDefaultHints(sessionContext);
            org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
                    info, FLAVOURS, hints, sessionContext);
            if (img instanceof ImageGraphics2D) {
                ImageGraphics2D imageG2D = (ImageGraphics2D)img;
                int width = (int)pos.getWidth();
                int height = (int)pos.getHeight();
                RendererContext context = createRendererContext(
                        x, y, width, height, foreignAttributes);
                getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(),
                        context, x, y, width, height);
            } else if (img instanceof ImageRendered) {
                ImageRendered imgRend = (ImageRendered)img;
                AffineTransform at = new AffineTransform();
                at.translate(x / 1000f, y / 1000f);
                double sx = pos.getWidth() / info.getSize().getWidthMpt();
                double sy = pos.getHeight() / info.getSize().getHeightMpt();
                sx *= userAgent.getSourceResolution() / info.getSize().getDpiHorizontal();
                sy *= userAgent.getSourceResolution() / info.getSize().getDpiVertical();
                at.scale(sx, sy);
                state.getGraph().drawRenderedImage(imgRend.getRenderedImage(), at);
            } else if (img instanceof ImageXMLDOM) {
                ImageXMLDOM imgXML = (ImageXMLDOM)img;
                renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(),
                        pos, foreignAttributes);
            }
        } catch (ImageException ie) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
        } catch (FileNotFoundException fe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
        }
    }

    /** {@inheritDoc} */
    protected RendererContext createRendererContext(int x, int y, int width, int height,
            Map foreignAttributes) {
        RendererContext context = super.createRendererContext(
                x, y, width, height, foreignAttributes);
        context.setProperty(Java2DRendererContextConstants.JAVA2D_STATE, state);
        return context;
    }

    /** {@inheritDoc} */
    public int print(Graphics g, PageFormat pageFormat, int pageIndex)
            throws PrinterException {
        if (pageIndex >= getNumberOfPages()) {
            return NO_SUCH_PAGE;
        }

        if (state != null) {
            throw new IllegalStateException("state must be null");
        }
        Graphics2D graphics = (Graphics2D) g;
        try {
            PageViewport viewport = getPageViewport(pageIndex);
            AffineTransform at = graphics.getTransform();
            state = new Java2DGraphicsState(graphics, this.fontInfo, at);

            // reset the current Positions
            currentBPPosition = 0;
            currentIPPosition = 0;

            renderPageAreas(viewport.getPage());
            return PAGE_EXISTS;
        } catch (FOPException e) {
            log.error(e);
            return NO_SUCH_PAGE;
        } finally {
            state = null;
        }
    }

    /** {@inheritDoc} */
    protected void beginTextObject() {
        //not necessary in Java2D
    }

    /** {@inheritDoc} */
    protected void endTextObject() {
        //not necessary in Java2D
    }

    /**
     * Controls the page background.
     * @param transparentPageBackground true if the background should be transparent
     */
    public void setTransparentPageBackground(boolean transparentPageBackground) {
        this.transparentPageBackground = transparentPageBackground;
    }
}


text:
<!DOCTYPE html>

  <link rel="stylesheet" href="/assets/revealjs/css/reveal.css">
  <link rel="stylesheet" href="/assets/revealjs/css/theme/night.css" id="theme">

  # CR490
  # Cryptographie appliquée
  ## Cours 3

    ## Encryption par enveloppe
    Plus un protocole de gestion de clé que d'encryption, les clés seront encryptés mais l'important est la structure autour de la gestion des clés.

    ## Objectifs
    1. Limiter les risques si une clé est compromise, permet de suppléer à la rotation et non de la remplacer.
    1.1 Problématique de la rotation dans la quantité de données à rechiffrer à la fin de la cryptopériode.
    2. Utiliser une manière plus efficace les cryptomodules et HSM
    (Limiter la quantité d'information à envoyer au module/hsm sans envoyer l'ensemble des données et nécessiter des opérations lourdes au niveau du module.)

    ## Processus de chiffrement

    1. Une clé de chiffrement des clés (KEK) est générée.  Cette clé est conservée à un endroit sécuritaire (souvent, un HSM)
    2. Lorsque des données doivent être chiffrées, une clé de chiffrement de données (DEK) est générée.
    3. La clé de chiffrement des donnée est utilisée pour chiffrer les données.
    4. La clé de chiffrement des donnée est envoyé au HSM (ou autre module cryptographique) pour être chiffrée avec la KEK.
    5. La DEK chiffrée est enregistreée avec les données.

    ## Processus de chiffrement

    1. Lorsque des données doivent être chiffrées, la clé de chiffrement des données stockées avec les donnée elle-même est extraite.
    2. La clé de chiffrement des donnée est envoyé eau HSM (ou autre module cryptographique) pour être déchiffrée avec la KEK.
    3. La clé de chiffrement des donnée est utilisée pour déchiffrer les données.

    ## Exemple

    1. Lorsque des données doivent être chiffrées, la clé de chiffrement des données stockées avec les donnée elle-même est extraite.
    2. La clé de chiffrement des donnée est envoyé eau HSM (ou autre module cryptographique) pour être déchiffrée avec la KEK.
    3. La clé de chiffrement des donnée est utilisée pour déchiffrer les données.

     Il est également possible d'utiliser plusieurs clés DEK si un fichier est volumineux ou une par fichier qui seront toutes dépendantes de l'autorité centrale (HSM avec MEK).
     L'objectif d'une signature de clé dans GPG est de faire confiance au fournisseur de la clé, dans un contexte asymétrique, renforce l'identité autour de la clé.

    # Démo d'outils de gestion des clés

    ## Google CloudKMS
     Joue le rôle d'un HSM en générant des clés non exportables et de faire des opérations crypto, également protège CID et assure AAA.

     En tant qu'utilisateur, on ne peut voir le contenu de la clé, seulement son existence; elle est non exportable.

     Possible de donner des rôles (Autorisation) au niveau de la gestion des clés mais non du chiffrement des données en les utilisant, incapables de les unwrapper.

     ## Google CloudKMS
     Validation d'identité via 0Auth (Authentification) avant de permettre l'accès aux opérations cryptographiques.

     Dans l'activité, on peut voir ce qui s'est passé avec la clé (création, encryption, décryption, etc.) car les traces sont conservées (Audit).

     La taille du fichier augmente dans le chffrement car google enregistre des métadonnées avec le fichier (version de clé) la longueur des blocs fixe peut nécessiter du padding.

     Possible de désactiver une clé sans la détruire.

     Le KMS ne peut pas encrypter de grandes quantités de données, max 64k, retourne une erreur autrement; son utilité ne s'applique qu'au niveau de clés.

    ## Vault


text:
package syscallx

import "syscall"

// PhysicalMemorySize returns the total physical memory size.
func PhysicalMemorySize() (uint64, error) {
	var info syscall.Sysinfo_t
	if err := syscall.Sysinfo(&info); err != nil {
		return 0, err
	}
	return info.Totalram, nil
}

// FreeDiskSpace returns the free disk space for a given path.
func FreeDiskSpace(path string) (uint64, error) {
	var stat syscall.Statfs_t
	if err := syscall.Statfs(path, &stat); err != nil {
		return 0, err
	}
	return stat.Bavail * uint64(stat.Bsize), nil
}


text:
importScripts('Najtingalo.js');
onmessage = function(e) {
    setTimeout(function(){callBF(e.data)},0);
};
function callBF(data) {
    var heap = data.heap || [];
    var func = Najtingalo.toRunnable(data.code, Infinity);
    var ret = {
        output: [],
        bfCode: data.code,
        time: 0,
        input: data.input,
        memory: heap,
        func: (''+func)
    };
    var t0 = (self.performance || Date).now();

    func(heap, function output(character) {
                    myOutput.push(character);
                }, function input() {
                    return data.input.shift();
                });
    var t1 = (self.performance || Date).now();
    time = (window.performance ? '': 'less than')+(t1-t0)+' miliseconds';
    ret.output = ret.output.join('');
    postMessage(ret);
}


text:
import abc
import datetime
import enum
import typing

import jsii
import jsii.compat
import publication

from jsii.python import classproperty

import aws_cdk.assets
import aws_cdk.aws_iam
import aws_cdk.aws_s3
import aws_cdk.core
import aws_cdk.cx_api
__jsii_assembly__ = jsii.JSIIAssembly.load("@aws-cdk/aws-s3-assets", "1.15.0", __name__, "aws-s3-assets@1.15.0.jsii.tgz")
@jsii.implements(aws_cdk.assets.IAsset)
class Asset(aws_cdk.core.Construct, metaclass=jsii.JSIIMeta, jsii_type="@aws-cdk/aws-s3-assets.Asset"):
    """An asset represents a local file or directory, which is automatically uploaded to S3 and then can be referenced within a CDK application.

    stability
    :stability: experimental
    """
    def __init__(self, scope: aws_cdk.core.Construct, id: str, *, path: str, readers: typing.Optional[typing.List[aws_cdk.aws_iam.IGrantable]]=None, source_hash: typing.Optional[str]=None, exclude: typing.Optional[typing.List[str]]=None, follow: typing.Optional[aws_cdk.assets.FollowMode]=None) -> None:
        """
        :param scope: -
        :param id: -
        :param props: -
        :param path: The disk location of the asset. The path should refer to one of the following: - A regular file or a .zip file, in which case the file will be uploaded as-is to S3. - A directory, in which case it will be archived into a .zip file and uploaded to S3.
        :param readers: A list of principals that should be able to read this asset from S3. You can use ``asset.grantRead(principal)`` to grant read permissions later. Default: - No principals that can read file asset.
        :param source_hash: Custom source hash to use when identifying the specific version of the asset. NOTE: the source hash is used in order to identify a specific revision of the asset, and used for optimizing and caching deployment activities related to this asset such as packaging, uploading to Amazon S3, etc. If you chose to customize the source hash, you will need to make sure it is updated every time the source changes, or otherwise it is possible that some deployments will not be invalidated. Default: - automatically calculate source hash based on the contents of the source file or directory.
        :param exclude: Glob patterns to exclude from the copy. Default: nothing is excluded
        :param follow: A strategy for how to handle symlinks. Default: Never

        stability
        :stability: experimental
        """
        props = AssetProps(path=path, readers=readers, source_hash=source_hash, exclude=exclude, follow=follow)

        jsii.create(Asset, self, [scope, id, props])

    @jsii.member(jsii_name="addResourceMetadata")
    def add_resource_metadata(self, resource: aws_cdk.core.CfnResource, resource_property: str) -> None:
        """Adds CloudFormation template metadata to the specified resource with information that indicates which resource property is mapped to this local asset.

        This can be used by tools such as SAM CLI to provide local
        experience such as local invocation and debugging of Lambda functions.

        Asset metadata will only be included if the stack is synthesized with the
        "aws:cdk:enable-asset-metadata" context key defined, which is the default
        behavior when synthesizing via the CDK Toolkit.

        :param resource: The CloudFormation resource which is using this asset [disable-awslint:ref-via-interface].
        :param resource_property: The property name where this asset is referenced (e.g. "Code" for AWS::Lambda::Function).

        see
        :see: https://github.com/aws/aws-cdk/issues/1432
        stability
        :stability: experimental
        """
        return jsii.invoke(self, "addResourceMetadata", [resource, resource_property])

    @jsii.member(jsii_name="grantRead")
    def grant_read(self, grantee: aws_cdk.aws_iam.IGrantable) -> None:
        """Grants read permissions to the principal on the assets bucket.

        :param grantee: -

        stability
        :stability: experimental
        """
        return jsii.invoke(self, "grantRead", [grantee])

    @property
    @jsii.member(jsii_name="assetPath")
    def asset_path(self) -> str:
        """The path to the asset (stringinfied token).

        If asset staging is disabled, this will just be the original path.
        If asset staging is enabled it will be the staged path.

        stability
        :stability: experimental
        """
        return jsii.get(self, "assetPath")

    @property
    @jsii.member(jsii_name="bucket")
    def bucket(self) -> aws_cdk.aws_s3.IBucket:
        """The S3 bucket in which this asset resides.

        stability
        :stability: experimental
        """
        return jsii.get(self, "bucket")

    @property
    @jsii.member(jsii_name="isZipArchive")
    def is_zip_archive(self) -> bool:
        """Indicates if this asset is a zip archive.

        Allows constructs to ensure that the
        correct file type was used.

        stability
        :stability: experimental
        """
        return jsii.get(self, "isZipArchive")

    @property
    @jsii.member(jsii_name="s3BucketName")
    def s3_bucket_name(self) -> str:
        """Attribute that represents the name of the bucket this asset exists in.

        stability
        :stability: experimental
        """
        return jsii.get(self, "s3BucketName")

    @property
    @jsii.member(jsii_name="s3ObjectKey")
    def s3_object_key(self) -> str:
        """Attribute which represents the S3 object key of this asset.

        stability
        :stability: experimental
        """
        return jsii.get(self, "s3ObjectKey")

    @property
    @jsii.member(jsii_name="s3Url")
    def s3_url(self) -> str:
        """Attribute which represents the S3 URL of this asset.

        stability
        :stability: experimental

        Example::
            # Example may have issues. See https://github.com/aws/jsii/issues/826
            https:
        """
        return jsii.get(self, "s3Url")

    @property
    @jsii.member(jsii_name="sourceHash")
    def source_hash(self) -> str:
        """A hash of the source of this asset, which is available at construction time.

        As this is a plain
        string, it can be used in construct IDs in order to enforce creation of a new resource when
        the content hash has changed.

        stability
        :stability: experimental
        """
        return jsii.get(self, "sourceHash")

@jsii.data_type(jsii_type="@aws-cdk/aws-s3-assets.AssetOptions", jsii_struct_bases=[aws_cdk.assets.CopyOptions], name_mapping={'exclude': 'exclude', 'follow': 'follow', 'readers': 'readers', 'source_hash': 'sourceHash'})
class AssetOptions(aws_cdk.assets.CopyOptions):
    def __init__(self, *, exclude: typing.Optional[typing.List[str]]=None, follow: typing.Optional[aws_cdk.assets.FollowMode]=None, readers: typing.Optional[typing.List[aws_cdk.aws_iam.IGrantable]]=None, source_hash: typing.Optional[str]=None):
        """
        :param exclude: Glob patterns to exclude from the copy. Default: nothing is excluded
        :param follow: A strategy for how to handle symlinks. Default: Never
        :param readers: A list of principals that should be able to read this asset from S3. You can use ``asset.grantRead(principal)`` to grant read permissions later. Default: - No principals that can read file asset.
        :param source_hash: Custom source hash to use when identifying the specific version of the asset. NOTE: the source hash is used in order to identify a specific revision of the asset, and used for optimizing and caching deployment activities related to this asset such as packaging, uploading to Amazon S3, etc. If you chose to customize the source hash, you will need to make sure it is updated every time the source changes, or otherwise it is possible that some deployments will not be invalidated. Default: - automatically calculate source hash based on the contents of the source file or directory.

        stability
        :stability: experimental
        """
        self._values = {
        }
        if exclude is not None: self._values["exclude"] = exclude
        if follow is not None: self._values["follow"] = follow
        if readers is not None: self._values["readers"] = readers
        if source_hash is not None: self._values["source_hash"] = source_hash

    @property
    def exclude(self) -> typing.Optional[typing.List[str]]:
        """Glob patterns to exclude from the copy.

        default
        :default: nothing is excluded

        stability
        :stability: experimental
        """
        return self._values.get('exclude')

    @property
    def follow(self) -> typing.Optional[aws_cdk.assets.FollowMode]:
        """A strategy for how to handle symlinks.

        default
        :default: Never

        stability
        :stability: experimental
        """
        return self._values.get('follow')

    @property
    def readers(self) -> typing.Optional[typing.List[aws_cdk.aws_iam.IGrantable]]:
        """A list of principals that should be able to read this asset from S3. You can use ``asset.grantRead(principal)`` to grant read permissions later.

        default
        :default: - No principals that can read file asset.

        stability
        :stability: experimental
        """
        return self._values.get('readers')

    @property
    def source_hash(self) -> typing.Optional[str]:
        """Custom source hash to use when identifying the specific version of the asset.

        NOTE: the source hash is used in order to identify a specific revision of the asset,
        and used for optimizing and caching deployment activities related to this asset such as
        packaging, uploading to Amazon S3, etc. If you chose to customize the source hash,
        you will need to make sure it is updated every time the source changes, or otherwise
        it is possible that some deployments will not be invalidated.

        default
        :default:

        - automatically calculate source hash based on the contents
          of the source file or directory.

        stability
        :stability: experimental
        """
        return self._values.get('source_hash')

    def __eq__(self, rhs) -> bool:
        return isinstance(rhs, self.__class__) and rhs._values == self._values

    def __ne__(self, rhs) -> bool:
        return not (rhs == self)

    def __repr__(self) -> str:
        return 'AssetOptions(%s)' % ', '.join(k + '=' + repr(v) for k, v in self._values.items())

@jsii.data_type(jsii_type="@aws-cdk/aws-s3-assets.AssetProps", jsii_struct_bases=[AssetOptions], name_mapping={'exclude': 'exclude', 'follow': 'follow', 'readers': 'readers', 'source_hash': 'sourceHash', 'path': 'path'})
class AssetProps(AssetOptions):
    def __init__(self, *, exclude: typing.Optional[typing.List[str]]=None, follow: typing.Optional[aws_cdk.assets.FollowMode]=None, readers: typing.Optional[typing.List[aws_cdk.aws_iam.IGrantable]]=None, source_hash: typing.Optional[str]=None, path: str):
        """
        :param exclude: Glob patterns to exclude from the copy. Default: nothing is excluded
        :param follow: A strategy for how to handle symlinks. Default: Never
        :param readers: A list of principals that should be able to read this asset from S3. You can use ``asset.grantRead(principal)`` to grant read permissions later. Default: - No principals that can read file asset.
        :param source_hash: Custom source hash to use when identifying the specific version of the asset. NOTE: the source hash is used in order to identify a specific revision of the asset, and used for optimizing and caching deployment activities related to this asset such as packaging, uploading to Amazon S3, etc. If you chose to customize the source hash, you will need to make sure it is updated every time the source changes, or otherwise it is possible that some deployments will not be invalidated. Default: - automatically calculate source hash based on the contents of the source file or directory.
        :param path: The disk location of the asset. The path should refer to one of the following: - A regular file or a .zip file, in which case the file will be uploaded as-is to S3. - A directory, in which case it will be archived into a .zip file and uploaded to S3.

        stability
        :stability: experimental
        """
        self._values = {
            'path': path,
        }
        if exclude is not None: self._values["exclude"] = exclude
        if follow is not None: self._values["follow"] = follow
        if readers is not None: self._values["readers"] = readers
        if source_hash is not None: self._values["source_hash"] = source_hash

    @property
    def exclude(self) -> typing.Optional[typing.List[str]]:
        """Glob patterns to exclude from the copy.

        default
        :default: nothing is excluded

        stability
        :stability: experimental
        """
        return self._values.get('exclude')

    @property
    def follow(self) -> typing.Optional[aws_cdk.assets.FollowMode]:
        """A strategy for how to handle symlinks.

        default
        :default: Never

        stability
        :stability: experimental
        """
        return self._values.get('follow')

    @property
    def readers(self) -> typing.Optional[typing.List[aws_cdk.aws_iam.IGrantable]]:
        """A list of principals that should be able to read this asset from S3. You can use ``asset.grantRead(principal)`` to grant read permissions later.

        default
        :default: - No principals that can read file asset.

        stability
        :stability: experimental
        """
        return self._values.get('readers')

    @property
    def source_hash(self) -> typing.Optional[str]:
        """Custom source hash to use when identifying the specific version of the asset.

        NOTE: the source hash is used in order to identify a specific revision of the asset,
        and used for optimizing and caching deployment activities related to this asset such as
        packaging, uploading to Amazon S3, etc. If you chose to customize the source hash,
        you will need to make sure it is updated every time the source changes, or otherwise
        it is possible that some deployments will not be invalidated.

        default
        :default:

        - automatically calculate source hash based on the contents
          of the source file or directory.

        stability
        :stability: experimental
        """
        return self._values.get('source_hash')

    @property
    def path(self) -> str:
        """The disk location of the asset.

        The path should refer to one of the following:

        - A regular file or a .zip file, in which case the file will be uploaded as-is to S3.
        - A directory, in which case it will be archived into a .zip file and uploaded to S3.

        stability
        :stability: experimental
        """
        return self._values.get('path')

    def __eq__(self, rhs) -> bool:
        return isinstance(rhs, self.__class__) and rhs._values == self._values

    def __ne__(self, rhs) -> bool:
        return not (rhs == self)

    def __repr__(self) -> str:
        return 'AssetProps(%s)' % ', '.join(k + '=' + repr(v) for k, v in self._values.items())

__all__ = ["Asset", "AssetOptions", "AssetProps", "__jsii_assembly__"]

publication.publish()


text:
package com.google.cloud.firestore;

import com.google.api.core.ApiAsyncFunction;
import com.google.api.core.ApiFunction;
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutureCallback;
import com.google.api.core.ApiFutures;
import com.google.api.core.CurrentMillisClock;
import com.google.api.core.SettableApiFuture;
import com.google.api.gax.retrying.ExponentialRetryAlgorithm;
import com.google.api.gax.retrying.TimedAttemptSettings;
import com.google.api.gax.rpc.ApiException;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.MoreExecutors;
import io.grpc.Context;
import io.opencensus.trace.AttributeValue;
import io.opencensus.trace.Span;
import io.opencensus.trace.Tracer;
import io.opencensus.trace.Tracing;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Implements backoff and retry semantics for Firestore transactions.
 *
 *
A TransactionRunner is instantiated with a `userCallback`, a `userCallbackExecutor` and
 * `numberOfAttempts`. Upon invoking {@link #run()}, the class invokes the provided callback on the
 * specified executor at most `numberOfAttempts` times. {@link #run()} returns an ApiFuture that
 * resolves when all retries complete.
 *
 *
TransactionRunner uses exponential backoff to increase the chance that retries succeed. To
 * customize the backoff settings, you can specify custom settings via {@link FirestoreOptions}.
 */
class TransactionRunner<T> {

  private static final Tracer tracer = Tracing.getTracer();
  private static final io.opencensus.trace.Status TOO_MANY_RETRIES_STATUS =
      io.opencensus.trace.Status.ABORTED.withDescription("too many retries");
  private static final io.opencensus.trace.Status USER_CALLBACK_FAILED =
      io.opencensus.trace.Status.ABORTED.withDescription("user callback failed");

  private final Transaction.AsyncFunction<T> userCallback;
  private final Span span;
  private final FirestoreImpl firestore;
  private final ScheduledExecutorService firestoreExecutor;
  private final Executor userCallbackExecutor;
  private final ExponentialRetryAlgorithm backoffAlgorithm;
  private final TransactionOptions transactionOptions;
  private TimedAttemptSettings nextBackoffAttempt;
  private Transaction transaction;
  private int attemptsRemaining;

  /**
   * @param firestore The active Firestore instance
   * @param userCallback The user provided transaction callback
   * @param transactionOptions The options determining which executor the {@code userCallback} is
   *     run on and whether the transaction is read-write or read-only
   */
  TransactionRunner(
      FirestoreImpl firestore,
      Transaction.AsyncFunction<T> userCallback,
      TransactionOptions transactionOptions) {
    this.transactionOptions = transactionOptions;
    this.span = tracer.spanBuilder("CloudFirestore.Transaction").startSpan();
    this.firestore = firestore;
    this.firestoreExecutor = firestore.getClient().getExecutor();
    this.userCallback = userCallback;
    this.attemptsRemaining = transactionOptions.getNumberOfAttempts();
    this.userCallbackExecutor =
        Context.currentContextExecutor(
            transactionOptions.getExecutor() != null
                ? transactionOptions.getExecutor()
                : this.firestore.getClient().getExecutor());

    this.backoffAlgorithm =
        new ExponentialRetryAlgorithm(
            firestore.getOptions().getRetrySettings(), CurrentMillisClock.getDefaultClock());
    this.nextBackoffAttempt = backoffAlgorithm.createFirstAttempt();
  }

  ApiFuture<T> run() {
    this.transaction = new Transaction(firestore, transactionOptions, this.transaction);

    --attemptsRemaining;

    span.addAnnotation(
        "Start runTransaction",
        ImmutableMap.of("attemptsRemaining", AttributeValue.longAttributeValue(attemptsRemaining)));

    return ApiFutures.catchingAsync(
        ApiFutures.transformAsync(
            maybeRollback(), new RollbackCallback(), MoreExecutors.directExecutor()),
        Throwable.class,
        new RestartTransactionCallback(),
        MoreExecutors.directExecutor());
  }

  private ApiFuture<Void> maybeRollback() {
    return transaction.hasTransactionId()
        ? transaction.rollback()
        : ApiFutures.immediateFuture(null);
  }

  /** A callback that invokes the BeginTransaction callback. */
  private class RollbackCallback implements ApiAsyncFunction<Void, T> {
    @Override
    public ApiFuture<T> apply(Void input) {
      final SettableApiFuture<Void> backoff = SettableApiFuture.create();
      // Add a backoff delay. At first, this is 0.
      firestoreExecutor.schedule(
          () -> {
            backoff.set(null);
          },
          nextBackoffAttempt.getRandomizedRetryDelay().toMillis(),
          TimeUnit.MILLISECONDS);

      nextBackoffAttempt = backoffAlgorithm.createNextAttempt(nextBackoffAttempt);
      return ApiFutures.transformAsync(
          backoff, new BackoffCallback(), MoreExecutors.directExecutor());
    }
  }

  /**
   * Invokes the user callback on the user callback executor and returns the user-provided result.
   */
  private SettableApiFuture<T> invokeUserCallback() {
    final SettableApiFuture<T> returnedResult = SettableApiFuture.create();

    userCallbackExecutor.execute(
        () -> {
          ApiFuture<T> userCallbackResult;
          try {
            userCallbackResult = userCallback.updateCallback(transaction);
          } catch (Exception e) {
            userCallbackResult = ApiFutures.immediateFailedFuture(e);
          }
          ApiFutures.addCallback(
              userCallbackResult,
              new ApiFutureCallback<T>() {
                @Override
                public void onFailure(Throwable t) {
                  returnedResult.setException(t);
                }

                @Override
                public void onSuccess(T result) {
                  returnedResult.set(result);
                }
              },
              firestoreExecutor);
        });
    return returnedResult;
  }

  /** A callback that invokes the BeginTransaction callback. */
  private class BackoffCallback implements ApiAsyncFunction<Void, T> {
    @Override
    public ApiFuture<T> apply(Void input) {
      return ApiFutures.transformAsync(
          transaction.begin(), new BeginTransactionCallback(), MoreExecutors.directExecutor());
    }
  }

  /**
   * The callback for the BeginTransaction RPC, which invokes the user callback and handles all
   * errors thereafter.
   */
  private class BeginTransactionCallback implements ApiAsyncFunction<Void, T> {
    public ApiFuture<T> apply(Void ignored) {
      return ApiFutures.transformAsync(
          invokeUserCallback(), new UserFunctionCallback(), MoreExecutors.directExecutor());
    }
  }

  /**
   * The callback that is invoked after the user function finishes execution. It invokes the Commit
   * RPC.
   */
  private class UserFunctionCallback implements ApiAsyncFunction<T, T> {
    @Override
    public ApiFuture<T> apply(T userFunctionResult) {
      return ApiFutures.transform(
          transaction.commit(),
          new CommitTransactionCallback(userFunctionResult),
          MoreExecutors.directExecutor());
    }
  }

  /** The callback that is invoked after the Commit RPC returns. It returns the user result. */
  private class CommitTransactionCallback implements ApiFunction<List<WriteResult>, T> {
    private final T userFunctionResult;

    CommitTransactionCallback(T userFunctionResult) {
      this.userFunctionResult = userFunctionResult;
    }

    @Override
    public T apply(List<WriteResult> input) {
      span.setStatus(io.opencensus.trace.Status.OK);
      span.end();
      return userFunctionResult;
    }
  }

  /** A callback that restarts a transaction after an ApiException. It invokes the Rollback RPC. */
  private class RestartTransactionCallback implements ApiAsyncFunction<Throwable, T> {
    public ApiFuture<T> apply(Throwable throwable) {
      if (!(throwable instanceof ApiException)) {
        // This is likely a failure in the user callback.
        span.setStatus(USER_CALLBACK_FAILED);
        return rollbackAndReject(throwable);
      }

      ApiException apiException = (ApiException) throwable;
      if (transaction.hasTransactionId() && isRetryableTransactionError(apiException)) {
        if (attemptsRemaining > 0) {
          span.addAnnotation("retrying");
          return run();
        } else {
          span.setStatus(TOO_MANY_RETRIES_STATUS);
          final FirestoreException firestoreException =
              FirestoreException.forApiException(
                  apiException, "Transaction was cancelled because of too many retries.");
          return rollbackAndReject(firestoreException);
        }
      } else {
        span.setStatus(TraceUtil.statusFromApiException(apiException));
        final FirestoreException firestoreException =
            FirestoreException.forApiException(
                apiException, "Transaction failed with non-retryable error");
        return rollbackAndReject(firestoreException);
      }
    }

    /** Determines whether the provided error is considered retryable. */
    private boolean isRetryableTransactionError(ApiException exception) {
      switch (exception.getStatusCode().getCode()) {
          // This list is based on
          // https://github.com/firebase/firebase-js-sdk/blob/c822e78b00dd3420dcc749beb2f09a947aa4a344/packages/firestore/src/core/transaction_runner.ts#L112
        case ABORTED:
        case CANCELLED:
        case UNKNOWN:
        case DEADLINE_EXCEEDED:
        case INTERNAL:
        case UNAVAILABLE:
        case UNAUTHENTICATED:
        case RESOURCE_EXHAUSTED:
          return true;
        case INVALID_ARGUMENT:
          // The Firestore backend uses "INVALID_ARGUMENT" for transactions IDs that have expired.
          // While INVALID_ARGUMENT is generally not retryable, we retry this specific case.
          return exception.getMessage().contains("transaction has expired");
        default:
          return false;
      }
    }

    /** Rolls the transaction back and returns the error. */
    private ApiFuture<T> rollbackAndReject(final Throwable throwable) {
      final SettableApiFuture<T> failedTransaction = SettableApiFuture.create();

      if (transaction.hasTransactionId()) {
        // We use `addListener()` since we want to return the original exception regardless of
        // whether rollback() succeeds.
        transaction
            .rollback()
            .addListener(
                () -> failedTransaction.setException(throwable), MoreExecutors.directExecutor());
      } else {
        failedTransaction.setException(throwable);
      }

      span.end();
      return failedTransaction;
    }
  }
}