jericho     2003/01/20 20:02:07

  Modified:    src/util/org/apache/util URI.java
  Log:
  - Add setXxxPath methods to set path correctly
    Reported by 'Armando_Anton <armando.anton at newknow.com>'
  
  - Force API programmer to inform the charset changed with exception to users
  
  Revision  Changes    Path
  1.25      +224 -25   jakarta-slide/src/util/org/apache/util/URI.java
  
  Index: URI.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/util/org/apache/util/URI.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- URI.java  5 Jan 2003 07:56:09 -0000       1.24
  +++ URI.java  21 Jan 2003 04:02:07 -0000      1.25
  @@ -891,6 +891,7 @@
       protected static final BitSet opaque_part = new BitSet(256);
       // Static initializer for opaque_part
       static {
  +        // it's generous. because first character must not include a slash
           opaque_part.or(uric_no_slash);
           opaque_part.or(uric);
       }
  @@ -1927,7 +1928,11 @@
                       _path = null;
                   }
               }
  -            setPath(tmp.substring(from, next));
  +            if (escaped) {
  +                setRawPath(tmp.substring(from, next).toCharArray());
  +            } else {
  +                setPath(tmp.substring(from, next));
  +            }
               at = next;
           }
   
  @@ -2376,10 +2381,37 @@
        * An individual URI scheme may require a single charset, define a default
        * charset, or provide a way to indicate the charset used.
        *
  +     * <p>
  +     * Always all the time, the setter method is always succeeded and throws
  +     * <code>CharsetChanged</code> exception.
  +     *
  +     * So API programmer must follow the following way:
  +     * <code>
  +     *  import org.apache.util.URI$CharsetChanged;
  +     *      .
  +     *      .
  +     *      .
  +     *  try {
  +     *      URI.setProtocolCharset("UTF-8");
  +     *  } catch (CharsetChanged cc) {
  +     *      if (cc.getReasonCode() == CharsetChanged.PROTOCOL_CHARSET) {
  +     *      // let user know the default protocol charset changed
  +     *      } else {
  +     *      // let user know the default document charset changed
  +     *      }
  +     *  }
  +     *  </code>
  +     *
  +     * The API programmer is responsible to set the correct charset.
  +     * And each application should remember its own charset to support.
  +     *
        * @param charset the default charset for each protocol
  +     * @throws CharsetChanged charset changed
        */
       public static void setProtocolCharset(String charset) {
           _protocolCharset = charset;
  +        throw new CharsetChanged(CharsetChanged.PROTOCOL_CHARSET,
  +                "the default protocol charset changed");
       }
   
   
  @@ -2410,11 +2442,38 @@
        * display of these character sets, the protocol charset could be simply
        * used again. Because it's not yet implemented that the insertion of BIDI
        * control characters at different points during composition is extracted.
  +     * <p>
  +     *
  +     * Always all the time, the setter method is always succeeded and throws
  +     * <code>CharsetChanged</code> exception.
  +     *
  +     * So API programmer must follow the following way:
  +     * <code>
  +     *  import org.apache.util.URI$CharsetChanged;
  +     *      .
  +     *      .
  +     *      .
  +     *  try {
  +     *      URI.setDocumentCharset("EUC-KR");
  +     *  } catch (CharsetChanged cc) {
  +     *      if (cc.getReasonCode() == CharsetChanged.DOCUMENT_CHARSET) {
  +     *      // let user know the default document charset changed
  +     *      } else {
  +     *      // let user know the default protocol charset changed
  +     *      }
  +     *  }
  +     *  </code>
  +     *
  +     * The API programmer is responsible to set the correct charset.
  +     * And each application should remember its own charset to support.
        *
        * @param charset the default charset for the document
  +     * @throws CharsetChanged charset changed
        */
       public static void setDocumentCharset(String charset) {
           _documentCharset = charset;
  +        throw new CharsetChanged(CharsetChanged.DOCUMENT_CHARSET,
  +                "the default document charset changed");
       }
   
   
  @@ -2600,21 +2659,90 @@
       // --------------------------------------------------------------- The path
   
       /**
  -     * Set the path.   The method couldn't be used by API programmers.
  +     * Set the raw-escaped path.
  +     *
  +     * @param escapedPath the path character sequence
  +     * @exception URIException encoding error or not proper for initial instance
  +     * @see #encode
  +     */
  +    public void setRawPath(char[] escapedPath) throws URIException {
  +        if (escapedPath == null || escapedPath.length == 0) {
  +            _path = _opaque = escapedPath;
  +            setURI();
  +            return;
  +        }
  +        // remove the fragment identifier
  +        escapedPath = removeFragmentIdentifier(escapedPath);
  +        if (_is_net_path || _is_abs_path) {
  +            if (escapedPath[0] != '/')
  +                throw new URIException(URIException.PARSING,
  +                        "not absolute path");
  +            if (!validate(escapedPath, abs_path))
  +                throw new URIException(URIException.ESCAPING,
  +                        "escaped absolute path not valid");
  +            _path = escapedPath;
  +        } else if (_is_rel_path) {
  +            int at = indexFirstOf(escapedPath, '/');
  +            if (at == 0)
  +                throw new URIException(URIException.PARSING, "incorrect path");
  +            if (at > 0 && !validate(escapedPath, 0, at, rel_segment) ||
  +                    at < 0 && !validate(escapedPath, 0, -1, abs_path))
  +                throw new URIException(URIException.ESCAPING,
  +                        "escaped relative path not valid");
  +            _path = escapedPath;
  +        } else if (_is_opaque_part) {
  +            if (!uric_no_slash.get(escapedPath[0]) &&
  +                    !validate(escapedPath, 1, -1, uric))
  +                throw new URIException(URIException.ESCAPING,
  +                    "escaped opaque part not valid");
  +            _opaque = escapedPath;
  +        } else {
  +            throw new URIException(URIException.PARSING, "incorrect path");
  +        }
  +        setURI();
  +    }
  +
  +
  +    /**
  +     * Set the escaped path.
  +     *
  +     * @param escapedPath the escaped path string
  +     * @exception URIException encoding error or not proper for initial instance
  +     * @see #encode
  +     */
  +    public void setEscapedPath(String escapedPath) throws URIException {
  +        if (escapedPath == null) {
  +            _path = _opaque = null;
  +            setURI();
  +            return;
  +        }
  +        setRawPath(escapedPath.toCharArray());
  +    }
  +
  +
  +    /**
  +     * Set the path.
        *
        * @param path the path string
        * @exception URIException set incorrectly or fragment only
        * @see #encode
        */
  -    protected void setPath(String path) throws URIException {
  +    public void setPath(String path) throws URIException {
   
  -        // set path
  +        if (path == null || path.length() == 0) {
  +            _path = _opaque = (path == null) ? null : path.toCharArray();
  +            setURI();
  +            return;
  +        }
           if (_is_net_path || _is_abs_path) {
               _path = encode(path, allowed_abs_path);
           } else if (_is_rel_path) {
               StringBuffer buff = new StringBuffer(path.length());
               int at = path.indexOf('/');
  -            if (at > 0) {  // never 0
  +            if (at == 0) // never 0
  +                throw new URIException(URIException.PARSING,
  +                        "incorrect relative path");
  +            if (at > 0) {
                   buff.append(encode(path.substring(0, at), allowed_rel_path));
                   buff.append(encode(path.substring(at), allowed_abs_path));
               } else {
  @@ -2622,10 +2750,14 @@
               }
               _path = buff.toString().toCharArray();
           } else if (_is_opaque_part) {
  -            _opaque = encode(path, allowed_opaque_part);
  +            StringBuffer buf = new StringBuffer();
  +            buf.insert(0, encode(path.substring(0, 1), uric_no_slash));
  +            buf.insert(1, encode(path.substring(1), uric));
  +            _opaque = buf.toString().toCharArray();
           } else {
               throw new URIException(URIException.PARSING, "incorrect path");
           }
  +        setURI();
       }
   
   
  @@ -2911,8 +3043,8 @@
        * @exception URIException escaped query not valid
        */
       public void setRawQuery(char[] escapedQuery) throws URIException {
  -        if (escapedQuery == null) {
  -            _query = null;
  +        if (escapedQuery == null || escapedQuery.length == 0) {
  +            _query = escapedQuery;
               setURI();
               return;
           }
  @@ -2960,8 +3092,8 @@
        * @see #encode
        */
       public void setQuery(String query) throws URIException {
  -        if (query == null) {
  -            _query = null;
  +        if (query == null || query.length() == 0) {
  +            _query = (query == null) ? null : query.toCharArray();
               setURI();
               return;
           }
  @@ -3010,8 +3142,8 @@
        * @exception URIException escaped fragment not valid
        */
       public void setRawFragment(char[] escapedFragment) throws URIException {
  -        if (escapedFragment == null) {
  -            _fragment = null;
  +        if (escapedFragment == null || escapedFragment.length == 0) {
  +            _fragment = escapedFragment;
               return;
           }
           if (!validate(escapedFragment, fragment))
  @@ -3033,12 +3165,7 @@
               _fragment = null;
               return;
           }
  -        char[] fragmentSequence = escapedFragment.toCharArray();
  -        if (!validate(fragmentSequence, fragment))
  -            throw new URIException(URIException.ESCAPING,
  -                    "escaped fragment not valid");
  -        _fragment = fragmentSequence;
  -        setURI();
  +        setRawFragment(escapedFragment.toCharArray());
       }
   
   
  @@ -3049,8 +3176,8 @@
        * @exception URIException
        */
       public void setFragment(String fragment) throws URIException {
  -        if (fragment == null) {
  -            _fragment = null;
  +        if (fragment == null || fragment.length() == 0) {
  +            _fragment = (fragment == null) ? null : fragment.toCharArray();
               return;
           }
           _fragment = encode(fragment, allowed_fragment);
  @@ -3447,7 +3574,7 @@
        * password to access manually.  Probably it will be supported in the each
        * subclass, however, not a whole URI-reference expression.
        *
  -     * @return the URI string
  +     * @return the escaped URI string
        * @see #clone()
        */
       public String toString() {
  @@ -3456,6 +3583,78 @@
   
   
       // ------------------------------------------------------------ Inner class
  +
  +    /** 
  +     * The charset-changed normal operation to represent to be required to
  +     * alert to user the fact the default charset is changed.
  +     */
  +    public static class CharsetChanged extends RuntimeException {
  +
  +        // ------------------------------------------------------- constructors
  +
  +        /**
  +         * The constructor with a reason string and its code arguments.
  +         *
  +         * @param reasonCode the reason code
  +         * @param reason the reason
  +         */
  +        public CharsetChanged(int reasonCode, String reason) {
  +            super(reason);
  +            this.reason = reason;
  +            this.reasonCode = reasonCode;
  +        }
  +
  +        // ---------------------------------------------------------- constants
  +
  +        /**
  +         * No specified reason code.
  +         */
  +        public static final int UNKNOWN = 0;
  +
  +        /**
  +         * Protocol charset changed.
  +         */
  +        public static final int PROTOCOL_CHARSET = 1;
  +
  +        /**
  +         * Document charset changed.
  +         */
  +        public static final int DOCUMENT_CHARSET = 2;
  +
  +        // ------------------------------------------------- instance variables
  +
  +        /**
  +         * The reason code.
  +         */
  +        private int reasonCode;
  +
  +        /**
  +         * The reason message.
  +         */
  +        private String reason;
  +
  +        // ------------------------------------------------------------ methods
  +
  +        /**
  +         * Get the reason code.
  +         *
  +         * @return the reason code
  +         */
  +        public int getReasonCode() {
  +            return reasonCode;
  +        }
  +
  +        /**
  +         * Get the reason message.
  +         *
  +         * @return the reason message
  +         */
  +        public String getReason() {
  +            return reason;
  +        }
  +
  +    }
  +
   
       /** 
        * A mapping to determine the (somewhat arbitrarily) preferred charset for 
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to