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]