Edit D:\app\Administrator\product\11.2.0\dbhome_1\owb\lib\int\HTTPClient\IdempotentSequence.java
/* * @(#)IdempotentSequence.java 0.3-3 06/05/2001 * * This file is part of the HTTPClient package * Copyright (C) 1996-2001 Ronald Tschal? * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA * * For questions, suggestions, bug-reports, enhancement-requests etc. * I may be contacted at: * * ronald@innovation.ch * * The HTTPClient's home page is located at: * * http://www.innovation.ch/java/HTTPClient/ * */ package HTTPClient; import java.util.Hashtable; import java.util.Enumeration; /** * <P>This class checks whether a sequence of requests is idempotent. This * is used to determine which requests may be automatically retried. This * class also serves as a central place to record which methods have side * effects and which methods are idempotent. * * <P>Note: unknown methods (i.e. a method which is not HEAD, GET, POST, PUT, * DELETE, OPTIONS, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, or * UNLOCK) are treated conservatively, meaning they are assumed to have side * effects and are not idempotent. * * <P>Usage: * <PRE> * IdempotentSequence seq = new IdempotentSequence(); * seq.add(r1); * ... * if (seq.isIdempotent(r1)) ... * ... * </PRE> * * @version 0.3-3 06/05/2001 * @author Ronald Tschal? */ class IdempotentSequence { /** method number definitions */ private static final int UNKNOWN = 0, HEAD = 1, GET = 2, POST = 3, PUT = 4, DELETE = 5, OPTIONS = 6, TRACE = 7, // DAV methods PROPFIND = 8, PROPPATCH = 9, MKCOL = 10, COPY = 11, MOVE = 12, LOCK = 13, UNLOCK = 14; /** these are the history of previous requests */ private int[] m_history; private String[] r_history; private int m_len, r_len; /** trigger analysis of threads */ private boolean analysis_done = false; private Hashtable threads = new Hashtable(); // Constructors /** * Start a new sequence of requests. */ public IdempotentSequence() { m_history = new int[10]; r_history = new String[10]; m_len = 0; r_len = 0; } // Methods /** * Add the request to the end of the list of requests. This is used * to build the complete sequence of requests before determining * whether the sequence is idempotent. * * @param req the next request */ public void add(Request req) { if (m_len >= m_history.length) m_history = Util.resizeArray(m_history, m_history.length+10); m_history[m_len++] = methodNum(req.getMethod()); if (r_len >= r_history.length) r_history = Util.resizeArray(r_history, r_history.length+10); r_history[r_len++] = req.getRequestURI(); } /** * Is this request part of an idempotent sequence? This method <em>must * not</em> be called before all requests have been added to this * sequence; similarly, <var>add()</var> <em>must not</em> be called * after this method was invoked. * * <P>We split up the sequence of requests into individual sub-sequences, * or threads, with all requests in a thread having the same request-URI * and no two threads having the same request-URI. Each thread is then * marked as idempotent or not according to the following rules: * * <OL> * <LI>If any method is UNKNOWN then the thread is not idempotent; * <LI>else, if no method has side effects then the thread is idempotent; * <LI>else, if the first method has side effects and is complete then * the thread is idempotent; * <LI>else, if the first method has side effects, is not complete, * and no other method has side effects then the thread is idempotent; * <LI>else the thread is not idempotent. * </OL> * * <P>The major assumption here is that the side effects of any method * only apply to resource specified. E.g. a <tt>"PUT /barbara.html"</tt> * will only affect the resource "/barbara.html" and nothing else. * This assumption is violated by POST of course; however, POSTs are * not pipelined and will therefore never show up here. * * @param req the request */ public boolean isIdempotent(Request req) { if (!analysis_done) do_analysis(); return ((Boolean) threads.get(req.getRequestURI())).booleanValue(); } private static final Object INDET = new Object(); private void do_analysis() { for (int idx=0; idx<r_len; idx++) { Object t_state = threads.get(r_history[idx]); if (m_history[idx] == UNKNOWN) threads.put(r_history[idx], Boolean.FALSE); else if (t_state == null) // new thread { if (methodHasSideEffects(m_history[idx])) { if (methodIsComplete(m_history[idx])) // is idempotent threads.put(r_history[idx], Boolean.TRUE); else threads.put(r_history[idx], Boolean.FALSE); } else // indeterminate threads.put(r_history[idx], INDET); } else // update thread { if (t_state == INDET && methodHasSideEffects(m_history[idx])) threads.put(r_history[idx], Boolean.FALSE); } } // any thread still indeterminate must be idempotent Enumeration te = threads.keys(); while (te.hasMoreElements()) { String res = (String) te.nextElement(); if (threads.get(res) == INDET) threads.put(res, Boolean.TRUE); } } /** * A method is idempotent if the side effects of N identical * requests is the same as for a single request (Section 9.1.2 * of RFC-????). * * @return true if method is idempotent */ public static boolean methodIsIdempotent(String method) { return methodIsIdempotent(methodNum(method)); } private static boolean methodIsIdempotent(int method) { switch (method) { case HEAD: case GET: case PUT: case DELETE: case OPTIONS: case TRACE: case PROPFIND: case PROPPATCH: case COPY: case MOVE: return true; case UNKNOWN: case POST: case MKCOL: case LOCK: case UNLOCK: default: return false; } } /** * A method is complete if any side effects of the request affect * the complete resource. For example, a PUT is complete but a * PUT with byte-ranges wouldn't be. In essence, if a request uses * a method which has side effects and is complete then the state * of the resource after the request is independent of the state of * the resource before the request. * * @return true if method is complete */ public static boolean methodIsComplete(String method) { return methodIsComplete(methodNum(method)); } private static boolean methodIsComplete(int method) { switch (method) { case HEAD: case GET: case PUT: case DELETE: case OPTIONS: case TRACE: case PROPFIND: case COPY: case MOVE: case LOCK: case UNLOCK: return true; case UNKNOWN: case POST: case PROPPATCH: case MKCOL: default: return false; } } public static boolean methodHasSideEffects(String method) { return methodHasSideEffects(methodNum(method)); } private static boolean methodHasSideEffects(int method) { switch (method) { case HEAD: case GET: case OPTIONS: case TRACE: case PROPFIND: case LOCK: case UNLOCK: return false; case UNKNOWN: case POST: case PUT: case DELETE: case PROPPATCH: case MKCOL: case COPY: case MOVE: default: return true; } } private static int methodNum(String method) { if (method.equals("GET")) return GET; if (method.equals("POST")) return POST; if (method.equals("HEAD")) return HEAD; if (method.equals("PUT")) return PUT; if (method.equals("DELETE")) return DELETE; if (method.equals("OPTIONS")) return OPTIONS; if (method.equals("TRACE")) return TRACE; if (method.equals("PROPFIND")) return PROPFIND; if (method.equals("PROPPATCH")) return PROPPATCH; if (method.equals("MKCOL")) return MKCOL; if (method.equals("COPY")) return COPY; if (method.equals("MOVE")) return MOVE; if (method.equals("LOCK")) return LOCK; if (method.equals("UNLOCK")) return UNLOCK; return UNKNOWN; } /** * Test code. */ public static void main(String args[]) { IdempotentSequence seq = new IdempotentSequence(); seq.add(new Request(null, "GET", "/b1", null, null, null, false)); seq.add(new Request(null, "PUT", "/b2", null, null, null, false)); seq.add(new Request(null, "GET", "/b1", null, null, null, false)); seq.add(new Request(null, "PUT", "/b3", null, null, null, false)); seq.add(new Request(null, "GET", "/b2", null, null, null, false)); seq.add(new Request(null, "POST", "/b8", null, null, null, false)); seq.add(new Request(null, "PUT", "/b3", null, null, null, false)); seq.add(new Request(null, "GET", "/b1", null, null, null, false)); seq.add(new Request(null, "TRACE", "/b4", null, null, null, false)); seq.add(new Request(null, "GET", "/b9", null, null, null, false)); seq.add(new Request(null, "LINK", "/b4", null, null, null, false)); seq.add(new Request(null, "GET", "/b4", null, null, null, false)); seq.add(new Request(null, "PUT", "/b5", null, null, null, false)); seq.add(new Request(null, "HEAD", "/b5", null, null, null, false)); seq.add(new Request(null, "PUT", "/b5", null, null, null, false)); seq.add(new Request(null, "POST", "/b9", null, null, null, false)); seq.add(new Request(null, "GET", "/b6", null, null, null, false)); seq.add(new Request(null, "DELETE", "/b6", null, null, null, false)); seq.add(new Request(null, "HEAD", "/b6", null, null, null, false)); seq.add(new Request(null, "OPTIONS", "/b7", null, null, null, false)); seq.add(new Request(null, "TRACE", "/b7", null, null, null, false)); seq.add(new Request(null, "GET", "/b7", null, null, null, false)); seq.add(new Request(null, "PUT", "/b7", null, null, null, false)); if (!seq.isIdempotent(new Request(null, null, "/b1", null, null, null, false))) System.err.println("Sequence b1 failed"); if (!seq.isIdempotent(new Request(null, null, "/b2", null, null, null, false))) System.err.println("Sequence b2 failed"); if (!seq.isIdempotent(new Request(null, null, "/b3", null, null, null, false))) System.err.println("Sequence b3 failed"); if (seq.isIdempotent(new Request(null, null, "/b4", null, null, null, false))) System.err.println("Sequence b4 failed"); if (!seq.isIdempotent(new Request(null, null, "/b5", null, null, null, false))) System.err.println("Sequence b5 failed"); if (seq.isIdempotent(new Request(null, null, "/b6", null, null, null, false))) System.err.println("Sequence b6 failed"); if (seq.isIdempotent(new Request(null, null, "/b7", null, null, null, false))) System.err.println("Sequence b7 failed"); if (seq.isIdempotent(new Request(null, null, "/b8", null, null, null, false))) System.err.println("Sequence b8 failed"); if (seq.isIdempotent(new Request(null, null, "/b9", null, null, null, false))) System.err.println("Sequence b9 failed"); System.out.println("Tests finished"); } }
Ms-Dos/Windows
Unix
Write backup
jsp File Browser version 1.2 by
www.vonloesch.de