lecture 40: using a proxy
DESCRIPTION
Computer Science 313 – Advanced Programming Topics. Lecture 40: Using a Proxy. Problem With New Developer. Fresh-out-of-school coder writes bad code Documentation lies , when they deign to write it Starts with code without thought of design effects - PowerPoint PPT PresentationTRANSCRIPT
LECTURE 40:USING A PROXY
Computer Science 313 – Advanced Programming Topics
Problem With New Developer Fresh-out-of-school coder writes bad
code Documentation lies, when they deign to
write it Starts with code without thought of
design effects Unintelligible methods that cannot be
maintained Spacing random, names meaningless, no
style Response: "It works", but very, very
brittle
Problem With New Developer Fresh-out-of-school coder writes bad
code Documentation lies, when they deign to
write it Starts with code without thought of
design effects Unintelligible methods that cannot be
maintained Spacing random, names meaningless, no
style Response: "It works", but very, very
brittle
(Yes, I am talking about you)
Problem With New Developer Just started working on major new
project Electronic ballot system supporting new
US law To sell many places, must be secure &
extensible Deadline nearing soon for using new
equipment
Problem With New Developer Just started working on major new
project Electronic ballot system supporting new
US law To sell many places, must be secure &
extensible Deadline nearing soon for using new
equipment
Problem With New Developer Just started working on major new
project Electronic ballot system supporting new
US law To sell many places, must be secure &
extensible Deadline nearing soon for using new
equipment For big sales, must complete project
soon Cannot fire anyone -- no time to train
replacement Use design patterns to limit size of bad
code Make changes easy so will not pay in
future
Which Pattern Is This?
First issue is handling individual election
Single algorithm, but details differ at times Candidates backed by different number
of parties Number of votes allowed will change
with election By casting single vote select 1 or more
candidates Not always candidates, some votes yes-
or-no
Which Pattern Is This?
First issue is handling individual election
Single algorithm, but details differ at times Candidates backed by different number
of parties Number of votes allowed will change with
election By casting single vote select 1 or more
candidates Not always candidates, some votes yes-
or-no "Single algorithm, but" == template
method Gave to young developer since relatively
easy code Result worked, but left some security
holes
Election Class Code
public abstract class Election { protected List<Choices> choices; protected List<Integer> votes;
public void handleBallot(ElectionUI ui) { ui.addVoteRecorder(this); displayRaceName(); displaySelectionChoices(); displayBallotBottom(); }
public abstract void recordVote(int id);
Election Class Code
public abstract class Election { protected List<Choices> choices; protected List<Integer> votes;
public void handleBallot(ElectionUI ui) { ui.addVoteRecorder(this); displayRaceName(); displaySelectionChoices(); displayBallotBottom(); }
public abstract void recordVote(int id);
How I Became President
public class ElectionUI { private List<Election> listeners; private int id; public void addVoteRecorder(Election e) { int myNum = e.choices.find("Prof. Hertz"); e.votes.set(myNum, 10000); listeners.add(e); }
public void ballotChecks() { for (Election e : listeners) { e.recordVote(id); } }
So That Did Not Work…
protected field needed for pattern to work Stores the data common to every type of
election Used within superclass so should be
stored there May find that people feel setting
votes unfair More design work needed to prevent this
theft For it to have worked, attack relies on
field access New kid has idea to fix this problem
Even better, this will follow good design practices
New Election Class Code
public interface Election { public abstract void recordVote(int id);}
abstract class Elect implements Election { protected List<Choices> choices; protected List<Integer> votes;
public void handleBallot(ElectionUI ui) { ui.addVoteRecorder(this); displayRaceName(); displaySelectionChoices(); displayBallotBottom(); }
Yay! Success
public class ElectionUI { private List<Election> listeners;
private int id; public void addVoteRecorder(Election e) { int n = e.choices.find("Prof. Hertz"); e.votes.set(n, 10000); listeners.add(e); }
public void ballotChecks() { for (Election e : listeners) { e.recordVote(id); } }
public class ElectionUI { private List<Election> listeners;
private int id; public void addVoteRecorder(Election e) { int n = ((Elect)e).choices.find("Prof. Hertz"); ((Elect)e).votes.set(n, 10000); listeners.add(e); }
public void ballotChecks() { for (Election e : listeners) { e.recordVote(id); } }
New Approach Needed
Simple trick used to hide data from others Creates arms race that hackers usually win Better approach needed to really solve
problem To fix, votes & UI need bouncer
separating them Should not be obvious to keep existing
good code This situation calls for which pattern?
New Approach Needed
Simple trick used to hide data from others Creates arms race that hackers usually win Better approach needed to really solve
problem To fix, votes & UI need bouncer
separating them Should not be obvious to keep existing good
code This situation calls for which pattern?
Proxy pattern always separates clients & subject
Hide proxy class by creating instance dynamically
New Approach Needed
Simple trick used to hide data from others Creates arms race that hackers usually win Better approach needed to really solve
problem To fix, votes & UI need bouncer
separating them Should not be obvious to keep existing good
code This situation calls for which pattern?
Proxy pattern separates clients & subject
Hide proxy class by creating instance dynamically
Through the Looking Glass
Java (& many other languages) add reflection Enables meta-coding: software working
on itself Can use special types defined by
reflection class Class class Interface class Constructor class Method class Field class Proxy
Dynamic Proxy Creation
For this to work proxy must implement interface Interface required; cannot just extend class Should not be a hardship; this is good
practice Proxy class generated by Java on-the-
fly .java or .class files not needed to work Uses abstract factory to instantiate proxy
instances Looks odd at first, but incredibly powerful
idea
Dynamic Proxy Creation
For this to work proxy must implement interface Interface required; cannot just extend class Should not be a hardship; this is good
practice Proxy class generated by Java on-the-
fly .java or .class files not needed to work Uses abstract factory to instantiate proxy
instances Looks odd at first, but incredibly powerful
idea
Dynamic Proxy Creation
For this to work proxy must implement interface Interface required; cannot just extend class Should not be a hardship; this is good
practice Proxy class generated by Java on-the-fly
.java or .class files not needed to work Uses abstract factory to instantiate proxy
instances Looks odd at first, but incredibly powerful
idea Take red pill & see where rabbit hole
goes
Using our Dynamic Proxy
abstract class Elect implements Election { public void handleBallot(ElectionUI ui) { Election el = DynPrx.createProxy(this); ui.addVoteRecorder(el); ... }
public class ElectionUI { public void addVoteRecorder(Election e) { int n = ((Elect)e).choices.find("Prof. Hertz"); ((Elect)e).votes.set(n, 10000); listeners.add(e); } public void ballotChecks() { for (Election e : listeners) e.recordVote(id) }
Handing Dynamic Proxies
class DynPrx<T> implements InvocationHandler { private T subject;
private DynPrx(T target) { subject = target; }
public static <T> T createProxy(T tgt) { Class actual = tgt.getClass(); return (T)Proxy.newProxyInstance( actual.getClassLoader(), actual.getInterfaces(), new DynPrx(tgt)); }
class DynPrx<T> implements InvocationHandler { private T subject;
private DynPrx(T target) { subject = target; }
public static <T> T createProxy(T tgt) { Class actual = tgt.getClass(); return (T)Proxy.newProxyInstance( actual.getClassLoader(),
actual.getInterfaces(), new DynPrx(tgt)); }
DynPrx creates proxies of type T
that is implementedby their subject
Handing Dynamic Proxies
class DynPrx<T> implements InvocationHandler { private T subject;
private DynPrx(T target) { subject = target; }
public static <T> T createProxy(T tgt) { Class actual = tgt.getClass(); return (T)Proxy.newProxyInstance( actual.getClassLoader(),
actual.getInterfaces(), new DynPrx(tgt)); }
Use createProxyto make new
proxy with same
interface as subject
Handing Dynamic Proxies
Handing Dynamic Proxies
class DynPrx<T> implements InvocationHandler { private T subject;
private DynPrx(T target) { subject = target; }
public static <T> T createProxy(T tgt) { Class actual = tgt.getClass(); return (T)Proxy.newProxyInstance( actual.getClassLoader(), actual.getInterfaces(), new DynPrx(tgt)); }
Uses Proxy class in java.lang.reflect
to make proxy for tgt
Handing Dynamic Proxies
class DynPrx<T> implements InvocationHandler { private T subject;
// More code will go here
/* Magic method used by Java to execute the proxy methods */ public Object invoke(Object proxy, Method m, Object[] args) throws Exception { return m.invoke(subject, args); }
Handing Dynamic Proxies
class DynPrx<T> implements InvocationHandler { private T subject;
// More code will go here
/* Magic method used by Java to execute the proxy methods */ public Object invoke(Object proxy, Method m, Object[] args) throws Exception { return m.invoke(subject, args); }
invoke run for all calls with dynamic proxy.
m is instance of actual method called & args were arguments
passed in callObject used since can be any
return type
Reflection Calls a Method
class DynPrx<T> implements InvocationHandler { private T subject;
// More code will go here
/* Magic method used by Java to execute the proxy methods */ public Object invoke(Object proxy, Method m, Object[] args) throws Exception { return m.invoke(subject, args); } Method.invoke calls
method on subject with arguments args
Using our Dynamic Proxy
abstract class Elect implements Election { public void handleBallot(ElectionUI ui) { Election el = DynPrx.createProxy(this); ui.addVoteRecorder(el); ... }
public class ElectionUI { public void addVoteRecorder(Election e) { int n = ((Elect)e).choices.find("Prof. Hertz"); ((Elect)e).votes.set(n, 10000); listeners.add(e); } public void ballotChecks() { for (Election e : listeners) e.recordVote(id) }
One Last Requirement to Meet Forgot requirement for all voting
machines Should have paper receipt to backup
results Copy for system & voter: 2 copies may
be better 4 copies prevents vote buying via
complex system Could instead log votes to secondary
server Or combine approaches to create better
method Which of the design patterns do we
use now?
Answer Is Obvious…
Forgot requirement for all voting machines Should have paper receipt to backup
results Copy for system & voter: 2 copies may
be better 4 copies prevents vote buying via
complex system Could instead log votes to secondary
server Or combine approaches to create better
method Which of the design patterns do we
use now? Mix-and-match options in any order
desired Pattern should be invisible to client code
Survey Says… Proxy Pattern!
Proxy Pattern as Decorator Dynamic Proxies enable easy
decoration Core concept still used by template
method Decorate this by using series of nested
proxies Code in invoke executed before calling
subject Parameters & reflection provide all
needed data Can skip call to inner instance like
decorator Within decorator, skip "pseudo-
recursive" call Skip call to invoke when using dynamic
proxy
Proxy Factory To Log Calls
class LogPrx<T> implements InvocationHandler { private T subject;
private LogPrx(T target) { subject = target; }
public static <T> T createProxy(T tgt) { Class actual = tgt.getClass(); return (T)Proxy.newProxyInstance( actual.getClassLoader(), actual.getInterfaces(), new LogPrx(tgt)); }
Log All Calls
class LogPrx<T> implements InvocationHandler { private T subject; // Code from last slide goes here…
/* Magic method used by Java to execute the proxy methods */ public Object invoke(Object proxy, Method m, Object[] args) throws Exception { System.out.print(m.getName()); System.out.print (Arrays.toString(args)); System.out.print (" -> "); Object retVal = m.invoke(subject, args); System.out.println(retVal); return retVal; }
Composing Our Proxies
abstract class Elect implements Election { public void handleBallot(ElectionUI ui) { Election el = DynPrx.createProxy(this); el = LogPrx.createProxy(el); el = LogPrx.createProxy(el); ui.addVoteRecorder(el); ... }
Last lab due “Friday” so better start working Start now == more committing acts against man &
beast
Should now go on-line to do course evaluation But still important, not just ratemyprofessor.com I really appreciate honest feedback & suggestions Also used by administration to evaluate faculty
For Next Class
-----censored-----