High all
A little sum up 
I made somme changes to Slide code to avoid Uri's leak of memory (I have used 
JProfiler  to monitor the heap and see several Uri(s) staying in heap using 
SLIDE) I suggested to make a change in ExtendedKeystore to use the "Uri" 
instead of Object for the removeObjectFromCache(Uri key ) method 
Does anybody tried to compile with this new type of parameter (I compiled 
without error) ?

Antoine Levy-Lambert suggested me that this modification doesn't change any 
thing because the toString method call is the good one in any  case , ... that 
rigth ! but I think my code is better because it limit the type Object at 
compiler time and throw an Exception at run time if the key sent is not an Uri

Nevertheless I propose to make a change to the Uri Class  these change will 
appears as "cosmetic" but I propose it anyway
In Uri class the method equals refer to the toString() method this is not 
correct from my point of vue I suggest :
  /**
     * Tests equivalence of two Uris.
     *
     * @param obj Object to test
     * @return boolean
     */
    public boolean equals(Object obj) {
        if ((obj != null) && (obj instanceof Uri)) {
           //    return (uri.equals(obj.toString()));
            return uri.equals(((Uri)obj).uri);
        } else {
            return false;
        }
    }
        
I attach Uri class code as it is today in my project I comment the Uri instance 
counter (used in constructor , clone and finalyse ) this simple code show the 
number of instances of Uri when SLIDE run
Futhermore I made some changes in the class UriPath (not so "cosmetic")
  /**
     * Equals .
     * @param  o  Object to 
     */
    public boolean equals(Object o) {
        boolean result = false;
        if ((o!= null) && (o instanceof UriPath)) {
            result = java.util.Arrays.equals(this.tokens,((UriPath)o).tokens);  
   <-- my code 
           /*    UriPath other = (UriPath)o;
            if (other.tokens.length == this.tokens.length) {
                result = true;
                for (int i = 0; i < this.tokens.length; i++) {
                    if (!other.tokens[i].equals(this.tokens[i])) {
                        result = false;
                        break;
                    }
                }
            }*/
        }
        return result;
    }
    
    /**
     * hashcode use  all tokens to compute hashcode 
     */
    public int hashCode() {
        if (tokens.length > 0) {
           // return tokens[tokens.length - 1].hashCode();
          return this.toString().hashCode();
        }
        else {
            return 0; 
        }
    }

Method equals : I change the token arrays comparison made in the loop and I use 
the java.util.Arrays class (this is cosmetic)
Method hashCode : as written today this method is not in accordance with equals 
method because only the length -1 token is used to compute the hash 
I suggest to use the toString().hashcode to use all tokens 
Bests regards 
B DOREL
/*
 * $Header: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/Uri.java,v 1.22 
2004/11/24 11:35:26 ozeigermann Exp $
 * $Revision: 1.22 $
 * $Date: 2004/11/24 11:35:26 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 *   BD/EADS, Le 19/01/07 
 *   Correction FFT 2006/EADS/1038 Fuites memoire sur le serveur tomcat (memory 
 *   leaks) 
 *   Fix method equals compare underLyings uri Strings
 *
 */

package org.apache.slide.common;

import java.io.IOException;
import java.util.Enumeration;

import org.apache.slide.store.Store;

/**
 * This class manages the unique identifier of an object which is
 * manipulated by Slide.
 *
 * @version $Revision: 1.22 $
 */
public class Uri implements Cloneable, java.io.Serializable {
    
    
    // ----------------------------------------------------------- Constructors
    
  // Apply a bebug cook book to compute the count of instances (using
  // constructor and finalyse method
 /* DEBUG 
  private static int _countUp = 0;
  private static int _countDown = 0;
  private int instance;
  private int origine; */
    
  private Uri(){
 /* DEBUG
    _countUp++;
    origine = 1;
    instance = _countUp; */
  } 
  /**
   * just for DEBUG display URI instances count
   */   
  /*   public void finalize() throws Throwable {
       _countDown++;
       System.out.println( instance + " instance " +" Uri nb Instances " +
                          (_countUp - _countDown) +
                          " finalize " +
                          this.uri + " " + origine 
                          );
       super.finalize();
     }*/
    /**
     * Constructor.
     *
     * @param namespace Namespace associated with this Uri
     * @param uri Uri
     * 
     * @deprecated use signature with SlideToken instead
     */
    public Uri(Namespace namespace, String uri) {
        this(null, namespace, uri);
    }
    
    
    /**
     * Constructor.
     *
     * @param token Slide token
     * @param namespace Namespace associated with this Uri
     * @param uri Uri
     */
    public Uri(SlideToken token, Namespace namespace, String uri) {
        this();
        this.token = token;
        this.namespace = namespace;
        this.uri = uri;
        parseUri(uri);
    }
 
    
    // ----------------------------------------------------- Instance Variables
    
    
    /**
     * Uri's namespace.
     */
    protected transient Namespace namespace;
    
    
    /**
     * uri MUST be unique.
     */
    protected transient String uri;
    
    
    /**
     * Scopes to which this Uri belongs.
     */
    protected transient ScopeTokenizer scopes;
    
    
    /**
     * FIXME : Is that still used ?
     */
    protected transient Scope scope;
    
    
    /**
     * Associated Store instance.
     */
    protected transient Store store;
    
    
    /** return (uri.equals(obj.toString()));
     * Associated SlideToken.
     */
    protected transient SlideToken token;
    
    
    // ------------------------------------------------------------- Properties
    
    
    /**
     * Uri mutator.
     *
     * @param uri New uri
     */
    public void setUri(String uri) {
        parseUri(uri);
    }
    
    
    /**
     * Method getRoot
     *
     * @param    uri                 an Uri
     *
     * @return   an Uri
     *
     */
    public static Uri getRoot(Uri uri) {
        return new Uri(uri.getToken(), uri.getNamespace(), 
uri.getScope().toString());
    }
    
    
    /**
     * Scope accessor.
     *
     * @return StringTokenizer
     */
    public Scope getScope() {
        return this.scope;
    }
    
    
    /**
     * Returns the scopes tokenized by the ScopeTokenizer associated
     * with this Uri object.
     *
     * @return Enumeration
     */
    public Enumeration getScopes() {
        return this.scopes.elements();
    }
    
    
    /**
     * Store accessor.
     *
     * @return Store
     */
    public Store getStore() {
        return this.store;
    }
    
    
    /**
     * Token accessor.
     *
     * @return The SlideToken, or null if no token has been set
     * (which is valid)
     */
    public SlideToken getToken() {
        return token;
    }
    
    
    /**
     * Token mutator.
     *
     * @param token New Slide token
     */
    public void setToken(SlideToken token) {
        this.token = token;
    }
    
    
    // --------------------------------------------------------- Public Methods
    
    
    /**
     * Return the namespace to which this Uri belongs.
     *
     * @return Namespace
     */
    public Namespace getNamespace() {
        return namespace;
    }
    
    
    /**
     * Get the parent uri.
     *
     * @return Uri
     */
    public Uri getParentUri() {
        Uri result = scopes.getParentUri();
        if (result != null)
            result.setToken(token);
        return result;
    }
    
    
    /**
     * Invalidate the current Services and PK. Used if there are changes in
     * the namespace at runtime.
     */
    public void invalidateServices() {
        store = null;
        parseUri(this.uri);
    }
    
    
    /**
     * Reconnect the Uri services.
     */
    public void reconnectServices() {
        try {
            if (token == null) {
                store.connectIfNeeded(null);
            } else {
                store.connectIfNeeded(token.getCredentialsToken());
            }
        } catch (ServiceConnectionFailedException e) {
            parseUri(this.uri);
        } catch (ServiceAccessException e) {
            parseUri(this.uri);
        }
    }
    
    
    /**
     * Get the relative path to the matched scope.
     */
    public String getRelative() {
        return (uri.substring(scope.toString().length()));
    }
    
    /**
     * Test whether this Uri is equivalent to its scope
     * @return   a boolean
     */
    public boolean isStoreRoot() {
        UriPath thisPath = new UriPath(uri);
        UriPath scopePath = new UriPath(scope.toString());
        return thisPath.equals(scopePath);
    }
    
    // --------------------------------------------------------- Object Methods
    
    
    /**
     * String representation of the uri object.
     *
     * @return String
     */
    public String toString() {
        return uri;
    }
    
    
    /**
     * Hash code.
     *
     * @return int hash code
     */
    public int hashCode() {
        return this.uri.hashCode();
    }
    
    
    /**
     * Tests equivalence of two Uris.
     *
     * @param obj Object to test
     * @return boolean
     */
    public boolean equals(Object obj) {
        if ((obj != null) && (obj instanceof Uri)) {
           //    return (uri.equals(obj.toString()));
            return uri.equals(((Uri)obj).uri);
        } else {
            return false;
        }
    }
    
    
    /**
     * Do a fast clone of the Uri object.
     */
   public Uri cloneObject() {
        
        Uri result = null;
        try {
            result = (Uri) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
 /* DEBUG       _countUp++;
        result.origine = 2;
        result.instance = _countUp; */
        return result;
    }
   
    
    /**
     * Tests if the given uri represents a parent object.
     *
     * @param uri Uri to test
     * @return boolean
     */
    public boolean isParent(Uri uri) {
        return this.uri.startsWith(uri.toString());
    }
    
    
    // -------------------------------------------------------- Private Methods
    
    
    /**
     * This function is called by the constructor and when uri is changed.
     *
     * @param uri Uri to parse
     */
    protected void parseUri(String uri) {
        // We first try to tokenize the uri string.
        
        scopes = new ScopeTokenizer(token, namespace, uri);
        
        this.uri = scopes.getUri(); // why that
        
        // Find the qualifiying stuff from the registry.
        // Then we contentStore the scope of the found Data Source
        // within scope.
        store = null;
        while ((store == null) && (scopes.hasMoreElements())) {
            Scope courScope = scopes.nextScope();
            try {
                if (store == null) {
                    if (token == null) {
                        store = namespace.retrieveStore(courScope, null);
                    } else {
                        store = namespace.retrieveStore(courScope, 
token.getCredentialsToken());
                    }
                    
                    if (store != null) {
                        scope = courScope;
                    }
                }
            } catch (ServiceConnectionFailedException e) {
                throw new SlideRuntimeException(e.toString(), true);
            } catch (ServiceAccessException e) {
                throw new SlideRuntimeException(e.toString(), true);
            }
        }
        
        // If descriptorsStore or contentStore is still null, then no valid
        // scope is defined in the namespace ...
        if (store == null) {
            throw new ServiceMissingOnRootNodeException();
        }
        
    }
    
    
    // ---------------------------------------------------------- Serialization
    
    
    /**
     * Read serialized object.
     */
    private void readObject(java.io.ObjectInputStream in)
        throws IOException, ClassNotFoundException {
        String namespaceName = (String) in.readObject();
        namespace = Domain.getNamespace(namespaceName);
        parseUri((String) in.readObject());
    }
    
    
    /**
     * Write serialized object.
     */
    private void writeObject(java.io.ObjectOutputStream out)
        throws IOException {
        out.writeObject(namespace.getName());
        out.writeObject(uri);
    }
    
}
/*
 * $Header: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/UriPath.java,v 
1.9 2005/01/03 15:43:26 luetzkendorf Exp $
 * $Revision: 1.9 $
 * $Date: 2005/01/03 15:43:26 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 *  BD/EADS Le 31/01/07 
 *  Fuites mémoire Slide" Enhance equals and hashcode methods 
 */

package org.apache.slide.common;

import java.util.StringTokenizer;

/**
 * An URI path.
 *
 * @version $Revision: 1.9 $
 */
public final class UriPath {
    
    private String[] tokens;
    
    private UriPath() {
    }
    
    private UriPath(String[] tokens) {
        this.tokens = tokens;
    }
    
    public UriPath(String uri) {
        StringTokenizer t = new StringTokenizer( uri, "/" );
        this.tokens = new String[t.countTokens()];
        for (int i = 0; t.hasMoreTokens(); i++) {
            tokens[i] = t.nextToken();
        }
    }
    
    public String[] tokens() {
        return tokens;
    }
    
    public String lastSegment() {
        return tokens.length > 0
            ? tokens[ tokens.length - 1 ]
            : null;
    }
    
    public UriPath parent() {
        if (this.tokens.length == 0) {
            return null;
        }
        return subUriPath(0, tokens.length - 1);
    }
    
    public UriPath child( String segment ) {
        String[] ctokens = new String[tokens.length + 1];
        for (int i = 0; i < tokens.length; i++) {
            ctokens[i] = tokens[i];
        }
        ctokens[tokens.length] = segment;
        return new UriPath(ctokens);
    }
    
    public UriPath subUriPath(int start, int end) {
        UriPath result = new UriPath();
        result.tokens = new String[end - start];
        System.arraycopy(tokens, start, result.tokens, 0, result.tokens.length);
        return result;
    }
    
    public String subUriPathString(int start, int end) {
        if (end > start) {
            StringBuffer b = new StringBuffer(tokens.length * 20);
            for (int i = start; i < end; i++) {
                b.append("/").append(tokens[i]);
            }
            return b.toString();
        } else {
            return "/";
        }
    }
    
    /**
     * Tests whether a given uri is a child of this uri path.
     * @param child uri of the possible child
     * @return <code>true</code> if <code>child</code> is a child of this path
     */
    public boolean isParentOf(String child) {
        StringTokenizer tokenizer = new StringTokenizer(child, "/");
        
        for(int i = 0; i < this.tokens.length && tokenizer.hasMoreTokens();i++) 
{
            String t = tokenizer.nextToken();
            if (!t.equals(this.tokens[i])) {
                return false;
            }
        }
        // there must be exactly one more token 
        if (tokenizer.hasMoreTokens()) {
            tokenizer.nextToken();
            return !tokenizer.hasMoreTokens();
        } else {
            return false;
        }
    }
   
    /**
     * Equals .
     * @param  o  Object to 
     */
    public boolean equals(Object o) {
        boolean result = false;
        if ((o!= null) && (o instanceof UriPath)) {
            result = java.util.Arrays.equals(this.tokens,((UriPath)o).tokens);
        /*    UriPath other = (UriPath)o;
            if (other.tokens.length == this.tokens.length) {
                result = true;
                for (int i = 0; i < this.tokens.length; i++) {
                    if (!other.tokens[i].equals(this.tokens[i])) {
                        result = false;
                        break;
                    }
                }
            }*/
        }
        return result;
    }
    
    /**
     * hashcode use  all tokens to compute hashcode 
     */
    public int hashCode() {
        if (tokens.length > 0) {
           // return tokens[tokens.length - 1].hashCode();
          return this.toString().hashCode();
        }
        else {
            return 0; 
        }
    }
    
    public String toString() {
        if (tokens.length > 0) {
            StringBuffer b = new StringBuffer();
            for (int i = 0; i < tokens.length; i++) {
                b.append("/").append(tokens[i]);
            }
            return b.toString();
        }
        else {
            return "/";
        }
    }
    
    public static int segmentCount(String uri) {
        return new StringTokenizer(uri, "/").countTokens();
    }
    
    public static String getParentUri(String uri) {
        if ("/".equals(uri)) return null;
        
        int lastSlashPos = uri.endsWith("/") ? 
                uri.lastIndexOf('/', uri.length()-2) : uri.lastIndexOf('/');
        if (lastSlashPos == -1) {
            throw new RuntimeException("Can't create parent uri for: " + uri);
        }
        if (lastSlashPos == 0) {
            return "/";
        }
        
        return uri.substring(0, lastSlashPos);
    }
    
    public static String getLastSegment(String uri) {
        if ("/".equals(uri)) return "";
        
        int lastSlashPos = uri.endsWith("/") ? 
                uri.lastIndexOf('/', uri.length()-2) : uri.lastIndexOf('/');
        if (lastSlashPos == -1) {
            return uri;
        }
        
        return uri.endsWith("/") 
                ? uri.substring(lastSlashPos+1, uri.length()-1)
                : uri.substring(lastSlashPos+1);
    }
    
    public static void main(String[] args) {
        System.out.println(getParentUri("/"));
        System.out.println(getParentUri("/abc"));
        System.out.println(getParentUri("/abc/"));
        System.out.println(getParentUri("/abc/def"));
        System.out.println(getParentUri("/abc/def/"));
        System.out.println(getLastSegment("/"));
        System.out.println(getLastSegment("/abc"));
        System.out.println(getLastSegment("/abc/"));
        System.out.println(getLastSegment("/abc/def"));
        System.out.println(getLastSegment("/abc/def/"));
    }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
  • Uri Bruno DOREL

Reply via email to