text:
<?php
class curlRequest{
    private $cookie;
    private $response_cookie;
    private $header=array();
    private $response_code;
    private $response;
    public function setCookie($arr)
    {
        $this->cookie='';
        foreach($arr as $key=>&$value)
        {
            $this->cookie=$this->cookie . ' '. htmlspecialchars($key) . "=" . htmlspecialchars($value) .';';
        }
        $this->cookie= substr($this->cookie,0,strlen($this->cookie)-1);
    }
    public function setHeader($value)
    {
        $this->header[]=$value;
    }
    public function setCookieRaw($cookie)
    {
        $this->cookie=$cookie;
    }
    public function post($url, $post,$timeout=10)
    {
        $request_data='';
        if(is_array($post))
        {
            $request_array=array();
            foreach($post as $key=>&$one)
            {
                $request_array[]=urlencode($key) . "=" . urlencode($one);
            }
            $request_data=implode("&",$request_array);
        }
        else
            $request_data=$post;

        $defaults = array(
            CURLOPT_POST => 1,
            CURLOPT_HEADER => 0,
            CURLOPT_URL => $url,
            CURLOPT_FRESH_CONNECT => 1,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_FORBID_REUSE => 1,
            CURLOPT_TIMEOUT => $timeout,
            CURLOPT_POSTFIELDS =>$request_data
        );

        $ch = curl_init();
        //curl_setopt ($ch, CURLOPT_PROXY, "127.0.0.1:8888");
        curl_setopt_array($ch, ( $defaults));
        curl_setopt($ch,CURLOPT_COOKIE,$this->cookie);
        if(!empty($this->header))
            curl_setopt($ch,CURLOPT_HTTPHEADER,$this->header);
        $cookie_filename=tempnam(sys_get_temp_dir(),"scutvj");
        curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_filename);
        $this->response_code=0;
        $result = curl_exec($ch);
        $this->response=$result;
        $this->response_code=curl_getinfo($ch,CURLINFO_HTTP_CODE );
        $error=curl_error($ch);
        curl_close($ch);
        $this->response_cookie=$this->processCookieJar(file_get_contents($cookie_filename));
        unlink($cookie_filename);
        if( ! $result)
        {
            echo $error;
            return false;
        }

        return $result;
    }
    public function get($url,$timeout=10)
    {
        $defaults = array(
            CURLOPT_HEADER => 0,
            CURLOPT_URL => $url,
            CURLOPT_FRESH_CONNECT => 1,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_FORBID_REUSE => 1,
            CURLOPT_TIMEOUT => $timeout
        );

        $ch = curl_init();
        curl_setopt_array($ch, ( $defaults));
        curl_setopt($ch,CURLOPT_COOKIE,$this->cookie);
        $this->response_code=0;

        if(!empty($this->header))
            curl_setopt($ch,CURLOPT_HTTPHEADER,$this->header);
        $cookie_filename=tempnam(sys_get_temp_dir(),"scutvj");
        curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_filename);
        $this->response_code=0;
        $result = curl_exec($ch);
        $this->response=$result;
        $this->response_code=curl_getinfo($ch,CURLINFO_HTTP_CODE );
        $error=curl_error($ch);
        curl_close($ch);
        $this->response_cookie=$this->processCookieJar(file_get_contents($cookie_filename));
        unlink($cookie_filename);

        if( ! $result)
        {
            echo $error;
            return false;
        }

        return $result;
    }
    public function getResponseCookie()
    {
        return $this->response_cookie;
    }
    public function getResponseCode()
    {
        return $this->response_code;
    }
    private function processCookieJar($str)
    {
        $str=str_replace("\t"," ",$str);
        $str=str_replace("\r","",$str);
        $arr=explode("\n",$str);
        $ret=array();
        foreach ($arr as $one) {
            $two=explode(" ",$one);
            if(count($two)!=7)
                continue;
            $ret[$two[5]]=$two[6];
        }
        return $this->cookieArr2Str($ret);

    }
    public function cookieArr2Str($arr)
    {
        $cookie="";
        foreach($arr as $key=>&$value)
        {
            $cookie=$cookie . ' '. htmlspecialchars($key) . "=" . htmlspecialchars($value) .';';
        }
        return substr($cookie,0,strlen($cookie)-1);
    }
    public function cookieStr2Arr($str)
    {
        $ret=array();
        $one=explode(";",$str);
        foreach($one as $two)
        {
            $three=explode("=",$two);
            if(count($three)==2)
                $ret[trim($three[0])]=trim($three[1]);
        }
        return $ret;
    }
}


text:
var express = require('express');
var request = require('request');
var router = express.Router();
var timeoutGlobal = 2000;

/* GET home page. */
router.get('/dashboard', function(req, res, next) {
	var data = {};
	data.layout = 'rrhh/base/layout';
	data.cantidadCargos = 2;
	data.cantidadDepartamentos = 2;
	data.cantidadTrabajadores = 0;

	request.get({url: req.servicios.rrhh.trabajadores.get_all, timeout:timeoutGlobal}, function(err,response,body){
		console.log("obtener listado de trabajadores...")
		if (!err && response.statusCode == 200) {
			var temp = JSON.parse(body);

			data.cantidadTrabajadores = temp.length;
			res.render('rrhh/index', data);
	  	}
	}).on('error', function(){
		data.codigo = -1;
		data.mensaje = "Ocurrio un problema al listar a los trabajadores, vuelva a intentarlo dentro de unos momentos.";
		res.render('rrhh/listarTrabajadores', data);
	});

});

/*.................................TRABAJADORES.................................................*/

/*GET pagina listado de trabajadores*/
router.get('/listarTrabajadores', function(req, res, next) {
	var data = {};
	data.layout ='rrhh/base/layout';

	request.get({url: req.servicios.rrhh.trabajadores.get_all, timeout:timeoutGlobal}, function(err,response,body){
		console.log("obtener listado de trabajadores...")
		if (!err && response.statusCode == 200) {
			data.trabajadores = JSON.parse(body);
			res.render('rrhh/listarTrabajadores', data);
	  	}
	}).on('error', function(){
		data.codigo = -1;
		data.mensaje = "Ocurrio un problema al listar a los trabajadores, vuelva a intentarlo dentro de unos momentos.";
		res.render('rrhh/listarTrabajadores', data);
	});
});

/*GET Obtiene un objeto JSON con los datos de un trabajador obtenido por rut.*/
router.get('/getTrabajadorByRut', function(req, res, next) {
	var rut = req.query.rut;
	console.log(rut);
	var data = {};
	request.get({url:req.servicios.rrhh.trabajadores.get_by_rut, timeout:timeoutGlobal, qs:{rut:rut}}, function(err,response,body){
		console.log("obtener trabajador")
		if (!err && response.statusCode == 200) {
	    	data = JSON.parse(body);
	    	console.log(data);
			res.json(data);
	  	}

	}).on('error', function(){
		data.codigo = -1;
		data.mensaje = "Ocurrio un problema al obtener al trabajador, vuelva a intentarlo dentro de unos momentos.";
		res.json(data);
	});
});

/*POST modifica los datos de un trabajador mediante AJAX*/
router.post('/modificar_trabajador', function(req, res, next) {
	var id_trabajador = req.body.id_trabajador;
	var rut = req.body.rut;
	var nombre = req.body.nombre;
	var apellido = req.body.apellido;
	var email = req.body.email;
	var password = req.body.password;
	var telefono = req.body.telefono;
	var fecha_contratacion = req.body.fecha_contratacion;
	var sueldo = req.body.sueldo;
	var id_departamento_fk = req.body.id_departamento_fk;
	var id_cargo_fk = req.body.id_cargo_fk;

	var data = {};

	request.put({url: req.servicios.rrhh.trabajadores.modify_by_rut, timeout:timeoutGlobal,
		form: {id_trabajador : id_trabajador, rut : rut, nombre : nombre, apellido : apellido,
			email : email, password : password, telefono : telefono, fecha_contratacion : fecha_contratacion,
			sueldo : sueldo, id_departamento_fk : id_departamento_fk, id_cargo_fk : id_cargo_fk}}, function(err,response,body){

		console.log("modificar trabajador")
		if (!err && response.statusCode == 200) {
	    	data.codigo = JSON.parse(body);
	    	data.mensaje = "Modificacion Exitosa."
	    	res.json(data);
	  	}

	}).on('error', function(){
		data.codigo = -1;
		data.mensaje = "Ocurrio un problema al modificar al trabajador, vuelva a intentarlo dentro de unos momentos.";
		res.json(data);
	});
});

/*POST Elimina trabajador por RUT mediante AJAX*/
router.post('/eliminarTrabajadorById', function(req, res, next) {
	var rut = req.body.rut;
	console.log(rut);

	var data = {};

	request.del({url:req.servicios.rrhh.trabajadores.delete_by_rut, timeout:timeoutGlobal,
		form: {rut : rut}, qs:{rut : rut}}, function(err,response,body){

		console.log("Eliminar trabajador")
		if (!err && response.statusCode == 200) {
	    	data.codigo = JSON.parse(body);
			res.json(data)
	  	}

	  	;
	}).on('error', function(){
		data.codigo = -1;
		data.mensaje = "Ocurrio un problema al eliminar al trabajador, vuelva a intentarlo dentro de unos momentos.";
		res.json(data);
	});
});

/*GET Despliega pagina para el ingreso de trabajadores*/
router.get('/ingresarTrabajador', function(req, res, next) {
	console.log("Ingresar trabajador");
	var data = {};
	data.layout = 'rrhh/base/layout';
	res.render('rrhh/ingresarTrabajador', data);
});

/*POST metodo que mediante peticion AJAX ingresa un trabajador*/
router.post('/add_trabajador', function(req, res, next) {
	var data = {};
	var rut = req.body.rut;
	var nombre = req.body.nombre;
	var apellido = req.body.apellido;
	var email = req.body.email;
	var password = req.body.password;
	var telefono = req.body.telefono;
	var fecha_contratacion = req.body.fecha_contratacion;
	var sueldo = req.body.sueldo;
	var nombreDepartamento = req.body.id_departamento_fk;
	var nombreCargo = req.body.id_cargo_fk;

	//ingresar el trabajador
	request.post({url:req.servicios.rrhh.trabajadores.add_trabajador, timeout:timeoutGlobal,
		form: {rut : rut, nombre : nombre, apellido : apellido,
			email : email, password : password, telefono : telefono, fecha_contratacion : fecha_contratacion,
			sueldo : sueldo, id_departamento_fk : nombreDepartamento, id_cargo_fk : nombreCargo} }, function(err,response,body){

			if (!err && response.statusCode == 200) {
				//console.log(JSON.parse(body)); //body trae los datos del trabajador
				data.mensaje = "Trabajador ingresado correctamente";
				data.codigo = response.statusCode;
				res.json(data);
		  	}else{
		  		//Manejdo de errores del servicio
		  		if(!err && response.statusCode==500){
		  			var parse = JSON.parse(body);
		  			console.log(parse);
		  			if(parse.code==11000){
		  				data.codigo=11000;
		  				data.mensaje="Error, email ya existe.";

		  			}
		  			res.json(data);
		  		}
		  	}

	}).on('error', function(){
		data.codigo = -1;
		data.mensaje = "Ocurrio un problema al ingresar al trabajador, vuelva a intentarlo dentro de unos momentos.";
		res.json(data);
	});
});

module.exports = router;

redpajama_set_name: RedPajamaGithub


text:
package com.google.j2cl.ported.java6;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests Autoboxing. */
@RunWith(JUnit4.class)
@SuppressWarnings("BoxedPrimitiveConstructor")
public class AutoboxTest {

  private Boolean boxedBoolean = Boolean.TRUE;

  private Byte boxedByte = new Byte((byte) 0xAB);

  private Character boxedChar = new Character('c');

  private Double boxedDouble = new Double(1.2323);

  private Float boxedFloat = new Float(1.2F);

  private Integer boxedInt = new Integer(20000000);

  private Long boxedLong = new Long(1231231231231L);

  private Short boxedShort = new Short((short) 6550);

  private boolean unboxedBoolean = true;

  private byte unboxedByte = (byte) 0xAB;

  private char unboxedChar = 'c';

  private double unboxedDouble = 1.2323;

  private float unboxedFloat = 1.2F;

  private int unboxedInt = 20000000;

  private long unboxedLong = 1231231231231L;

  private short unboxedShort = 6550;

  @Test
  public void testBoxing() {
    Boolean boolean_ = unboxedBoolean;
    assertThat(boolean_.booleanValue() == unboxedBoolean).isTrue();
    Byte byte_ = unboxedByte;
    assertThat(byte_.byteValue() == unboxedByte).isTrue();
    Character char_ = unboxedChar;
    assertThat(char_.charValue() == unboxedChar).isTrue();
    Short short_ = unboxedShort;
    assertThat(short_.shortValue() == unboxedShort).isTrue();
    Integer int_ = unboxedInt;
    assertThat(int_.intValue() == unboxedInt).isTrue();
    Long long_ = unboxedLong;
    assertThat(long_.longValue() == unboxedLong).isTrue();
    Float float_ = unboxedFloat;
    assertThat(float_.floatValue() == unboxedFloat).isTrue();
    Double double_ = unboxedDouble;
    assertThat(double_.doubleValue() == unboxedDouble).isTrue();

    // test boxing of return values
    assertThat(box(unboxedBoolean).booleanValue() == unboxedBoolean).isTrue();
    assertThat(box(unboxedByte).byteValue() == unboxedByte).isTrue();
    assertThat(box(unboxedShort).shortValue() == unboxedShort).isTrue();
    assertThat(box(unboxedChar).charValue() == unboxedChar).isTrue();
    assertThat(box(unboxedInt).intValue() == unboxedInt).isTrue();
    assertThat(box(unboxedLong).longValue() == unboxedLong).isTrue();
    assertThat(box(unboxedFloat).floatValue() == unboxedFloat).isTrue();
    assertThat(box(unboxedDouble).doubleValue() == unboxedDouble).isTrue();

    // test boxing of parameters
    assertThat(unbox(unboxedBoolean) == unboxedBoolean).isTrue();
    assertThat(unbox(unboxedByte) == unboxedByte).isTrue();
    assertThat(unbox(unboxedShort) == unboxedShort).isTrue();
    assertThat(unbox(unboxedChar) == unboxedChar).isTrue();
    assertThat(unbox(unboxedInt) == unboxedInt).isTrue();
    assertThat(unbox(unboxedLong) == unboxedLong).isTrue();
    assertThat(unbox(unboxedFloat) == unboxedFloat).isTrue();
    assertThat(unbox(unboxedDouble) == unboxedDouble).isTrue();
  }

  /**
   * JLS 5.2 has a special case for assignment of a constant to a variable of type Byte, Short, or
   * Character. Such an assignment is allowed so long as the constant fits within the type's range.
   * In such cases, the box type can be different from the type of the constant.
   */
  @Test
  public void testBoxingDifferentType() {
    Character c = 1;
    assertThat((Object) c).isEqualTo(Character.valueOf((char) 1));

    Byte b = 2;
    assertThat((Object) b).isEqualTo(Byte.valueOf((byte) 2));

    Short s = 3;
    assertThat((Object) s).isEqualTo(Short.valueOf((short) 3));
  }

  /** Verify that .valueOf() methods return identical references for types within certain ranges. */
  @Test
  public void testCaching() {
    assertThat((byte) 3).isSameInstanceAs((byte) 3);
    assertThat('A').isSameInstanceAs('A');
    assertThat((short) 120).isSameInstanceAs((short) 120);
    assertThat(-13).isSameInstanceAs(-13);
    assertThat(7L).isSameInstanceAs(7L);
  }

  /**
   * Test ++, --, and compound assignments like += when the left-hand side is a boxed Integer. Use
   * assertNotSame to ensure that a new Integer is created instead of modifying the original integer
   * in place. (Issue 2446).
   */
  @Test
  public void testCompoundAssignmentsWithInteger() {
    {
      Integer operand;
      Integer original;
      Integer result;

      original = operand = 0;
      result = operand++;
      // operand must be different object now.
      assertWithMessage("[o++] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[o++] original == result, ").that(result).isSameInstanceAs(original);
      assertWithMessage("[o++] result != operand, ").that(operand).isNotSameInstanceAs(result);
      // checks against boxedvalues cached object.
      assertWithMessage("[o++] valueOf(n) == operand, ").that(operand).isSameInstanceAs(1);
      // checks cached object's value.
      assertWithMessage("[o++] n == operand.value, ").that(operand.intValue()).isEqualTo(1);
    }

    {
      Integer operand;
      Integer original;
      Integer result;
      original = operand = 2;
      result = ++operand;
      assertWithMessage("[++o] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[++o] original != result, ").that(result).isNotSameInstanceAs(original);
      assertWithMessage("[++o] result == operand, ").that(operand).isSameInstanceAs(result);
      assertWithMessage("[++o] valueOf(n) == operand, ").that(operand).isSameInstanceAs(3);
      assertWithMessage("[++o] n == operand.value, ").that(operand.intValue()).isEqualTo(3);
    }

    {
      Integer operand;
      Integer original;
      Integer result;
      original = operand = 5;
      result = operand--;
      assertWithMessage("[o--] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[o--] original == result, ").that(result).isSameInstanceAs(original);
      assertWithMessage("[o--] result != operand, ").that(operand).isNotSameInstanceAs(result);
      assertWithMessage("[o--] valueOf(n) == operand, ").that(operand).isSameInstanceAs(4);
      assertWithMessage("[o--] n == operand.value, ").that(operand.intValue()).isEqualTo(4);
    }

    {
      Integer operand;
      Integer original;
      Integer result;
      original = operand = 7;
      result = --operand;
      assertWithMessage("[--o] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[--o] original != result, ").that(result).isNotSameInstanceAs(original);
      assertWithMessage("[--o] result == operand, ").that(operand).isSameInstanceAs(result);
      assertWithMessage("[--o] valueOf(n) == operand, ").that(operand).isSameInstanceAs(6);
      assertWithMessage("[--o] n == operand.value, ").that(operand.intValue()).isEqualTo(6);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 8;
      operand += 2;
      assertWithMessage("[+=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[+=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(10);
      assertWithMessage("[+=] n == operand.value, ").that(operand.intValue()).isEqualTo(10);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 11;
      operand -= 2;
      assertWithMessage("[-=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[-=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(9);
      assertWithMessage("[-=] n == operand.value, ").that(operand.intValue()).isEqualTo(9);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 21;
      operand *= 2;
      assertWithMessage("[*=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[*=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(42);
      assertWithMessage("[*=] n == operand.value, ").that(operand.intValue()).isEqualTo(42);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 30;
      operand /= 2;
      assertWithMessage("[/=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[/=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(15);
      assertWithMessage("[/=] n == operand.value, ").that(operand.intValue()).isEqualTo(15);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 123;
      operand %= 100;
      assertWithMessage("[%=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[%=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(23);
      assertWithMessage("[%=] n == operand.value, ").that(operand.intValue()).isEqualTo(23);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 0x55;
      operand &= 0xF;
      assertWithMessage("[&=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[&=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(0x5);
      assertWithMessage("[&=] n == operand.value, ").that(operand.intValue()).isEqualTo(0x5);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 0x55;
      operand |= 0xF;
      assertWithMessage("[|=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[|=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(0x5F);
      assertWithMessage("[|=] n == operand.value, ").that(operand.intValue()).isEqualTo(0x5F);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 0x55;
      operand ^= 0xF;
      assertWithMessage("[&=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[&=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(0x5A);
      assertWithMessage("[&=] n == operand.value, ").that(operand.intValue()).isEqualTo(0x5A);
    }

    {
      Integer operand;
      Integer original;
      original = operand = 0x3F;
      operand <<= 1;
      assertWithMessage("[<<=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[<<=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(0x7E);
      assertWithMessage("[<<=] n == operand.value, ").that(operand.intValue()).isEqualTo(0x7E);
    }

    {
      Integer operand;
      Integer original;
      original = operand = -16;
      operand >>= 1;
      assertWithMessage("[>>=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[>>=] valueOf(n) == operand, ").that(operand).isSameInstanceAs(-8);
      assertWithMessage("[>>=] n == operand.value, ").that(operand.intValue()).isEqualTo(-8);
    }

    {
      Integer operand;
      Integer original;
      original = operand = -1;
      operand >>>= 1;
      assertWithMessage("[>>>=] original != operand, ").that(operand).isNotSameInstanceAs(original);
      assertWithMessage("[>>>=] valueOf(n).equals(operand), ")
          .that(operand)
          .isEqualTo(Integer.valueOf(0x7FFFFFFF));
      assertWithMessage("[>>>=] n == operand.value, ")
          .that(operand.intValue())
          .isEqualTo(0x7FFFFFFF);
    }
  }

  /** Tests operations like += and *= where the left-hand side is a boxed Long. */
  @Test
  public void testCompoundAssignmentsWithLong() {
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 += 5;
      assertThat(long1).isEqualTo(10L);
      assertThat(long2).isEqualTo(15L);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 += 1;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(11);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 -= 1;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(9);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 *= 2;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(20);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 /= 2;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(5);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 %= 3;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(1);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 <<= 1;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(20);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 >>= 1;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(5);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 >>>= 1;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(5);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 &= 8;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(8);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 |= 1;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(11);
    }
    {
      Long long1 = 10L;
      Long long2 = long1;
      long2 ^= 1;
      assertThat(long1).isEqualTo(10);
      assertThat(long2).isEqualTo(11);
    }
  }

  /**
   * Tests ++ and -- on all boxed types. Use assertNotSame to ensure that a new wrapper is created
   * instead of modifying the original boxed value in place. (Issue 2446).
   */
  @Test
  public void testIncrDecr() {
    {
      // these initial tests are miscellaneous one-off tests
      Byte originalBoxedByte = boxedByte;

      Object value2 = (byte) boxedByte++;
      assertThat(value2).isEqualTo(unboxedByte);
      assertThat((byte) boxedByte).isEqualTo(unboxedByte + 1);
      boxedByte = originalBoxedByte;

      Integer[] ary = new Integer[] {0, 10, 20, 30, 40, 50};
      Integer idx = 2;
      Object value1 = (int) ary[idx++]++;
      assertThat(value1).isEqualTo(20);
      assertThat((int) ary[2]).isEqualTo(21);
      assertThat((int) idx).isEqualTo(3);
      Object value = (int) ary[idx += 1];
      assertThat(value).isEqualTo(40);
      assertThat((int) idx).isEqualTo(4);
    }
    // the rest of this method tests all boxed types under ++ and --
    {
      Byte originalBoxedByte = boxedByte;
      boxedByte++;
      assertWithMessage("Boxed byte modified in place")
          .that(originalBoxedByte)
          .isNotSameInstanceAs(boxedByte);
      assertThat((byte) boxedByte).isEqualTo(unboxedByte + 1);
      boxedByte = originalBoxedByte;
      ++boxedByte;
      assertWithMessage("Boxed byte modified in place")
          .that(originalBoxedByte)
          .isNotSameInstanceAs(boxedByte);
      assertThat((byte) boxedByte).isEqualTo(unboxedByte + 1);
      boxedByte = originalBoxedByte;
      boxedByte--;
      assertWithMessage("Boxed byte modified in place")
          .that(originalBoxedByte)
          .isNotSameInstanceAs(boxedByte);
      assertThat((byte) boxedByte).isEqualTo(unboxedByte - 1);
      boxedByte = originalBoxedByte;
      --boxedByte;
      assertWithMessage("Boxed byte modified in place")
          .that(originalBoxedByte)
          .isNotSameInstanceAs(boxedByte);
      assertThat((byte) boxedByte).isEqualTo(unboxedByte - 1);
      boxedByte = originalBoxedByte;
    }
    {
      Character originalBoxedChar = boxedChar;
      boxedChar++;
      assertWithMessage("Boxed character modified in place")
          .that(originalBoxedChar)
          .isNotSameInstanceAs(boxedChar);
      assertThat((char) boxedChar).isEqualTo(unboxedChar + 1);
      boxedChar = originalBoxedChar;
      ++boxedChar;
      assertWithMessage("Boxed character modified in place")
          .that(originalBoxedChar)
          .isNotSameInstanceAs(boxedChar);
      assertThat((char) boxedChar).isEqualTo(unboxedChar + 1);
      boxedChar = originalBoxedChar;
      boxedChar--;
      assertWithMessage("Boxed character modified in place")
          .that(originalBoxedChar)
          .isNotSameInstanceAs(boxedChar);
      assertThat((char) boxedChar).isEqualTo(unboxedChar - 1);
      boxedChar = originalBoxedChar;
      --boxedChar;
      assertWithMessage("Boxed character modified in place")
          .that(originalBoxedChar)
          .isNotSameInstanceAs(boxedChar);
      assertThat((char) boxedChar).isEqualTo(unboxedChar - 1);
      boxedChar = originalBoxedChar;
    }
    {
      Short originalBoxedShort = boxedShort;
      boxedShort++;
      assertWithMessage("Boxed short modified in place")
          .that(originalBoxedShort)
          .isNotSameInstanceAs(boxedShort);
      assertThat((short) boxedShort).isEqualTo(unboxedShort + 1);
      boxedShort = originalBoxedShort;
      ++boxedShort;
      assertWithMessage("Boxed short modified in place")
          .that(originalBoxedShort)
          .isNotSameInstanceAs(boxedShort);
      assertThat((short) boxedShort).isEqualTo(unboxedShort + 1);
      boxedShort = originalBoxedShort;
      boxedShort--;
      assertWithMessage("Boxed short modified in place")
          .that(originalBoxedShort)
          .isNotSameInstanceAs(boxedShort);
      assertThat((short) boxedShort).isEqualTo(unboxedShort - 1);
      boxedShort = originalBoxedShort;
      --boxedShort;
      assertWithMessage("Boxed short modified in place")
          .that(originalBoxedShort)
          .isNotSameInstanceAs(boxedShort);
      assertThat((short) boxedShort).isEqualTo(unboxedShort - 1);
      boxedShort = originalBoxedShort;
    }
    {
      Integer originalBoxedInt = boxedInt;
      boxedInt++;
      assertWithMessage("Boxed int modified in place")
          .that(originalBoxedInt)
          .isNotSameInstanceAs(boxedInt);
      assertThat((int) boxedInt).isEqualTo(unboxedInt + 1);
      boxedInt = originalBoxedInt;
      ++boxedInt;
      assertWithMessage("Boxed int modified in place")
          .that(originalBoxedInt)
          .isNotSameInstanceAs(boxedInt);
      assertThat((int) boxedInt).isEqualTo(unboxedInt + 1);
      boxedInt = originalBoxedInt;
      boxedInt--;
      assertWithMessage("Boxed int modified in place")
          .that(originalBoxedInt)
          .isNotSameInstanceAs(boxedInt);
      assertThat((int) boxedInt).isEqualTo(unboxedInt - 1);
      boxedInt = originalBoxedInt;
      --boxedInt;
      assertWithMessage("Boxed int modified in place")
          .that(originalBoxedInt)
          .isNotSameInstanceAs(boxedInt);
      assertThat((int) boxedInt).isEqualTo(unboxedInt - 1);
      boxedInt = originalBoxedInt;
    }
    {
      Long originalBoxedLong = boxedLong;
      boxedLong++;
      assertWithMessage("Boxed long modified in place")
          .that(originalBoxedLong)
          .isNotSameInstanceAs(boxedLong);
      assertThat((long) boxedLong).isEqualTo(unboxedLong + 1);
      boxedLong = originalBoxedLong;
      ++boxedLong;
      assertWithMessage("Boxed long modified in place")
          .that(originalBoxedLong)
          .isNotSameInstanceAs(boxedLong);
      assertThat((long) boxedLong).isEqualTo(unboxedLong + 1);
      boxedLong = originalBoxedLong;
      boxedLong--;
      assertWithMessage("Boxed long modified in place")
          .that(originalBoxedLong)
          .isNotSameInstanceAs(boxedLong);
      assertThat((long) boxedLong).isEqualTo(unboxedLong - 1);
      boxedLong = originalBoxedLong;
      --boxedLong;
      assertWithMessage("Boxed long modified in place")
          .that(originalBoxedLong)
          .isNotSameInstanceAs(boxedLong);
      assertThat((long) boxedLong).isEqualTo(unboxedLong - 1);
      boxedLong = originalBoxedLong;
    }
    {
      Float originalBoxedFloat = boxedFloat;
      boxedFloat++;
      assertWithMessage("Boxed float modified in place")
          .that(originalBoxedFloat)
          .isNotSameInstanceAs(boxedFloat);
      assertThat((float) boxedFloat).isEqualTo(unboxedFloat + 1);
      boxedFloat = originalBoxedFloat;
      ++boxedFloat;
      assertWithMessage("Boxed float modified in place")
          .that(originalBoxedFloat)
          .isNotSameInstanceAs(boxedFloat);
      assertThat((float) boxedFloat).isEqualTo(unboxedFloat + 1);
      boxedFloat = originalBoxedFloat;
      boxedFloat--;
      assertWithMessage("Boxed float modified in place")
          .that(originalBoxedFloat)
          .isNotSameInstanceAs(boxedFloat);
      assertThat((float) boxedFloat).isEqualTo(unboxedFloat - 1);
      boxedFloat = originalBoxedFloat;
      --boxedFloat;
      assertWithMessage("Boxed float modified in place")
          .that(originalBoxedFloat)
          .isNotSameInstanceAs(boxedFloat);
      assertThat((float) boxedFloat).isEqualTo(unboxedFloat - 1);
      boxedFloat = originalBoxedFloat;
    }
    {
      Double originalBoxedDouble = boxedDouble;
      boxedDouble++;
      assertWithMessage("Boxed double modified in place")
          .that(originalBoxedDouble)
          .isNotSameInstanceAs(boxedDouble);
      assertThat((double) boxedDouble).isEqualTo(unboxedDouble + 1);
      boxedDouble = originalBoxedDouble;
      ++boxedDouble;
      assertWithMessage("Boxed double modified in place")
          .that(originalBoxedDouble)
          .isNotSameInstanceAs(boxedDouble);
      assertThat((double) boxedDouble).isEqualTo(unboxedDouble + 1);
      boxedDouble = originalBoxedDouble;
      boxedDouble--;
      assertWithMessage("Boxed double modified in place")
          .that(originalBoxedDouble)
          .isNotSameInstanceAs(boxedDouble);
      assertThat((double) boxedDouble).isEqualTo(unboxedDouble - 1);
      boxedDouble = originalBoxedDouble;
      --boxedDouble;
      assertWithMessage("Boxed double modified in place")
          .that(originalBoxedDouble)
          .isNotSameInstanceAs(boxedDouble);
      assertThat((double) boxedDouble).isEqualTo(unboxedDouble - 1);
      boxedDouble = originalBoxedDouble;
    }
  }

  @Test
  public void testUnboxing() {
    boolean boolean_ = boxedBoolean;
    assertThat(boolean_ == boxedBoolean.booleanValue()).isTrue();
    byte byte_ = boxedByte;
    assertThat(byte_ == boxedByte.byteValue()).isTrue();
    char char_ = boxedChar;
    assertThat(char_ == boxedChar.charValue()).isTrue();
    short short_ = boxedShort;
    assertThat(short_ == boxedShort.shortValue()).isTrue();
    int int_ = boxedInt;
    assertThat(int_ == boxedInt.intValue()).isTrue();
    long long_ = boxedLong;
    assertThat(long_ == boxedLong.longValue()).isTrue();
    float float_ = boxedFloat;
    assertThat(float_ == boxedFloat.floatValue()).isTrue();
    double double_ = boxedDouble;
    assertThat(double_ == boxedDouble.doubleValue()).isTrue();

    // test unboxing of return values
    assertThat(unbox(boxedBoolean) == unboxedBoolean).isTrue();
    assertThat(unbox(boxedByte) == unboxedByte).isTrue();
    assertThat(unbox(boxedShort) == unboxedShort).isTrue();
    assertThat(unbox(boxedChar) == unboxedChar).isTrue();
    assertThat(unbox(boxedInt) == unboxedInt).isTrue();
    assertThat(unbox(boxedLong) == unboxedLong).isTrue();
    assertThat(unbox(boxedFloat) == unboxedFloat).isTrue();
    assertThat(unbox(boxedDouble) == unboxedDouble).isTrue();

    // test unboxing of parameters
    assertThat(box(boxedBoolean).booleanValue() == unboxedBoolean).isTrue();
    assertThat(box(boxedByte).byteValue() == unboxedByte).isTrue();
    assertThat(box(boxedShort).shortValue() == unboxedShort).isTrue();
    assertThat(box(boxedChar).charValue() == unboxedChar).isTrue();
    assertThat(box(boxedInt).intValue() == unboxedInt).isTrue();
    assertThat(box(boxedLong).longValue() == unboxedLong).isTrue();
    assertThat(box(boxedFloat).floatValue() == unboxedFloat).isTrue();
    assertThat(box(boxedDouble).doubleValue() == unboxedDouble).isTrue();
  }

  @Test
  public void testUnboxingDifferentType() {
    {
      short short_ = boxedByte;
      assertThat(short_ == boxedByte.byteValue()).isTrue();
      int int_ = boxedByte;
      assertThat(int_ == boxedByte.byteValue()).isTrue();
      long long_ = boxedByte;
      assertThat(long_ == boxedByte.byteValue()).isTrue();
      float float_ = boxedByte;
      assertThat(float_ == boxedByte.byteValue()).isTrue();
      double double_ = boxedByte;
      assertThat(double_ == boxedByte.byteValue()).isTrue();
    }

    {
      int int_ = boxedShort;
      assertThat(int_ == boxedShort.shortValue()).isTrue();
      long long_ = boxedShort;
      assertThat(long_ == boxedShort.shortValue()).isTrue();
      float float_ = boxedShort;
      assertThat(float_ == boxedShort.shortValue()).isTrue();
      double double_ = boxedShort;
      assertThat(double_ == boxedShort.shortValue()).isTrue();
    }

    {
      int int_ = boxedChar;
      assertThat(int_ == boxedChar.charValue()).isTrue();
      long long_ = boxedChar;
      assertThat(long_ == boxedChar.charValue()).isTrue();
      float float_ = boxedChar;
      assertThat(float_ == boxedChar.charValue()).isTrue();
      double double_ = boxedChar;
      assertThat(double_ == boxedChar.charValue()).isTrue();
    }

    {
      long long_ = boxedInt;
      assertThat(long_ == boxedInt.intValue()).isTrue();
      float float_ = boxedInt;
      assertThat(float_ == boxedInt.intValue()).isTrue();
      double double_ = boxedInt;
      assertThat(double_ == boxedInt.intValue()).isTrue();
    }
  }

  private static Boolean box(boolean b) {
    return b;
  }

  private static Byte box(byte b) {
    return b;
  }

  private static Character box(char c) {
    return c;
  }

  private static Double box(double d) {
    return d;
  }

  private static Float box(float f) {
    return f;
  }

  private static Integer box(int i) {
    return i;
  }

  private static Long box(long l) {
    return l;
  }

  private static Short box(short s) {
    return s;
  }

  private static boolean unbox(Boolean b) {
    return b;
  }

  private static byte unbox(Byte b) {
    return b;
  }

  private static char unbox(Character c) {
    return c;
  }

  private static double unbox(Double d) {
    return d;
  }

  private static float unbox(Float f) {
    return f;
  }

  private static int unbox(Integer i) {
    return i;
  }

  private static long unbox(Long l) {
    return l;
  }

  private static short unbox(Short s) {
    return s;
  }
}


text:
前置文章
------
[Spring Security 入门:登录与退出](http://www.jianshu.com/p/a8e317e82425)

本文说明
------
本文是 spring security 与 mybatis 的整合,实现基于数据库的登录校验,使用 mariadb( mysql 通用,不用改任何代码),希望对你有所帮助!

Github地址
-------
https://github.com/ChinaSilence/any-spring-security/tree/master/security-login-db

运行程序
------
1、clone 代码
```
git clone https://github.com/ChinaSilence/any-spring-security.git
cd security-login-db
```

2、建数据库,名称为 any
```
create database any;
use any;
```

3、执行 user.sql,会生成如下数据:

id|username|password|nickname|roles
--|--|--|--|--
1|anoy|pwd|anoy|ROLE_USER
2|admin|pwd|admin|ROLE_USER,ROLE_ADMIN

4、启动应用
```
mvn spring-boot:run
```

5、注册并登陆。

Spring Security 校验流程图
------
![Spring Security 登录流程.jpg](http://upload-images.jianshu.io/upload_images/3424642-7418a70abdfc7287.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

相关解释说明(认真看哦)
-----
#### AbstractAuthenticationProcessingFilter 抽象类

```
/**
	 * 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。
	 * 如果需要验证,则会调用 #attemptAuthentication(HttpServletRequest, HttpServletResponse) 方法。
	 * 有三种结果:
	 * 1、返回一个 Authentication 对象。
     * 配置的 SessionAuthenticationStrategy` 将被调用,
     * 然后 然后调用 #successfulAuthentication(HttpServletRequest,HttpServletResponse,FilterChain,Authentication) 方法。
     * 2、验证时发生 AuthenticationException。
     * #unsuccessfulAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationException) 方法将被调用。
     * 3、返回Null,表示身份验证不完整。假设子类做了一些必要的工作(如重定向)来继续处理验证,方法将立即返回。
	 * 假设后一个请求将被这种方法接收,其中返回的Authentication对象不为空。
	 */
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;

		if (!requiresAuthentication(request, response)) {
			chain.doFilter(request, response);

			return;
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Request is to process authentication");
		}

		Authentication authResult;

		try {
			authResult = attemptAuthentication(request, response);
			if (authResult == null) {
				// return immediately as subclass has indicated that it hasn't completed
				// authentication
				return;
			}
			sessionStrategy.onAuthentication(authResult, request, response);
		}
		catch (InternalAuthenticationServiceException failed) {
			logger.error(
					"An internal error occurred while trying to authenticate the user.",
					failed);
			unsuccessfulAuthentication(request, response, failed);

			return;
		}
		catch (AuthenticationException failed) {
			// Authentication failed
			unsuccessfulAuthentication(request, response, failed);

			return;
		}

		// Authentication success
		if (continueChainBeforeSuccessfulAuthentication) {
			chain.doFilter(request, response);
		}

		successfulAuthentication(request, response, chain, authResult);
	}
```

#### UsernamePasswordAuthenticationFilter(AbstractAuthenticationProcessingFilter的子类)
```
public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		if (postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException(
					"Authentication method not supported: " + request.getMethod());
		}

		String username = obtainUsername(request);
		String password = obtainPassword(request);

		if (username == null) {
			username = "";
		}

		if (password == null) {
			password = "";
		}

		username = username.trim();

		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				username, password);

		// Allow subclasses to set the "details" property
		setDetails(request, authRequest);

		return this.getAuthenticationManager().authenticate(authRequest);
	}
```

`#attemptAuthentication ()` 方法将 request 中的 username 和 password 生成 UsernamePasswordAuthenticationToken 对象,用于 `AuthenticationManager ` 的验证(即 this.getAuthenticationManager().authenticate(authRequest) )。

默认情况下注入 Spring 容器的 `AuthenticationManager` 是 `ProviderManager`。

#### ProviderManager(AuthenticationManager的实现类)
```
/**
	 * 尝试验证 Authentication 对象
	 * AuthenticationProvider 列表将被连续尝试,直到 AuthenticationProvider 表示它能够认证传递的过来的Authentication 对象。然后将使用该 AuthenticationProvider 尝试身份验证。
	 * 如果有多个 AuthenticationProvider 支持验证传递过来的Authentication 对象,那么由第一个来确定结果,覆盖早期支持AuthenticationProviders 所引发的任何可能的AuthenticationException。 成功验证后,将不会尝试后续的AuthenticationProvider。
	 * 如果最后所有的 AuthenticationProviders 都没有成功验证 Authentication 对象,将抛出 AuthenticationException。
	 */
	public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		Class<? extends Authentication> toTest = authentication.getClass();
		AuthenticationException lastException = null;
		Authentication result = null;
		boolean debug = logger.isDebugEnabled();

		for (AuthenticationProvider provider : getProviders()) {
			if (!provider.supports(toTest)) {
				continue;
			}

			if (debug) {
				logger.debug("Authentication attempt using "
						+ provider.getClass().getName());
			}

			try {
				result = provider.authenticate(authentication);

				if (result != null) {
					copyDetails(authentication, result);
					break;
				}
			}
			catch (AccountStatusException e) {
				prepareException(e, authentication);
				// SEC-546: Avoid polling additional providers if auth failure is due to
				// invalid account status
				throw e;
			}
			catch (InternalAuthenticationServiceException e) {
				prepareException(e, authentication);
				throw e;
			}
			catch (AuthenticationException e) {
				lastException = e;
			}
		}

		if (result == null && parent != null) {
			// Allow the parent to try.
			try {
				result = parent.authenticate(authentication);
			}
			catch (ProviderNotFoundException e) {
				// ignore as we will throw below if no other exception occurred prior to
				// calling parent and the parent
				// may throw ProviderNotFound even though a provider in the child already
				// handled the request
			}
			catch (AuthenticationException e) {
				lastException = e;
			}
		}

		if (result != null) {
			if (eraseCredentialsAfterAuthentication
					&& (result instanceof CredentialsContainer)) {
				// Authentication is complete. Remove credentials and other secret data
				// from authentication
				((CredentialsContainer) result).eraseCredentials();
			}

			eventPublisher.publishAuthenticationSuccess(result);
			return result;
		}

		// Parent was null, or didn't authenticate (or throw an exception).

		if (lastException == null) {
			lastException = new ProviderNotFoundException(messages.getMessage(
					"ProviderManager.providerNotFound",
					new Object[] { toTest.getName() },
					"No AuthenticationProvider found for {0}"));
		}

		prepareException(lastException, authentication);

		throw lastException;
	}
```
从代码中不难看出,由 provider 来验证 authentication, 核心点方法是:
```
Authentication result = provider.authenticate(authentication);
```
此处的 `provider` 是 `AbstractUserDetailsAuthenticationProvider`,
`AbstractUserDetailsAuthenticationProvider` 是AuthenticationProvider的实现,看看它的 `#authenticate(authentication)` 方法:
```
// 验证 authentication
public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
				messages.getMessage(
						"AbstractUserDetailsAuthenticationProvider.onlySupports",
						"Only UsernamePasswordAuthenticationToken is supported"));

		// Determine username
		String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
				: authentication.getName();

		boolean cacheWasUsed = true;
		UserDetails user = this.userCache.getUserFromCache(username);

		if (user == null) {
			cacheWasUsed = false;

			try {
				user = retrieveUser(username,
						(UsernamePasswordAuthenticationToken) authentication);
			}
			catch (UsernameNotFoundException notFound) {
				logger.debug("User '" + username + "' not found");

				if (hideUserNotFoundExceptions) {
					throw new BadCredentialsException(messages.getMessage(
							"AbstractUserDetailsAuthenticationProvider.badCredentials",
							"Bad credentials"));
				}
				else {
					throw notFound;
				}
			}

			Assert.notNull(user,
					"retrieveUser returned null - a violation of the interface contract");
		}

		try {
			preAuthenticationChecks.check(user);
			additionalAuthenticationChecks(user,
					(UsernamePasswordAuthenticationToken) authentication);
		}
		catch (AuthenticationException exception) {
			if (cacheWasUsed) {
				// There was a problem, so try again after checking
				// we're using latest data (i.e. not from the cache)
				cacheWasUsed = false;
				user = retrieveUser(username,
						(UsernamePasswordAuthenticationToken) authentication);
				preAuthenticationChecks.check(user);
				additionalAuthenticationChecks(user,
						(UsernamePasswordAuthenticationToken) authentication);
			}
			else {
				throw exception;
			}
		}

		postAuthenticationChecks.check(user);

		if (!cacheWasUsed) {
			this.userCache.putUserInCache(user);
		}

		Object principalToReturn = user;

		if (forcePrincipalAsString) {
			principalToReturn = user.getUsername();
		}

		return createSuccessAuthentication(principalToReturn, authentication, user);
	}
```
`AbstractUserDetailsAuthenticationProvider` 内置了缓存机制,从缓存中获取不到的 UserDetails 信息的话,就调用如下方法获取用户信息,然后和 用户传来的信息进行对比来判断是否验证成功。
```
// 获取用户信息
UserDetails user = retrieveUser(username,
 (UsernamePasswordAuthenticationToken) authentication);
```
`#retrieveUser()` 方法在 `DaoAuthenticationProvider` 中实现,`DaoAuthenticationProvider` 是 `AbstractUserDetailsAuthenticationProvider `的子类。具体实现如下:
```
protected final UserDetails retrieveUser(String username,
			UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		UserDetails loadedUser;

		try {
			loadedUser = this.getUserDetailsService().loadUserByUsername(username);
		}
		catch (UsernameNotFoundException notFound) {
			if (authentication.getCredentials() != null) {
				String presentedPassword = authentication.getCredentials().toString();
				passwordEncoder.isPasswordValid(userNotFoundEncodedPassword,
						presentedPassword, null);
			}
			throw notFound;
		}
		catch (Exception repositoryProblem) {
			throw new InternalAuthenticationServiceException(
					repositoryProblem.getMessage(), repositoryProblem);
		}

		if (loadedUser == null) {
			throw new InternalAuthenticationServiceException(
					"UserDetailsService returned null, which is an interface contract violation");
		}
		return loadedUser;
	}
```
可以看到此处的返回对象 `userDetails` 是由 `UserDetailsService` 的 `#loadUserByUsername(username)` 来获取的。

到了此处,就很清晰啦,Demo 中自定义了 `AnyUserDetailsService`。


text:
using System;

namespace LocalNotifications.Plugin.Abstractions
{
    /// <summary>
    /// Notification options data used for creating native notification
    /// </summary>
    public class LocalNotification
    {
        /// <summary>
        /// Gets or sets the identifier.
        /// </summary>
        /// <value>
        /// Notification identifier used for canceling not scheduled notification
        /// </value>
        public int Id { get; set; }

        /// <summary>
        /// Gets or sets the notification title.
        /// </summary>
        /// <value>
        /// The notification title.
        /// </value>
        public string Title { get; set; }

        /// <summary>
        /// Gets or sets the notification text.
        /// </summary>
        /// <value>
        /// The notification text.
        /// </value>
        public string Text { get; set; }

        /// <summary>
        /// Gets or sets the notify time of notification.
        /// </summary>
        /// <value>
        /// The notify time of notification.
        /// </value>
        public DateTime NotifyTime { get; set; }

        /// <summary>
        /// Enable notification vibrate, default set 500ms for android and ios not configurable.
        /// </summary>
        public bool Vibrate { get; set; }

        /// <summary>
        /// Play the default notification sound
        /// </summary>
        public NoficationSoundType PlaySound { get; set; }

        public string CustomIOSSound { get; set; }
    }

    /// <summary>
    /// None and RingtoneType
    /// </summary>
    public enum NoficationSoundType
    {
        None = 0,
        Ringtone = 1,
        Notification = 2,  //Recommended, maybe some pad have no Ringtone and Alarm
        Alarm = 4
    }
}


text:
Plug.UPnP_AVTransport
============================

A Plug.UPnP Abstraction API for communicating specifically with a UPnP Media Renderer obtained via the [W3C Network Service Discovery draft specification (4th October 2012 version)](http://www.w3.org/TR/2012/WD-discovery-api-20121004/).

__A general description of the Plug.Play library is available in the main [README](https://github.com/richtr/plug.play.js/blob/master/README.md) file available in the root of this repository.__

### Example Usage

The following example shows how to obtain and use a Plug.UPnP_AVTransport object. For [Step 1](https://github.com/richtr/plug.play.js/blob/master/README.md#step-1-obtaining-networkservice-objects) and [Step 2](https://github.com/richtr/plug.play.js/blob/master/README.md#step-2-creating-a-new-plug.upnp-object) please consult the main [README](https://github.com/richtr/plug.play.js/blob/master/README.md) file.

    var mediaRenderer = new Plug.UPnP_AVTransport( service, { debug: false } );

    mediaRenderer.getTransportInfo().then(function(response) {

        if (response && response.data) {
            debugLog("Service[" + service._index + "] is reporting CurrentTransportState=[" + response.data.CurrentTransportState + "]");
        } else {
            debugLog("Service[" + service._index + "] is reporting no response");
        }

    }).then( null, function( error ) { // Handle any errors

        debugLog( "An error occurred: " + error.description );

    });

You can see this code in action in [demo.html](https://github.com/richtr/plug.play.js/tree/master/lib/AVTransport/demo.html).


text:
'use strict';

var React = require('react');
var assign = require('object-assign');
var decorate = require('./decorate');

class TabbedPane extends React.Component {
  props: {
    tabs: {[key: string]: () => React$Element},
    selected: string,
    setSelectedTab: (name: string) => void,
  };

  render() {
    var tabs = Object.keys(this.props.tabs);
    if (tabs.length === 1) {
      return this.props.tabs[tabs[0]]();
    }
    return (

          {tabs.map((name, i) => {
            var style = styles.tab;
            if (name === this.props.selected) {
              style = assign({}, style, styles.selectedTab);
            }
            if (i === tabs.length - 1) {
              style = assign({}, style, styles.lastTab);
            }
            return (

 this.props.setSelectedTab(name)}>
                {name}

            );
          })}

          {this.props.tabs[this.props.selected]()}

    );
  }
}

var styles = {
  container:{
    flex: 1,
    display: 'flex',
    flexDirection: 'column',
    width: '100%',
  },
  tabs: {
    display: 'flex',
    flexShrink: 0,
    listStyle: 'none',
    backgroundColor: '#eee',
    borderBottom: '1px solid rgb(163, 163, 163)',
    margin: 0,
    padding: '0 2px',
  },
  tab: {
    padding: '2px 4px',
    lineHeight: '15px',
    fontSize: 12,
    fontFamily: "'Lucida Grande', sans-serif",
    cursor: 'pointer',
    borderLeft: '1px solid rgb(163, 163, 163)',
  },
  lastTab: {
    borderRight: '1px solid rgb(163, 163, 163)',
  },
  selectedTab: {
    backgroundColor: 'white',
  },
  body: {
    flex: 1,
    display: 'flex',
    minHeight: 0,
  },
};

module.exports = decorate({
  listeners: () => ['selectedTab'],
  shouldUpdate: (props, prevProps) => {
    for (var name in props) {
      if (props[name] !== prevProps[name]) {
        return true;
      }
    }
    return false;
  },
  props(store) {
    return {
      selected: store.selectedTab,
      setSelectedTab: name => store.setSelectedTab(name),
    };
  },
}, TabbedPane);


text:
<?php

namespace Ideato\SimplePagerBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class IdeatoSimplePagerBundle extends Bundle
{
}


text:
package org.pesc.oauth;

import org.pesc.api.model.AuthUser;
import org.pesc.service.OrganizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by james on 1/22/17.
 */
public class CustomTokenEnhancer implements TokenEnhancer {

    @Autowired
    private OrganizationService organizationService;

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        Object principal = authentication.getPrincipal();

        final Map<String, Object> additionalInfo = new HashMap<>();

        if (principal instanceof AuthUser) {

            AuthUser user = (AuthUser) principal;

            additionalInfo.put("user_id", user.getId());
            additionalInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getAuthorities()));
            additionalInfo.put("organization_id", user.getOrganizationId());
            additionalInfo.put("serviced_organizations", organizationService.getInstitutionsByServiceProviderId(user.getOrganizationId()));
            //((DefaultOAuth2AccessToken) accessToken).setScope(new HashSet(Arrays.asList("read_inbox", "read_transactions", "write_outbox", "read_outbox"));

        } else {
            additionalInfo.put("authorities", new String[]{"ROLE_NETWORK_SERVER"});
            additionalInfo.put("organization_id", principal);

        }

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);

        return accessToken;
    }
}


text:
/**
 * Support for formula functions that operate on {@link org.diirt.vtype.VString}s.
 */
package org.diirt.datasource.formula.vstring;


text:
namespace PersonClass
{
    public class Person
    {
        public Person(string name, int? age = null)
        {
            this.Name = name;
            this.Age = age;
        }

        public string Name { get; private set; }

        public int? Age { get; set; }

        public override string ToString()
        {
            return string.Format("Name: {0}, Age: {1}", this.Name, this.Age == null ? (dynamic)"Not specified" : this.Age);
        }
    }
}


text:
package fr.unice.polytech.ihm.kevinapplication;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

import fr.unice.polytech.ihm.kevinapplication.model.Menu;
import fr.unice.polytech.ihm.kevinapplication.model.bd.TypeNotification;

/**
 * An activity representing a list of Items. This activity
 * has different presentations for handset and tablet-size devices. On
 * handsets, the activity presents a list of items, which when touched,
 * lead to a {@link ItemDetailActivity} representing
 * item details. On tablets, the activity presents the list of items and
 * item details side-by-side using two vertical panes.
 */
public class ItemListActivity extends AppCompatActivity {

    /**
     * Whether or not the activity is in two-pane mode, i.e. running on a tablet
     * device.
     */
    private boolean mTwoPane;
    public View mView=null;
    private ItemDetailFragment fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_item_list);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setTitle(getTitle());

        View recyclerView = findViewById(R.id.item_list);
        assert recyclerView != null;
        setupRecyclerView((RecyclerView) recyclerView);

        if (findViewById(R.id.item_detail_container) != null) {
            // The detail container view will be present only in the
            // large-screen layouts (res/values-w900dp).
            // If this view is present, then the
            // activity should be in two-pane mode.
            mTwoPane = true;
        }
    }

    private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
        recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(Menu.ITEMS));
    }

    public class SimpleItemRecyclerViewAdapter
            extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {

        private final List<Menu.MenuItem> mValues;

        public SimpleItemRecyclerViewAdapter(List<Menu.MenuItem> items) {
            mValues = items;
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            parent.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_list_content, parent, false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            holder.mItem = mValues.get(position);
            ImageAsyncTask imageAsyncTask = new ImageAsyncTask(holder.mimage);
            imageAsyncTask.execute(mValues.get(position).image);
            holder.mContentView.setText(mValues.get(position).content.toString());
            holder.mView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mTwoPane) {
                        Bundle arguments = new Bundle();
                        arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id);
                        if(mView!=null)
                            mView.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
                        holder.mView.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
                        mView=holder.mView;
                        fragment = new ItemDetailFragment();
                        fragment.setArguments(arguments);
                        getSupportFragmentManager().beginTransaction()
                                .replace(R.id.item_detail_container, fragment)
                                .commit();
                    } else {
                        Context context = v.getContext();
                        Intent intent = new Intent(context, ItemDetailActivity.class);
                        intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id);
                        context.startActivity(intent);
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return mValues.size();
        }

        public class ViewHolder extends RecyclerView.ViewHolder {
            public final View mView;
            public final ImageView mimage;
            public final TextView mContentView;
            public Menu.MenuItem mItem;

            public ViewHolder(View view) {
                super(view);
                mView = view;
                mimage = (ImageView) view.findViewById(R.id.image);
                mContentView = (TextView) view.findViewById(R.id.content);
            }

            @Override
            public String toString() {
                return super.toString() + " '" + mContentView.getText() + "'";
            }
        }
    }

    public void call(View target){
        fragment.call(target);
    }
    public void sendMail(View target) {
        fragment.sendMail(target);
    }
    public void onswitch(View target){
        DataBaseHelper bd=new DataBaseHelper(this);
        try {
            bd.createDataBase();
            bd.openDataBase();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        bd.updateNotification(new TypeNotification((String) ((Switch) target.findViewById(R.id.expandedListItem)).getText(),((Switch) target.findViewById(R.id.expandedListItem)).isChecked()));
        List<fr.unice.polytech.ihm.kevinapplication.model.bd.Notification> notifications=bd.getNotificationsActif();
        if(((Switch) target.findViewById(R.id.expandedListItem)).isChecked())
            createNotification(notifications);
    }

    private final void createNotification(List<fr.unice.polytech.ihm.kevinapplication.model.bd.Notification> notifications){
        int i=0;
        for(fr.unice.polytech.ihm.kevinapplication.model.bd.Notification n :notifications) {
            NotificationManager mNotification = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            Intent launchNotifiactionIntent = new Intent(this, ItemDetailActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, launchNotifiactionIntent, PendingIntent.FLAG_ONE_SHOT);
            Notification.Builder builder = new Notification.Builder(this)
                    .setWhen(System.currentTimeMillis())
                    .setContentTitle(n.getNom())
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentText(n.getDescriptif())
                    .setContentIntent(pendingIntent);
            mNotification.notify(i, builder.build());
            i++;
        }
    }

}


text:
<!DOCTYPE HTML>

		<title>BERKSHIRE HATHAWAY INC</title>

			BERKSHIRE HATHAWAY INC. 3555 Farnam Street Suite 1440, Omaha, NE 68131 Official Home Page

A Message from Warren E. Buffett

News ReleasesUpdated February 16, 2016

Annual and Interim Reports Updated November 6, 2015

Warren Buffett's Letter to Berkshire Shareholders Updated February 28, 2015

Special Letters from Warren and Charlie RE: Past, Present, and Future

Charlie Munger's Letter to Wesco Shareholders

Link to SEC Filings

Annual Meeting Information

Links to Berkshire Subsidiary Companies

Celebrating 50 Years of Profitable PartnershipA commemorative book first sold at the 2015 Annual Meeting and now for sale on eBay.

Corporate Governance

Comparative Rights and Relative Prices of Class A and B Stock

Owner's Manual

Berkshire Activewear

Letters from Warren E. Buffett Regarding Pledges to Make Gifts of Berkshire Stock

FOR A FREE CAR INSURANCE RATE QUOTE THAT COULD SAVE YOU SUBSTANTIAL MONEY
		WWW.GEICO.COM OR CALL 1-888-395-6349, 24 HOURS A DAY

If you have any comments about our WEB page, you can either write us at the address shown above or e-mail us at berkshire@berkshirehathaway.com. However, due to the limited number of personnel in our corporate office, we are unable to provide a direct response.

Legal Disclaimer

Copyright © 1978-2016 Berkshire Hathaway Inc.


text:
class LoginFormController {
	constructor($auth, ToastService, $state, $rootScope, $log) {
		'ngInject';

		this.$rootScope = $rootScope;
		this.$state = $state;
		this.$auth = $auth;
		this.ToastService = ToastService;
		this.$log = $log;
	}

	$onInit() {
		if (this.$rootScope.$auth.isAuthenticated()) {
			this.$state.go('app.client_profile');
			this.ToastService.show('Already Logged In', 500);
		}

		//for dev purposes
		this.email = '';
		this.password = '';

	}

	login() {
		let user = {
			email: this.email,
			password: this.password
		};

		this.$auth.login(user)
			.then((response) => {
				this.$auth.setToken(response.data);

				this.redirectToProfile(response.data.data.user);
				this.ToastService.show('Welcome Back', 500);
			})
			.catch(this.failedLogin.bind(this));
	}

	failedLogin(response) {
		if (response.status === 422) {
			for (let error in response.data.errors) {
				return this.ToastService.error(response.data.errors[error][0]);
			}
		}
		else if (response.status === 401) {
			return this.ToastService.error('Wrong Email or Password');
		}
		this.ToastService.error(response.statusText);
	}

	redirectToProfile(user) {
		if (angular.isObject(user.consultant)) {
			this.$state.go('app.consultant_profile');
		}
		else if (angular.isObject(user.client)) {
			this.$state.go('app.client_profile');
		}
	}
}

export const LoginFormComponent = {
	templateUrl: './views/app/components/login-form/login-form.component.html',
	controller: LoginFormController,
	controllerAs: 'vm',
	bindings: {}
}


text:
package terraform

import (
	"fmt"

	"github.com/hashicorp/terraform/config"
)

// EvalValidateError is the error structure returned if there were
// validation errors.
type EvalValidateError struct {
	Warnings []string
	Errors   []error
}

func (e *EvalValidateError) Error() string {
	return fmt.Sprintf("Warnings: %s. Errors: %s", e.Warnings, e.Errors)
}

// EvalValidateCount is an EvalNode implementation that validates
// the count of a resource.
type EvalValidateCount struct {
	Resource *config.Resource
}

// TODO: test
func (n *EvalValidateCount) Eval(ctx EvalContext) (interface{}, error) {
	var count int
	var errs []error
	var err error
	if _, err := ctx.Interpolate(n.Resource.RawCount, nil); err != nil {
		errs = append(errs, fmt.Errorf(
			"Failed to interpolate count: %s", err))
		goto RETURN
	}

	count, err = n.Resource.Count()
	if err != nil {
		// If we can't get the count during validation, then
		// just replace it with the number 1.
		c := n.Resource.RawCount.Config()
		c[n.Resource.RawCount.Key] = "1"
		count = 1
	}
	err = nil

	if count < 0 {
		errs = append(errs, fmt.Errorf(
			"Count is less than zero: %d", count))
	}

RETURN:
	if len(errs) != 0 {
		err = &EvalValidateError{
			Errors: errs,
		}
	}
	return nil, err
}

// EvalValidateProvider is an EvalNode implementation that validates
// the configuration of a resource.
type EvalValidateProvider struct {
	Provider *ResourceProvider
	Config   **ResourceConfig
}

func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) {
	provider := *n.Provider
	config := *n.Config

	warns, errs := provider.Validate(config)
	if len(warns) == 0 && len(errs) == 0 {
		return nil, nil
	}

	return nil, &EvalValidateError{
		Warnings: warns,
		Errors:   errs,
	}
}

// EvalValidateProvisioner is an EvalNode implementation that validates
// the configuration of a resource.
type EvalValidateProvisioner struct {
	Provisioner *ResourceProvisioner
	Config      **ResourceConfig
}

func (n *EvalValidateProvisioner) Eval(ctx EvalContext) (interface{}, error) {
	provisioner := *n.Provisioner
	config := *n.Config
	warns, errs := provisioner.Validate(config)
	if len(warns) == 0 && len(errs) == 0 {
		return nil, nil
	}

	return nil, &EvalValidateError{
		Warnings: warns,
		Errors:   errs,
	}
}

// EvalValidateResource is an EvalNode implementation that validates
// the configuration of a resource.
type EvalValidateResource struct {
	Provider     *ResourceProvider
	Config       **ResourceConfig
	ResourceName string
	ResourceType string
	ResourceMode config.ResourceMode

	// IgnoreWarnings means that warnings will not be passed through. This allows
	// "just-in-time" passes of validation to continue execution through warnings.
	IgnoreWarnings bool
}

func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) {
	provider := *n.Provider
	cfg := *n.Config
	var warns []string
	var errs []error
	// Provider entry point varies depending on resource mode, because
	// managed resources and data resources are two distinct concepts
	// in the provider abstraction.
	switch n.ResourceMode {
	case config.ManagedResourceMode:
		warns, errs = provider.ValidateResource(n.ResourceType, cfg)
	case config.DataResourceMode:
		warns, errs = provider.ValidateDataSource(n.ResourceType, cfg)
	}

	// If the resource name doesn't match the name regular
	// expression, show an error.
	if !config.NameRegexp.Match([]byte(n.ResourceName)) {
		errs = append(errs, fmt.Errorf(
			"%s: resource name can only contain letters, numbers, "+
				"dashes, and underscores.", n.ResourceName))
	}

	if (len(warns) == 0 || n.IgnoreWarnings) && len(errs) == 0 {
		return nil, nil
	}

	return nil, &EvalValidateError{
		Warnings: warns,
		Errors:   errs,
	}
}


text:
<?php

namespace Drupal\Tests\user\Kernel;

use Drupal\Core\KeyValueStore\KeyValueExpirableFactory;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\Lock\DatabaseLockBackend;
use Drupal\Core\Database\Database;

/**
 * Tests the temporary object storage system.
 *
 * @group user
 * @see \Drupal\Core\TempStore\TempStore.
 */
class TempStoreDatabaseTest extends KernelTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
  public static $modules = array('system', 'user');

  /**
   * A key/value store factory.
   *
   * @var \Drupal\user\SharedTempStoreFactory
   */
  protected $storeFactory;

  /**
   * The name of the key/value collection to set and retrieve.
   *
   * @var string
   */
  protected $collection;

  /**
   * An array of (fake) user IDs.
   *
   * @var array
   */
  protected $users = array();

  /**
   * An array of random stdClass objects.
   *
   * @var array
   */
  protected $objects = array();

  protected function setUp() {
    parent::setUp();

    // Install system tables to test the key/value storage without installing a
    // full Drupal environment.
    $this->installSchema('system', array('key_value_expire'));

    // Create several objects for testing.
    for ($i = 0; $i <= 3; $i++) {
      $this->objects[$i] = $this->randomObject();
    }

  }

  /**
   * Tests the UserTempStore API.
   */
  public function testUserTempStore() {
    // Create a key/value collection.
    $factory = new SharedTempStoreFactory(new KeyValueExpirableFactory(\Drupal::getContainer()), new DatabaseLockBackend(Database::getConnection()), $this->container->get('request_stack'));
    $collection = $this->randomMachineName();

    // Create two mock users.
    for ($i = 0; $i <= 1; $i++) {
      $users[$i] = mt_rand(500, 5000000);

      // Storing the SharedTempStore objects in a class member variable causes a
      // fatal exception, because in that situation garbage collection is not
      // triggered until the test class itself is destructed, after tearDown()
      // has deleted the database tables. Store the objects locally instead.
      $stores[$i] = $factory->get($collection, $users[$i]);
    }

    $key = $this->randomMachineName();
    // Test that setIfNotExists() succeeds only the first time.
    for ($i = 0; $i <= 1; $i++) {
      // setIfNotExists() should be TRUE the first time (when $i is 0) and
      // FALSE the second time (when $i is 1).
      $this->assertEqual(!$i, $stores[0]->setIfNotExists($key, $this->objects[$i]));
      $metadata = $stores[0]->getMetadata($key);
      $this->assertEqual($users[0], $metadata->owner);
      $this->assertIdenticalObject($this->objects[0], $stores[0]->get($key));
      // Another user should get the same result.
      $metadata = $stores[1]->getMetadata($key);
      $this->assertEqual($users[0], $metadata->owner);
      $this->assertIdenticalObject($this->objects[0], $stores[1]->get($key));
    }

    // Remove the item and try to set it again.
    $stores[0]->delete($key);
    $stores[0]->setIfNotExists($key, $this->objects[1]);
    // This time it should succeed.
    $this->assertIdenticalObject($this->objects[1], $stores[0]->get($key));

    // This user can update the object.
    $stores[0]->set($key, $this->objects[2]);
    $this->assertIdenticalObject($this->objects[2], $stores[0]->get($key));
    // The object is the same when another user loads it.
    $this->assertIdenticalObject($this->objects[2], $stores[1]->get($key));

    // This user should be allowed to get, update, delete.
    $this->assertTrue($stores[0]->getIfOwner($key) instanceof \stdClass);
    $this->assertTrue($stores[0]->setIfOwner($key, $this->objects[1]));
    $this->assertTrue($stores[0]->deleteIfOwner($key));

    // Another user can update the object and become the owner.
    $stores[1]->set($key, $this->objects[3]);
    $this->assertIdenticalObject($this->objects[3], $stores[0]->get($key));
    $this->assertIdenticalObject($this->objects[3], $stores[1]->get($key));
    $metadata = $stores[1]->getMetadata($key);
    $this->assertEqual($users[1], $metadata->owner);

    // The first user should be informed that the second now owns the data.
    $metadata = $stores[0]->getMetadata($key);
    $this->assertEqual($users[1], $metadata->owner);

    // The first user should no longer be allowed to get, update, delete.
    $this->assertNull($stores[0]->getIfOwner($key));
    $this->assertFalse($stores[0]->setIfOwner($key, $this->objects[1]));
    $this->assertFalse($stores[0]->deleteIfOwner($key));

    // Now manually expire the item (this is not exposed by the API) and then
    // assert it is no longer accessible.
    db_update('key_value_expire')
      ->fields(array('expire' => REQUEST_TIME - 1))
      ->condition('collection', "user.shared_tempstore.$collection")
      ->condition('name', $key)
      ->execute();
    $this->assertFalse($stores[0]->get($key));
    $this->assertFalse($stores[1]->get($key));
  }

}