|
N.B.
Il codice di questa pagina ha significato puramente teorico. Purtroppo non è stato possibile analizzarne il comportamento nella pratica, ove peraltro potrebbe risultare completamente inadatto o errato. In linea di principio però, vista anche la semplicità degli algoritmi proposti, può dirsi corretto: si tratta di comunicare al Server quando una applicazione ha inizio o termine e attendere la conferma prima di iniziarne l'elaborazione.
Fin dall'inizio si possono poi fare alcune considerazioni:
- Cosa accade se l'utente chiude il canale sicuro prima che un applicazione termini ?
- Cosa accade se la risposta del CountServer si fa attendere in eterno ?
E' evidente quanto sia necessario raffinare gli algoritmi proposti. Purtroppo non è possibile spingersi più avanti visto il mancato riscontro pratico, dato dalla non operatività del pacchetto da noi prodotto, alla quale, in fase di sviluppo, saremmo soggetti.
|
Utilizziamo come esempio una delle Applet a corredo del JDK 1.2, leggermente modificata .
Cliccare sull'immagine per ingrandire.
XYZApp.java:
@(#)XYZApp.java 1.8 98/06/29
import java.applet.Applet;
import java.awt.Button;
import java.awt.BorderLayout;
import java.awt.Panel;
import java.awt.Image;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Dimension;
import java.io.*;
import java.lang.*;
import java.net.URL;
import java.util.Hashtable;
import java.awt.image.IndexColorModel;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.event.*;
/** The representation of a Chemical .xyz model */
class XYZChemModel {
float vert[];
Atom atoms[];
int tvert[];
int ZsortMap[];
int nvert, maxvert;
static Hashtable atomTable = new Hashtable();
static Atom defaultAtom;
static {
atomTable.put("c", new Atom(0, 0, 0));
atomTable.put("h", new Atom(210, 210, 210));
atomTable.put("n", new Atom(0, 0, 255));
atomTable.put("o", new Atom(255, 0, 0));
atomTable.put("p", new Atom(255, 0, 255));
atomTable.put("s", new Atom(255, 255, 0));
atomTable.put("hn", new Atom(150, 255, 150));
defaultAtom = new Atom(255, 100, 200);
}
boolean transformed;
Matrix3D mat;
float xmin, xmax, ymin, ymax, zmin, zmax;
XYZChemModel () {
mat = new Matrix3D();
mat.xrot(20);
mat.yrot(30);
}
/** Create a Cehmical model by parsing an input stream */
XYZChemModel (InputStream is) throws Exception {
this();
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(is)));
st.eolIsSignificant(true);
st.commentChar('#');
int slot = 0;
try{
scan:
while (true) {
switch ( st.nextToken() ){
case StreamTokenizer.TT_EOF:
break scan;
default:
break;
case StreamTokenizer.TT_WORD:
String name = st.sval;
double x = 0, y = 0, z = 0;
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
x = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
y = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER)
z = st.nval;
}
}
addVert(name, (float) x, (float) y, (float) z);
while( st.ttype != StreamTokenizer.TT_EOL && st.ttype != StreamTokenizer.TT_EOF )
st.nextToken();
} // end Switch
} // end while
is.close();
} // end Try
catch( IOException e) {}
if (st.ttype != StreamTokenizer.TT_EOF)
throw new Exception(st.toString());
} // end XYZChemModel()
/** Add a vertex to this model */
int addVert(String name, float x, float y, float z) {
int i = nvert;
if (i >= maxvert)
if (vert == null) {
maxvert = 100;
vert = new float[maxvert * 3];
atoms = new Atom[maxvert];
} else {
maxvert *= 2;
float nv[] = new float[maxvert * 3];
System.arraycopy(vert, 0, nv, 0, vert.length);
vert = nv;
Atom na[] = new Atom[maxvert];
System.arraycopy(atoms, 0, na, 0, atoms.length);
atoms = na;
}
Atom a = (Atom) atomTable.get(name.toLowerCase());
if (a == null) a = defaultAtom;
atoms[i] = a;
i *= 3;
vert[i] = x;
vert[i + 1] = y;
vert[i + 2] = z;
return nvert++;
}
/** Transform all the points in this model */
void transform() {
if (transformed || nvert <= 0)
return;
if (tvert == null || tvert.length < nvert * 3)
tvert = new int[nvert * 3];
mat.transform(vert, tvert, nvert);
transformed = true;
}
/** Paint this model to a graphics context. It uses the matrix associated
with this model to map from model space to screen space.
The next version of the browser should have double buffering,
which will make this *much* nicer */
void paint(Graphics g) {
if (vert == null || nvert <= 0)
return;
transform();
int v[] = tvert;
int zs[] = ZsortMap;
if (zs == null) {
ZsortMap = zs = new int[nvert];
for (int i = nvert; --i >= 0;)
zs[i] = i * 3;
}
/*
* I use a bubble sort since from one iteration to the next, the sort
* order is pretty stable, so I just use what I had last time as a
* "guess" of the sorted order. With luck, this reduces O(N log N)
* to O(N)
*/
for (int i = nvert - 1; --i >= 0;) {
boolean flipped = false;
for (int j = 0; j <= i; j++) {
int a = zs[j];
int b = zs[j + 1];
if (v[a + 2] > v[b + 2]) {
zs[j + 1] = a;
zs[j] = b;
flipped = true;
}
}
if (!flipped)
break;
}
int lg = 0;
int lim = nvert;
Atom ls[] = atoms;
if (lim <= 0 || nvert <= 0)
return;
for (int i = 0; i < lim; i++) {
int j = zs[i];
int grey = v[j + 2];
if (grey < 0)
grey = 0;
if (grey > 15)
grey = 15;
// g.drawString(names[i], v[j], v[j+1]);
atoms[j/3].paint(g, v[j], v[j + 1], grey);
// g.drawImage(iBall, v[j] - (iBall.width >> 1), v[j + 1] -
// (iBall.height >> 1));
}
}
/** Find the bounding box of this model */
void findBB() {
if (nvert <= 0)
return;
float v[] = vert;
float xmin = v[0], xmax = xmin;
float ymin = v[1], ymax = ymin;
float zmin = v[2], zmax = zmin;
for (int i = nvert * 3; (i -= 3) > 0;) {
float x = v[i];
if (x < xmin)
xmin = x;
if (x > xmax)
xmax = x;
float y = v[i + 1];
if (y < ymin)
ymin = y;
if (y > ymax)
ymax = y;
float z = v[i + 2];
if (z < zmin)
zmin = z;
if (z > zmax)
zmax = z;
}
this.xmax = xmax;
this.xmin = xmin;
this.ymax = ymax;
this.ymin = ymin;
this.zmax = zmax;
this.zmin = zmin;
}
}
/** An applet to put a Chemical model into a page */
public class XYZApp
extends Applet
implements Runnable, MouseListener, MouseMotionListener {
StartTime start = null;
StopTime stop = null;
XYZChemModel md;
boolean painted = true;
float xfac;
int prevx, prevy;
float xtheta, ytheta;
float scalefudge = 1;
Matrix3D amat = new Matrix3D(), tmat = new Matrix3D();
String mdname = null, precedente = null;
String message = null;
Image backBuffer;
Graphics backGC;
Dimension backSize;
Button[] b=new Button[6];
private synchronized void newBackBuffer() {
backBuffer = createImage(getSize().width, getSize().height);
backGC = backBuffer.getGraphics();
backSize = getSize();
}
public void init() {
/* Si comunica al CountServer l'intenzione di eseguire l'applicazione, dopodichè si attende la conferma.*/
try {
start = new StartTime();
if ((start.startTime()==false) System.exit(1);
} catch (Exception e) { System.out.println(e); }
b[0]=new Button("benzene");
add(b[0]);
b[0].addActionListener(new GestButton());
b[1]=new Button("buckminsterfullerine");
add(b[1]);
b[1].addActionListener(new GestButton());
b[2]=new Button("cyclohexane");
add(b[2]);
b[2].addActionListener(new GestButton());
b[3]=new Button("ethane");
add(b[3]);
b[3].addActionListener(new GestButton());
b[4]=new Button("HyaluronicAcid");
add(b[4]);
b[4].addActionListener(new GestButton());
b[5]=new Button("water");
add(b[5]);
b[5].addActionListener(new GestButton());
try {
scalefudge = Float.valueOf(getParameter("scale")).floatValue();
} catch(Exception e) {};
amat.yrot(20);
amat.xrot(20);
resize(getSize().width <= 20 ? 400 : getSize().width,
getSize().height <= 20 ? 400 : getSize().height);
newBackBuffer();
addMouseListener(this);
addMouseMotionListener(this);
}
public void destroy() {
removeMouseListener(this);
removeMouseMotionListener(this);
b[0].removeActionListener(new GestButton());
b[1].removeActionListener(new GestButton());
b[2].removeActionListener(new GestButton());
b[3].removeActionListener(new GestButton());
b[4].removeActionListener(new GestButton());
b[5].removeActionListener(new GestButton());
/* Si comunica al CountServer l'intenzione di terminare l'applicazione e si esce senza attendere conferma.*/
try {
stop = new StopTime();
stop.stopTime("Http://AndreA",8089);
} catch (Exception e) {
System.out.println(e);
}
}
public void run() {
InputStream is = null;
do {
try {
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
while ((mdname==null) || (mdname.equals(precedente))) Thread.currentThread().sleep(1000);
precedente=mdname;
is = new URL(getDocumentBase(), "models/"+mdname+".xyz").openStream();
XYZChemModel m = new XYZChemModel (is);
Atom.setApplet(this);
md = m;
m.findBB();
float xw = m.xmax - m.xmin;
float yw = m.ymax - m.ymin;
float zw = m.zmax - m.zmin;
if (yw > xw)
xw = yw;
if (zw > xw)
xw = zw;
float f1 = getSize().width / xw;
float f2 = getSize().height / xw;
xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
} catch(Exception e) {
e.printStackTrace();
md = null;
message = e.toString();
}
try {
if (is != null)
is.close();
} catch(Exception e) {}
repaint();
} while (true);
}
public void start() {
if (md == null && message == null)
new Thread(this).start();
}
public void stop() {
}
/* event handling */
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
prevx = e.getX();
prevy = e.getY();
e.consume();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
int x = e.getX();
int y = e.getY();
tmat.unit();
float xtheta = (prevy - y) * (360.0f / getSize().width);
float ytheta = (x - prevx) * (360.0f / getSize().height);
tmat.xrot(xtheta);
tmat.yrot(ytheta);
amat.mult(tmat);
if (painted) {
painted = false;
repaint();
}
prevx = x;
prevy = y;
e.consume();
}
public void mouseMoved(MouseEvent e) {
}
public void update(Graphics g) {
if (backBuffer == null)
g.clearRect(0, 0, getSize().width, getSize().height);
paint(g);
}
public void paint(Graphics g) {
if (md != null) {
md.mat.unit();
md.mat.translate(-(md.xmin + md.xmax) / 2,
-(md.ymin + md.ymax) / 2,
-(md.zmin + md.zmax) / 2);
md.mat.mult(amat);
// md.mat.scale(xfac, -xfac, 8 * xfac / getSize().width);
md.mat.scale(xfac, -xfac, 16 * xfac / getSize().width);
md.mat.translate(getSize().width / 2, getSize().height / 2, 8);
md.transformed = false;
if (backBuffer != null) {
if (!backSize.equals(getSize()))
newBackBuffer();
backGC.setColor(getBackground());
backGC.fillRect(0,0,getSize().width,getSize().height);
md.paint(backGC);
g.drawImage(backBuffer, 0, 0, this);
} else md.paint(g);
setPainted();
} else if (message != null) {
g.drawString("Error in model:", 3, 20);
g.drawString(message, 10, 40);
}
}
private synchronized void setPainted() {
painted = true;
notifyAll();
}
private synchronized void waitPainted(){
while (!painted) {
try {
wait();
}
catch (InterruptedException e) {}
}
painted = false;
}
public String getAppletInfo() {
return "Title: XYZApp \nAuthor: James Gosling \nAn applet to put a Chemical model into a page.";
}
public String[][] getParameterInfo() {
String[][] info = {
{"model", "path string", "The path to the model to be displayed in .xyz format (see http://chem.leeds.ac.uk/Project/MIME.html). Default is model.obj."},
{"scale", "float", "Scale factor. Default is 1 (i.e. no scale)."}
};
return info;
}
class GestButton implements ActionListener {
public void actionPerformed(ActionEvent evt) {
precedente=mdname;
mdname = evt.getActionCommand();
}
}
} // end class XYZApp
class Atom {
private static Applet applet;
private static byte[] data;
private final static int R = 40;
private final static int hx = 15;
private final static int hy = 15;
private final static int bgGrey = 192;
private final static int nBalls = 16;
private static int maxr;
private int Rl;
private int Gl;
private int Bl;
private Image balls[];
static {
data = new byte[R * 2 * R * 2];
int mr = 0;
for (int Y = 2 * R; --Y >= 0;) {
int x0 = (int) (Math.sqrt(R * R - (Y - R) * (Y - R)) + 0.5);
int p = Y * (R * 2) + R - x0;
for (int X = -x0; X < x0; X++) {
int x = X + hx;
int y = Y - R + hy;
int r = (int) (Math.sqrt(x * x + y * y) + 0.5);
if (r > mr)
mr = r;
data[p++] = r <= 0 ? 1 : (byte) r;
}
}
maxr = mr;
}
static void setApplet(Applet app) {
applet = app;
}
Atom(int Rl, int Gl, int Bl) {
this.Rl = Rl;
this.Gl = Gl;
this.Bl = Bl;
}
private final int blend(int fg, int bg, float fgfactor) {
return (int) (bg + (fg - bg) * fgfactor);
}
private void Setup() {
balls = new Image[nBalls];
byte red[] = new byte[256];
red[0] = (byte) bgGrey;
byte green[] = new byte[256];
green[0] = (byte) bgGrey;
byte blue[] = new byte[256];
blue[0] = (byte) bgGrey;
for (int r = 0; r < nBalls; r++) {
float b = (float) (r+1) / nBalls;
for (int i = maxr; i >= 1; --i) {
float d = (float) i / maxr;
red[i] = (byte) blend(blend(Rl, 255, d), bgGrey, b);
green[i] = (byte) blend(blend(Gl, 255, d), bgGrey, b);
blue[i] = (byte) blend(blend(Bl, 255, d), bgGrey, b);
}
IndexColorModel model = new IndexColorModel(8, maxr + 1,
red, green, blue, 0);
balls[r] = applet.createImage(
new MemoryImageSource(R*2, R*2, model, data, 0, R*2));
}
}
void paint(Graphics gc, int x, int y, int r) {
Image ba[] = balls;
if (ba == null) {
Setup();
ba = balls;
}
Image i = ba[r];
int size = 10 + r;
gc.drawImage(i, x - (size >> 1), y - (size >> 1), size, size, applet);
}
}
/*******************************************************************/
StartTime.java:
import java.io.*;
import java.net.*;
import iaik.security.ssl.*;
import iaik.java.security.*;
import iaik.x509.X509Certificate;
import com.entrust.security.provider.*;
import com.entrust.x509.*;
import com.entrust.x509.directory.*;
import com.entrust.toolkit.ETKCertificateVerifier;
public class StartTime {
InputStream sslInputStream = null;
OutputStream sslOutputStream = null;
SSLSocket socket = null;
/* Ripristino i parametri della connessione */
public boolean startTime ( String server, int port) throws Exception {
// Create the client context
SSLClientContext clientContext = new SSLClientContext();
// Prepare the client context to use some strong ciphers
CipherSuite[] suites = {
CipherSuite.SSL_RSA_WITH_3DES_EDE_CBC_SHA,
CipherSuite.SSL_RSA_WITH_RC4_SHA,
CipherSuite.SSL_RSA_WITH_RC4_MD5
};
clientContext.setEnabledCipherSuites( suites );
// Generate a trust decider object and add it to the client context
// ClientTrustDecider trustDecider = new ETKCertificateVerifier( directory, profile );
// clientContext.setTrustDecider( trustDecider );
// Connect to the remote host by creating a new SSLSocket
socket = new SSLSocket( server, port, clientContext );
// Retrieve the I/O streams from the SSLSocket
sslInputStream = socket.getInputStream();
sslOutputStream = socket.getOutputStream();
DataInputStream inStream = new DataInputStream(sslInputStream);
DataOutputStream outStream = new DataOutputStream(sslOutputStream);
// Even though the constructor has not yet finished, at this point
// an SSL connection has been established.
System.out.println( "-- Connected to Server\n" );
// Check which cipher and key length has been chosen
// Note that the cipher suite is only available after either
// SSLSocket.getInputStream() or SSLSocket.getOutputStream() has been
// called.
CipherSuite cs = socket.getActiveCipherSuite();
if ( cs == null ) {
System.out.println( "-- ERROR: Active Cipher Suite is null" );
} else {
if ( cs.keyMaterial() == cs.expandedKeyMaterial() ) {
System.out.println( " Active Algorithm : " +
cs.cipherAlgorithm() + " with "
+ cs.keyMaterial()*8 +
" bit key\n" );
} else {
System.out.println( "-- Warning : EXPORT Strength Algorithm Chosen" );
System.out.println( " Active Algorithm : " + cs.cipherAlgorithm() );
System.out.println( " Actual Key Material : " + cs.keyMaterial() );
System.out.println( " Expanded Key Material : " + cs.expandedKeyMaterial() );
System.out.println( "" );
}
}
/* La comunicazione col CountServer avviene necessariamente su canale sicuro (già instaurato precedentemente). Si tratta di trasmettere il valore 10, e attendere la ricezione della risposta del Server: se anche questa è uguale a 10 l'applicazione può essere eseguita altrimenti viene chiusa./*
outStream.writeInt(10);
int Start = inStream.readInt();
if(Start == 10) return true;
else return false;
close(socket);
}
}
/*******************************************************************/
StopTime.java:
import java.io.*;
import java.net.*;
import iaik.security.ssl.*;
import iaik.java.security.*;
import iaik.x509.X509Certificate;
import com.entrust.security.provider.*;
import com.entrust.x509.*;
import com.entrust.x509.directory.*;
import com.entrust.toolkit.ETKCertificateVerifier;
public class SSTime {
InputStream sslInputStream = null;
OutputStream sslOutputStream = null;
SSLSocket socket = null;
/* Ripristino i parametri della connessione */
public void stopTime ( String server, int port) throws Exception {
// Create the client context
SSLClientContext clientContext = new SSLClientContext();
// Prepare the client context to use some strong ciphers
CipherSuite[] suites = {
CipherSuite.SSL_RSA_WITH_3DES_EDE_CBC_SHA,
CipherSuite.SSL_RSA_WITH_RC4_SHA,
CipherSuite.SSL_RSA_WITH_RC4_MD5
};
clientContext.setEnabledCipherSuites( suites );
// Generate a trust decider object and add it to the client context
// ClientTrustDecider trustDecider = new ETKCertificateVerifier( directory, profile );
// clientContext.setTrustDecider( trustDecider );
// Connect to the remote host by creating a new SSLSocket
socket = new SSLSocket( server, port, clientContext );
// Retrieve the I/O streams from the SSLSocket
sslInputStream = socket.getInputStream();
sslOutputStream = socket.getOutputStream();
DataInputStream inStream = new DataInputStream(sslInputStream);
DataOutputStream outStream = new DataOutputStream(sslOutputStream);
// Even though the constructor has not yet finished, at this point
// an SSL connection has been established.
System.out.println( "-- Connected to Server\n" );
// Check which cipher and key length has been chosen
// Note that the cipher suite is only available after either
// SSLSocket.getInputStream() or SSLSocket.getOutputStream() has been
// called.
CipherSuite cs = socket.getActiveCipherSuite();
if ( cs == null ) {
System.out.println( "-- ERROR: Active Cipher Suite is null" );
} else {
if ( cs.keyMaterial() == cs.expandedKeyMaterial() ) {
System.out.println( " Active Algorithm : " +
cs.cipherAlgorithm() + " with "
+ cs.keyMaterial()*8 +
" bit key\n" );
} else {
System.out.println( "-- Warning : EXPORT Strength Algorithm Chosen" );
System.out.println( " Active Algorithm : " + cs.cipherAlgorithm() );
System.out.println( " Actual Key Material : " + cs.keyMaterial() );
System.out.println( " Expanded Key Material : " + cs.expandedKeyMaterial() );
System.out.println( "" );
}
}
/* La comunicazione col CountServer avviene necessariamente su canale sicuro (già instaurato precedentemente). Consiste trasmettere il valore 20 per comunicare di aver terminato l'utilizzo della applicazione/*
outStream.writeInt(20);
close(socket);
}
}
|
|