The Source for Java Technology Collaboration
User: Password:



Jayson Falkner's Blog

March 2006 Archives


Blard #24: An image rollover JSP .tag

Posted by jfalkner on March 27, 2006 at 11:05 PM | Permalink | Comments (1)

This is an example of a good use of JSP .tag files, a DHTML widget for making image rollovers. It was originally encoded as an example during a Develop Mentor Java Web Tier course I taught. As with all my stuff, it is free for commercial and non-commercial use. If you like it, please remember to mention who originally wrote the code.

Here is the code. Save it in your WEB-INF/tags directory.

<%@ tag isELIgnored="false" %>
<%@ attribute name="image1" required="true" %>
<%@ attribute name="image2" required="true" %>
<%@ attribute name="link" required="true" %>
<%@ attribute name="name" required="true" %>

<a href="${link}">
<image src="${image1}" border="0"
  name="${name}" 
  onmouseover="document.${name}.src='${image2}'"
  onmouseout="document.${name}.src='${image1}'"></a>

Using the code requires importing the taglib and setting attributes for the name, image1, image2, and link attributes. The name can be anything, but it must be unique out of all the other tags on the page. The two image attributes are the images to show initially and when the mouse is over respectively. The link attribute is for setting a hyperlink.

Here is an example JSP.

<%@ taglib prefix="x" tagdir="/WEB-INF/tags" %>
<html>
<h1>HelloWorld</h1>

<x:Rollover
  name="news"
  image1="http://www.proteomecommons.org/archive/1129421002687/news.jpg"
  image2="http://www.proteomecommons.org/archive/1129421002687/news-bite.jpg"
  link="http://www.google.com"/><br/>
  
</html>


Blarg #23: Can't use the back button filter.

Posted by jfalkner on March 27, 2006 at 10:52 PM | Permalink | Comments (2)

This is an example Filter that uses JavaScript to try and ensure that people can't click the back button to revisit pages on your website. It was originally encoded as an example during a Develop Mentor course I taught. It is a nice example of a servlet filter that buffers a response, locates the body tag using a simple regular expression, and inserts a call to 'history.forward()'. As with all my stuff, it is free for commercial and non-commercial use. If you like it, please remember to mention who originally wrote the code.

The code. Remember each filter has three parts: the Filter, ServletResponseWrapper, and ServletOutputStream sub-class.

CantGoBackFilter.java

This filter wraps the HttpServletResponse in order to buffer text sent out to a client.

package example.cgb;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class CantGoBackFilter implements Filter {
    ServletContext sc = null;
    
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        // check that it is a HTTP request
        if (req instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            
            // nonce encode the normal output
            CantGoBackResponseWrapper wrappedResponse = new CantGoBackResponseWrapper(
                    response, sc);

            chain.doFilter(req, wrappedResponse);
            // finish the respone
            wrappedResponse.finishResponse();
        }
    }
    
    public void init(FilterConfig filterConfig) {
        // reference the context
        sc = filterConfig.getServletContext();
    }
    
    public void destroy() {
        // noop
    }
}

CantGoBackResponseWrapper.java

This wrapper sends back a custom ServletOutputStream object in order to buffer all text that is being sent to the client.

package example.cgb;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class CantGoBackResponseWrapper extends HttpServletResponseWrapper {
    protected HttpServletResponse origResponse = null;
    protected ServletOutputStream stream = null;
    protected PrintWriter writer = null;
    ServletContext sc;
    
    public CantGoBackResponseWrapper(HttpServletResponse response, ServletContext sc) {
        super(response);
        this.sc = sc;
        origResponse = response;
    }
    
    public ServletOutputStream createOutputStream() throws IOException {
        return (new CantGoBackResponseStream(origResponse, sc));
    }
    
    public void finishResponse() {
        try {
            if (writer != null) {
                writer.close();
            } else {
                if (stream != null) {
                    stream.close();
                }
            }
        } catch (IOException e) {}
    }
    
    public void flushBuffer() throws IOException {
        stream.flush();
    }
    
    public ServletOutputStream getOutputStream() throws IOException {
        if (writer != null) {
            throw new IllegalStateException("getWriter() has already been called!");
        }
        
        if (stream == null)
            stream = createOutputStream();
        return (stream);
    }
    
    public PrintWriter getWriter() throws IOException {
        if (writer != null) {
            return (writer);
        }
        
        if (stream != null) {
            throw new IllegalStateException("getOutputStream() has already been called!");
        }
        
        stream = createOutputStream();
        // BUG FIX 2003-12-01 Reuse content's encoding, don't assume UTF-8
        writer = new PrintWriter(new OutputStreamWriter(stream, origResponse.getCharacterEncoding()));
        return (writer);
    }
    
    public void setContentLength(int length) {}
}

CantGoBackResponseStream.java

This response stream buffers all text that is send to the client and uses a regular expression to locate the body tag and inject a JavaScript call to 'history.forward()', which fools most users in to thinking that they can't use the back button.

package example.cgb;

import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 *
 * @author Jayson Falkner - jayson@jspinsider.com
 */
public class CantGoBackResponseStream extends ServletOutputStream {
    // abstraction of the output stream used for compression
    protected OutputStream bufferedOutput = null;
    
    // state keeping variable for if close() has been called
    protected boolean closed = false;
    
    // reference to original response
    protected HttpServletResponse response = null;
    
    // reference to the output stream to the client's browser
    protected ServletOutputStream output = null;
    
    // default size of the in-memory buffer
    private int bufferSize = 50000;
    
    ServletContext sc;
    
    public CantGoBackResponseStream(HttpServletResponse response, ServletContext sc) throws IOException {
        super();
        closed = false;
        this.sc = sc;
        this.response = response;
        this.output = response.getOutputStream();
        bufferedOutput = new ByteArrayOutputStream();
    }
    
    public void close() throws IOException {
        // make up a nonce
        String nonce = Integer.toString((int)(Math.random()*Integer.MAX_VALUE));
        // set the nonce in app scope
        sc.setAttribute("nonce", nonce);
        
        // get the content
        ByteArrayOutputStream baos = (ByteArrayOutputStream) bufferedOutput;
        
        // make a string out of the response
        String pageText = new String(baos.toByteArray());
        
        // use regex to find the links
        Pattern p = Pattern.compile("]*");
        Matcher m = p.matcher(pageText);
        
        String newText = "";
        int offset = 0;
        while (m.find(offset)) {
            // update the text
            newText += pageText.substring(offset, m.start());
            // update the offset
            offset = m.end();
            // get the matching string
            String match = pageText.substring(m.start(), m.end());
            // replace the body tag
            newText += "




Blarg #22: A Filter that auto-encodes session IDs on relative page links.

Posted by jfalkner on March 27, 2006 at 10:43 PM | Permalink | Comments (3)

This is an example Filter that auto-encodes all relative links on a website using the HttpServletResponse.encodeURL() method. It was originally encoded as an example during a Develop Mentor course I taught. It is a nice example of a servlet filter that buffers a response, locates links using a simple regular expression, and replaces links with encoded links.

The code. Remember each filter has three parts: the Filter, ServletResponseWrapper, and ServletOutputStream sub-class.

EncodeSessionInURLFilter.java

This filter does nothing more than wraps the HttpServletResponse in order to buffer text sent out to a client.

package example;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class EncodeSessionInURLFilter implements Filter {
    ServletContext sc = null;
    
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        // check that it is a HTTP request
        if (req instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            
            // nonce encode the normal output
            EncodeSessionInURLResponseWrapper wrappedResponse = new EncodeSessionInURLResponseWrapper(
                    response, sc);
            
            // make sure a session exists
            HttpSession session = request.getSession(true);
            
            chain.doFilter(req, wrappedResponse);
            // finish the respone
            wrappedResponse.finishResponse();
        }
    }
    
    public void init(FilterConfig filterConfig) {
        // reference the context
        sc = filterConfig.getServletContext();
    }
    
    public void destroy() {
        // noop
    }
}

EncodeSessionInURLResponseWrapper.java

This wrapper sends back a custom ServletOutputStream object in order to buffer all text that is being sent to the client.

package example;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class EncodeSessionInURLResponseWrapper extends HttpServletResponseWrapper {
    protected HttpServletResponse origResponse = null;
    protected ServletOutputStream stream = null;
    protected PrintWriter writer = null;
    ServletContext sc;
    
    public EncodeSessionInURLResponseWrapper(HttpServletResponse response, ServletContext sc) {
        super(response);
        this.sc = sc;
        origResponse = response;
    }
    
    public ServletOutputStream createOutputStream() throws IOException {
        return (new EncodeSessionInURLResponseStream(origResponse, sc));
    }
    
    public void finishResponse() {
        try {
            if (writer != null) {
                writer.close();
            } else {
                if (stream != null) {
                    stream.close();
                }
            }
        } catch (IOException e) {}
    }
    
    public void flushBuffer() throws IOException {
        stream.flush();
    }
    
    public ServletOutputStream getOutputStream() throws IOException {
        if (writer != null) {
            throw new IllegalStateException("getWriter() has already been called!");
        }
        
        if (stream == null)
            stream = createOutputStream();
        return (stream);
    }
    
    public PrintWriter getWriter() throws IOException {
        if (writer != null) {
            return (writer);
        }
        
        if (stream != null) {
            throw new IllegalStateException("getOutputStream() has already been called!");
        }
        
        stream = createOutputStream();
        // BUG FIX 2003-12-01 Reuse content's encoding, don't assume UTF-8
        writer = new PrintWriter(new OutputStreamWriter(stream, origResponse.getCharacterEncoding()));
        return (writer);
    }
    
    public void setContentLength(int length) {}
}

EncodeSessionInURLResponseStream.java

This response stream buffers all text that is send to the client and uses a regular expression to locate and replace links with encoded links.

package example;

import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 *
 * @author Jayson Falkner - jayson@jspinsider.com
 */
public class EncodeSessionInURLResponseStream extends ServletOutputStream {
    // abstraction of the output stream used for compression
    protected OutputStream bufferedOutput = null;
    
    // state keeping variable for if close() has been called
    protected boolean closed = false;
    
    // reference to original response
    protected HttpServletResponse response = null;
    
    // reference to the output stream to the client's browser
    protected ServletOutputStream output = null;
    
    // default size of the in-memory buffer
    private int bufferSize = 50000;
    
    ServletContext sc;
    
    public EncodeSessionInURLResponseStream(HttpServletResponse response, ServletContext sc) throws IOException {
        super();
        closed = false;
        this.sc = sc;
        this.response = response;
        this.output = response.getOutputStream();
        bufferedOutput = new ByteArrayOutputStream();
    }
    
    public void close() throws IOException {
        // make up a nonce
        String nonce = Integer.toString((int)(Math.random()*Integer.MAX_VALUE));
        // set the nonce in app scope
        sc.setAttribute("nonce", nonce);
        
        // get the content
        ByteArrayOutputStream baos = (ByteArrayOutputStream) bufferedOutput;
        
        // make a string out of the response
        String pageText = new String(baos.toByteArray());
        
        // use regex to find the links
        Pattern p = Pattern.compile(" href=\"[^\"]*|action=\"[^\"]*");
        Matcher m = p.matcher(pageText);
        
        String newText = "";
        int offset = 0;
        while (m.find(offset)) {
            // update the text
            newText += pageText.substring(offset, m.start());
            // update the offset
            offset = m.end();
            // get the matching string
            String match = pageText.substring(m.start(), m.end());
            // get the URL
            String[] split = match.split("\"");
            String url = split[1];
            // encode the match
            String encoded = response.encodeURL(url);
            
            // add the match to the new text
            newText += split[0]+"\""+encoded;
        }
        // add the final text
        newText += pageText.substring(offset, pageText.length());
        
        
        
        // set appropriate HTTP headers
//        response.setContentLength(compressedBytes.length);
        output.write(newText.getBytes());
        output.flush();
        output.close();
        closed = true;
        
    }
    
    public void flush() throws IOException {
        if (closed) {
            throw new IOException("Cannot flush a closed output stream");
        }
        bufferedOutput.flush();
    }
    
    public void write(int b) throws IOException {
        if (closed) {
            throw new IOException("Cannot write to a closed output stream");
        }
        // write the byte to the temporary output
        bufferedOutput.write((byte) b);
    }
    
    public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }
    
    public void write(byte b[], int off, int len) throws IOException {
        System.out.println("writing...");
        if (closed) {
            throw new IOException("Cannot write to a closed output stream");
        }
        // write the content to the buffer
        bufferedOutput.write(b, off, len);
    }
    
    public boolean closed() {
        return (this.closed);
    }
    
    public void reset() {
        //noop
    }
}


Blarg #21: DevelopMentor JWT links that need to be on-line

Posted by jfalkner on March 20, 2006 at 10:08 AM | Permalink | Comments (2)

For those of you at DevelopMentor's Java Web Tier course, here are the links we used in class. If you weren't at this class and you want to learn about making websites with Java.... Ha, I bet DM loves me now!

Here are those links.

SessionCountListener.java

This class counts the number of current sessions. When one is created, the count goes up. When one is destroyed, the count goes down. This is not a hit tracker. It is a count of "live" users.

package example;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 *A listener class that counts the number of concurent sessions.
 * @author Jayson Falkner - jfalkner@umich.edu
 */
public class SessionCountListener implements HttpSessionListener {
    int count = 0;
    
    /**
     *When a session is destroyed, decrement the counter.
     */
    public void sessionDestroyed(HttpSessionEvent se) {
        // increment the count
        count--;
        // set the attribute
        setAttribute(se);
    }
    
    /**
     *When a session is created, increment the counter.
     */
    public void sessionCreated(HttpSessionEvent se) {
        // decrement the count
        count++;
        // set the attribute
        setAttribute(se);
    }
    
    // helper method to set the attribte in 'application' scope
    private void setAttribute(HttpSessionEvent se) {
        // get the session
        HttpSession hs = se.getSession();
        // get the servlet context
        ServletContext sc = hs.getServletContext();
        // set the attribute on the servlet context
        sc.setAttribute("userCount", Integer.toString(count));
    }
}

And don't forget that you must register this class via web.xml

<web-app>
    <listener>
        <listener-class>example.SessionCountListener</listener-class>
    </listener>
    <!-- rest of your web.xml stuff... -->
</web-app>

Finally, you can show the count from any JSP or serlvet that has access to the ServletContext object. Here is an example JSP.

<html>
    <h1>JSP Page ${userCount}</h1>
</html>




Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds