mcardle     2005/11/08 11:57:03 CET

  Modified files:
    src/org/jahia/esi    GetThread.java 
  Log:
  * creates dummy cache entries which contain the appropriate error message why 
a given object/fragment wasn't retrieved correctly.

  * supports a configurable number of connection retries

  * removes If-conditional HTTP headers from requests
  
  Revision  Changes    Path
  1.6       +152 -48   esi_server/src/org/jahia/esi/GetThread.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/GetThread.java.diff?r1=1.5&r2=1.6&f=h
  
  
  
  Index: GetThread.java
  ===================================================================
  RCS file: /home/cvs/repository/esi_server/src/org/jahia/esi/GetThread.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- GetThread.java    2 Nov 2005 15:46:02 -0000       1.5
  +++ GetThread.java    8 Nov 2005 10:57:03 -0000       1.6
  @@ -1,9 +1,5 @@
   package org.jahia.esi;
   
  -import org.apache.commons.httpclient.HttpClient;
  -import org.apache.commons.httpclient.URI;
  -import org.apache.commons.httpclient.URIException;
  -import org.apache.commons.httpclient.Header;
   import org.apache.commons.httpclient.methods.GetMethod;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  @@ -24,6 +20,8 @@
   import org.jahia.esi.cache.UrlCacheObject;
   import org.jahia.esi.tags.EsiIncludeTag;
   import org.jahia.esi.tags.EsiRemoveTag;
  +import org.jahia.esi.settings.GeneralSettings;
  +import org.jahia.esi.exceptions.TransferFailedException;
   import net.sf.j2ep.ProxyFilter;
   import net.sf.j2ep.responsehandlers.ResponseHandlerBase;
   
  @@ -34,6 +32,9 @@
   import java.util.Date;
   import java.io.InputStream;
   import java.io.ByteArrayOutputStream;
  +import java.io.IOException;
  +
  +import org.apache.commons.httpclient.*;
   
   /**
    * Created by IntelliJ IDEA.
  @@ -44,19 +45,21 @@
    */
   public class GetThread extends Thread {
   
  +    private static final int SC_NULL = -1;
  +
       private static final transient Log log = 
LogFactory.getLog(GetThread.class);
   
       private HttpClient httpClient;
       private GetMethod methodToServer;
       private int id = (int)(Math.random()*100.0);
       private  ResponseHandlerBase responseHandlerBase;
  -
       private HttpServletResponse clientResponse;
       private HttpServletRequest clientRequest;
       private String urlKey;
       private UrlCacheObject urlObj;
       private String urlToServer;
       private String clientRequestUrl;
  +    private boolean success = true;
   
       long expirationDateInSecs = (new Date()).getTime();
       long expirationInSecs = EsiConst.DEFAULT_EXPIRATION;
  @@ -106,7 +109,13 @@
           return urlToServer;
       }
   
  +    public boolean isSuccess() {
  +        return success;
  +    }
   
  +    public void setSuccess(boolean success) {
  +        this.success = success;
  +    }
   
       /**
        * Executes the GetMethod and prints some satus information.
  @@ -120,7 +129,19 @@
           //******************** FETCH ************************
           byte[] bytes = null;
   
  -        bytes = retrieveBytesFromServer(bytes);
  +        try {
  +            bytes = retrieveBytesFromServer();
  +        }
  +        catch (TransferFailedException e) {
  +            log.error(id + " - error: " + e);
  +            setSuccess(false);
  +            String urlKey = 
CacheAdminstrator.getInstance().generateEntryKey("GET" , clientRequestUrl );
  +            StringBuffer errorMsg = new StringBuffer("<b>ESI ERROR: Could 
not fetch the object (urlKey:[").append(urlKey).append("]) due to error: ");
  +            errorMsg.append(e.toString()).append(" - Http Status Code 
").append(this.methodToServer.getStatusLine().toString())
  +                    .append(" - for client request: 
").append(clientRequestUrl).append("</b>");
  +            fragmentCache.addUnfectched ( urlKey  , this.methodToServer , 
errorMsg.toString() , this.clientRequestUrl);
  +            return;
  +        }
   
           //******************** CHECK CONTENT TYPE ************************
           //***********************************************
  @@ -243,7 +264,6 @@
                   GetThread thread = (GetThread) threadEnum.nextElement();
                   try {
                       thread.join();
  -
                   } catch (InterruptedException ex) {
                       log.error(id + "THREAD WAS INTERRUPTED 
!!!!!!!!!!!!!!!!!!!!");
                       //TODO: deal with error
  @@ -326,60 +346,115 @@
   
           } catch (Exception e) {
               log.error(id + " - Main Thread ERROR : " + e);
  +            e.printStackTrace();
           }
   
           yield();
   
       }
   
  -    private byte[] retrieveBytesFromServer(byte[] bytes) {
  +
  +
  +    private byte[] retrieveBytesFromServer()
  +            throws TransferFailedException {
  +
  +        byte[] bytes = null;
  +
  +        int statusCode = SC_NULL;
  +
  +        int attempt = 0;
  +
           try {
  -            //TODO: replace by STREAM version
  +            // We will retry up to NumberOfAttempts times.
  +            while ( statusCode == SC_NULL && attempt < 
GeneralSettings.getInstance().getNumberOfAttempts() )
  +            {
  +                try
  +                {
   
  -            
//ResponseHandlerBase.getRidOfDodgyRequestHeaders(methodToServer);
  +                    getRidOfConditionalHttpHeaders();
   
  -            log.debug(id + " - about to get something from " + urlToServer );
  -            // execute the methodToServer
  -            httpClient.executeMethod(methodToServer);
  -
  -            // TODO: CHECK CONTENT TYPE should go here so that if the 
content is binary and too big,
  -            // then we just do a passthrough. If it's just binary and small 
enough to cache
  -            // we do a passthroughAndCache.
  -
  -            log.debug(id + " - get executed");
  -            // get the response body as an array of bytes
  -
  -            InputStream streamFromServer = 
methodToServer.getResponseBodyAsStream();
  -            ByteArrayOutputStream byteStream = new 
ByteArrayOutputStream(1000);
  -
  -            if (streamFromServer != null) {
  -                byte[] buffer = new 
byte[1024];//CHANGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  -                int read = streamFromServer.read(buffer);
  -                while (read > 0) {
  -                    byteStream.write(buffer, 0, read);
  -                    read = streamFromServer.read(buffer);
  -                }
  -                streamFromServer.close();
  -            }
  +                    log.debug(id + " - about to get something from " + 
urlToServer );
  +                    // execute the methodToServer
  +                    statusCode = httpClient.executeMethod(methodToServer);
  +
  +                    // TODO: CHECK CONTENT TYPE should go here so that if 
the content is binary and too big,
  +                    // then we just do a passthrough. If it's just binary 
and small enough to cache
  +                    // we do a passthroughAndCache.
  +
  +                    // get the response body as an array of bytes
  +                    InputStream streamFromServer = 
methodToServer.getResponseBodyAsStream();
  +                    ByteArrayOutputStream byteStream = new 
ByteArrayOutputStream(1000);
  +
  +                    if (streamFromServer != null) {
  +                        byte[] buffer = new byte[1024]; //TODO: check best 
optimal value
  +                        int read = streamFromServer.read(buffer);
  +                        while (read > 0) {
  +                            byteStream.write(buffer, 0, read);
  +                            read = streamFromServer.read(buffer);
  +                        }
  +                        streamFromServer.close();
  +                    }
  +
  +                    byteStream.flush();
  +                    byteStream.close();
  +
  +                    bytes = byteStream.toByteArray();
  +
  +                    if (bytes==null)  {
  +                        log.error(id + " -  bytes is NULL. No content 
returned. bytes["+bytes+"]");
  +                        log.error(id + " -  therefore setting it to some 
random one byte value. ++++++++++++++++++++++++++++++");
  +                        bytes[0] = 0;
  +                    }
   
  -            byteStream.flush();
  -            byteStream.close();
  +                    log.debug(id + " - " + bytes.length + " bytes read");
   
  -            bytes = byteStream.toByteArray();
  +                    //TODO: NEED TO CHECK RESPONSE ESI HEADERS
  +                }
  +                catch (HttpException e )
  +                //catch ( HttpRecoverableException e )
  +                {
  +                    attempt++;
  +                }
  +                catch ( IOException e )
  +                {
  +                    log.error(id + " - error: " + e);
  +                    throw new TransferFailedException( e.getMessage(), e );
  +                }
   
  -            if (bytes==null)  {
  -                log.error(id + " -  bytes is NULL. No content returned. 
bytes["+bytes+"]");
  -                log.error(id + " -  therefore setting it to some random one 
byte value. ++++++++++++++++++++++++++++++");
  -                bytes[0] = 0;
               }
   
  -            log.debug(id + " - " + bytes.length + " bytes read");
  +            // Check that we didn't run out of retries.
  +            switch ( statusCode )
  +            {
  +                case HttpStatus.SC_OK:
  +                    break;
   
  -            //TODO: NEED TO CHECK RESPONSE ESI HEADERS
  +                case HttpStatus.SC_CREATED:
  +                    break;
   
  -        } catch (Exception e) {
  -            log.error(id + " - error: " + e);
  -        } finally {
  +                case SC_NULL:
  +                    throw new TransferFailedException(
  +                            "Failed to transfer file: " + urlToServer + " 
after " + attempt + " attempts" );
  +                case HttpStatus.SC_FORBIDDEN:
  +                    throw new TransferFailedException( "Access denided to: " 
+ urlToServer );
  +
  +                case HttpStatus.SC_UNAUTHORIZED:
  +                    throw new TransferFailedException( "Not authorized." );
  +
  +                case HttpStatus.SC_NOT_FOUND:
  +                    throw new TransferFailedException( "File: " + 
urlToServer + " does not exist" );
  +
  +                case HttpStatus.SC_NOT_MODIFIED:
  +                    log.error( "304 on File: " + urlToServer + " which is 
IMPOSSIBLE ");
  +                    throw new TransferFailedException( "304 on File: " + 
urlToServer + " which is IMPOSSIBLE " );
  +                //add more entries here
  +                default :
  +                    throw new TransferFailedException(
  +                            "Failed to transfer file: " + urlToServer + ". 
Return code is: " + statusCode );
  +            }
  +
  +        }
  +        finally {
               // always release the connection after we're done
               methodToServer.releaseConnection();
               log.debug(id + " - connection released");
  @@ -389,9 +464,38 @@
   
               parseEsiResponseHeaders();
           }
  +
           return bytes;
       }
   
  +    /**
  +     * We have to remove the client's If-conditional HTTP request headers 
when fetching content which is not
  +     * in the cache, otherwise we'll just get a 304 back and we won't have 
any entries in the cache.
  +     */
  +    private void getRidOfConditionalHttpHeaders() {
  +        String ifnonematch = "";
  +        try {
  +            if (methodToServer.getRequestHeader("if-none-match").getValue() 
!=null) {
  +                log.debug("removed if-none-match 
["+methodToServer.getRequestHeader("if-none-match")+"] ");
  +                methodToServer.removeRequestHeader("if-none-match");
  +            }
  +
  +        } catch (Exception ex) {
  +            //log.debug(" no if-none-match 
["+methodToServer.getResponseHeader("if-none-match")+"]  ex: "+ex);
  +        }
  +        String ifmodifiedsince = "";
  +        try {
  +            if 
(methodToServer.getRequestHeader("if-modified-since").getValue() !=null) {
  +                log.debug("removed if-modified-since 
["+methodToServer.getRequestHeader("if-modified-since")+"] ");
  +                methodToServer.removeRequestHeader("if-modified-since");
  +            }
  +
  +        } catch (Exception ex) {
  +            //log.debug(" no if-modified-since 
["+methodToServer.getResponseHeader("if-modified-since")+"]  ex: "+ex);
  +        }
  +
  +    }
  +
       private static OrFilter EsiTagFilter = new OrFilter(
               new NodeClassFilter (EsiIncludeTag.class),//new TagNameFilter 
("esi:include")),
               new NodeClassFilter (EsiRemoveTag.class)
  @@ -405,12 +509,12 @@
       }
   
       private void removeAllAttributes(TagNode tag) {
  -         Vector v = tag.getAttributesEx();
  +        Vector v = tag.getAttributesEx();
   
           Enumeration enumAtt = v.elements();
           while (enumAtt.hasMoreElements()) {
  -           Attribute att = (Attribute) enumAtt.nextElement();
  -           tag.removeAttribute(att.getName());
  +            Attribute att = (Attribute) enumAtt.nextElement();
  +            tag.removeAttribute(att.getName());
           }
       }
   
  

Reply via email to