On Fri, Apr 20, 2018 at 9:01 AM, Guillaume Nodet <[email protected]> wrote: > I'm going to work on those classes too then, in order to reuse them instead > of the one we have in Karaf. They are actually closer to the ones in the > framework. It also includes a CapabilitySet / SimpleFilter which speeds > things a lot when using the resolver.
I was hoping we could maybe reuse them in the framework as well. regards, Karl > One point though, I'm not sure I like the setResource(xx) on the Capability > / Requirement, because there's a risk of running out of sync with > Resource#getCapabilities / getRequirements. So I wonder if a final > Resource field would be more appropriate. > > I think a Resource implementation would be interesting too. > > 2018-04-20 8:34 GMT+02:00 <[email protected]>: > >> Author: davidb >> Date: Fri Apr 20 06:34:25 2018 >> New Revision: 1829625 >> >> URL: http://svn.apache.org/viewvc?rev=1829625&view=rev >> Log: >> Improvements to the OSGi Capability and Requirement implementations >> >> These come from the Apache Sling Whitenboard Feature Model project. Merged >> with Felix Utils to increase sharing across projects. >> >> Added: >> felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/ >> AbstractCapabilityRequirement.java >> Modified: >> felix/trunk/utils/pom.xml >> felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/CapabilityImpl.java >> felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/RequirementImpl.java >> felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/ >> CapabilityImplTest.java >> felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/ >> RequirementImplTest.java >> >> Modified: felix/trunk/utils/pom.xml >> URL: http://svn.apache.org/viewvc/felix/trunk/utils/pom.xml?rev= >> 1829625&r1=1829624&r2=1829625&view=diff >> ============================================================ >> ================== >> --- felix/trunk/utils/pom.xml (original) >> +++ felix/trunk/utils/pom.xml Fri Apr 20 06:34:25 2018 >> @@ -27,7 +27,7 @@ >> <modelVersion>4.0.0</modelVersion> >> <name>Apache Felix Utils</name> >> <description>Utility classes for OSGi.</description> >> - <version>1.10.5-SNAPSHOT</version> >> + <version>1.11.0-SNAPSHOT</version> >> <artifactId>org.apache.felix.utils</artifactId> >> >> <scm> >> >> Added: felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/AbstractCapabilityRequirement.java >> URL: http://svn.apache.org/viewvc/felix/trunk/utils/src/main/ >> java/org/apache/felix/utils/capabilities/AbstractCapabilityRequirement. >> java?rev=1829625&view=auto >> ============================================================ >> ================== >> --- felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/ >> AbstractCapabilityRequirement.java (added) >> +++ felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/ >> AbstractCapabilityRequirement.java Fri Apr 20 06:34:25 2018 >> @@ -0,0 +1,135 @@ >> +/* >> + * Licensed to the Apache Software Foundation (ASF) under one or more >> + * contributor license agreements. See the NOTICE file distributed with >> this >> + * work for additional information regarding copyright ownership. The ASF >> + * licenses this file to You 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. >> + */ >> +package org.apache.felix.utils.capabilities; >> + >> +import org.osgi.resource.Resource; >> + >> +import java.util.Collections; >> +import java.util.HashMap; >> +import java.util.Map; >> + >> +abstract class AbstractCapabilityRequirement { >> + >> + /** The namespace. Required. */ >> + private final String namespace; >> + >> + /** Optional resource. */ >> + private volatile Resource resource; >> + >> + /** Optional attributes. Never null. */ >> + private final Map<String, Object> attributes; >> + >> + /** Optional attributes. Never null. */ >> + private final Map<String, String> directives; >> + >> + AbstractCapabilityRequirement(final String ns, final Map<String, >> Object> attrs, final Map<String, String> dirs, final Resource res) { >> + if ( ns == null ) { >> + throw new IllegalArgumentException("Namespace must not be >> null."); >> + } >> + namespace = ns; >> + attributes = attrs == null >> + ? Collections.<String, Object>emptyMap() >> + : Collections.unmodifiableMap(new HashMap<String, >> Object>(attrs)); >> + directives = dirs == null >> + ? Collections.<String,String>emptyMap() >> + : Collections.unmodifiableMap(new >> HashMap<String,String>(dirs)); >> + resource = res; >> + } >> + >> + /** >> + * Return the namespace. >> + * @return The namespace. This is never @{code null}. >> + */ >> + public String getNamespace() { >> + return namespace; >> + } >> + >> + /** >> + * Return the attributes. >> + * @return The attributes, might be empty. >> + */ >> + public Map<String, Object> getAttributes() { >> + return attributes; >> + } >> + >> + /** >> + * Return the directives. >> + * @return The directives, might be empty. >> + */ >> + public Map<String, String> getDirectives() { >> + return directives; >> + } >> + >> + /** >> + * Return the resource. >> + * @return The resource or @{code null}. >> + */ >> + public Resource getResource() { >> + return resource; >> + } >> + >> + /** >> + * Set the resource associated with this requirement. >> + * >> + * @param res The resource. >> + */ >> + public void setResource(Resource res) { >> + resource = res; >> + } >> + >> + @Override >> + public int hashCode() { >> + final int prime = 31; >> + int result = 1; >> + result = prime * result + attributes.hashCode(); >> + result = prime * result + directives.hashCode(); >> + result = prime * result + namespace.hashCode(); >> + >> + if (resource != null) >> + result = prime * result + resource.hashCode(); >> + >> + return result; >> + } >> + >> + @Override >> + public boolean equals(Object obj) { >> + if (this == obj) >> + return true; >> + if (obj == null) >> + return false; >> + if (getClass() != obj.getClass()) >> + return false; >> + AbstractCapabilityRequirement other = >> (AbstractCapabilityRequirement) >> obj; >> + if (!namespace.equals(other.namespace)) >> + return false; >> + if (!attributes.equals(other.attributes)) >> + return false; >> + if (!directives.equals(other.directives)) >> + return false; >> + if (resource == null) { >> + return other.resource == null; >> + } else { >> + return resource.equals(other.resource); >> + } >> + } >> + >> + @Override >> + public String toString() { >> + return getClass().getSimpleName() + " [resource=" + resource + ", >> namespace=" + namespace + ", attributes=" + attributes >> + + ", directives=" + directives + "]"; >> + } >> +} >> >> Modified: felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/CapabilityImpl.java >> URL: http://svn.apache.org/viewvc/felix/trunk/utils/src/main/ >> java/org/apache/felix/utils/capabilities/CapabilityImpl. >> java?rev=1829625&r1=1829624&r2=1829625&view=diff >> ============================================================ >> ================== >> --- felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/CapabilityImpl.java (original) >> +++ felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/CapabilityImpl.java Fri Apr 20 06:34:25 2018 >> @@ -1,161 +1,59 @@ >> /* >> - * Licensed to the Apache Software Foundation (ASF) under one >> - * or more contributor license agreements. See the NOTICE file >> - * distributed with this work for additional information >> - * regarding copyright ownership. The ASF licenses this file >> - * to you 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 >> + * Licensed to the Apache Software Foundation (ASF) under one or more >> + * contributor license agreements. See the NOTICE file distributed with >> this >> + * work for additional information regarding copyright ownership. The ASF >> + * licenses this file to You 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 >> + * 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. >> + * 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. >> */ >> package org.apache.felix.utils.capabilities; >> >> import org.osgi.resource.Capability; >> import org.osgi.resource.Resource; >> >> -import java.util.Collections; >> import java.util.Map; >> >> /** >> * Implementation of the OSGi Capability interface. >> */ >> -public class CapabilityImpl implements Capability >> -{ >> - private final String namespace; >> - private final Map<String, Object> attributes; >> - private final Map<String, String> directives; >> - private volatile Resource resource; >> - >> +public class CapabilityImpl extends AbstractCapabilityRequirement >> implements Capability { >> /** >> - * Create a capability. >> - * >> + * Create a capability that is not associated with a resource. >> + * @param res The resource associated with the capability. May be >> null. >> * @param ns The namespace of the capability. >> * @param attrs The attributes of the capability. >> * @param dirs The directives of the capability. >> */ >> - public CapabilityImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs) >> - { >> + public CapabilityImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs) { >> this(ns, attrs, dirs, null); >> } >> >> /** >> * Create a capability. >> - * >> * @param ns The namespace of the capability. >> * @param attrs The attributes of the capability. >> * @param dirs The directives of the capability. >> - * @param res The resource associated with the capability. >> - */ >> - public CapabilityImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs, Resource res) >> - { >> - namespace = ns; >> - attributes = Collections.unmodifiableMap(attrs); >> - directives = Collections.unmodifiableMap(dirs); >> - resource = res; >> - } >> - >> - /** >> - * Returns the namespace of this capability. >> - * >> - * @return The namespace of this capability. >> - */ >> - public String getNamespace() >> - { >> - return namespace; >> - } >> - >> - /** >> - * Returns the attributes of this capability. >> - * >> - * @return An unmodifiable map of attribute names to attribute values >> for >> - * this capability, or an empty map if this capability has no >> - * attributes. >> - */ >> - public Map<String, Object> getAttributes() >> - { >> - return attributes; >> - } >> - >> - /** >> - * Returns the directives of this capability. >> - * >> - * @return An unmodifiable map of directive names to directive values >> for >> - * this capability, or an empty map if this capability has no >> - * directives. >> + * @param res The resource associated with the capability. May be >> null. >> */ >> - public Map<String, String> getDirectives() >> - { >> - return directives; >> + public CapabilityImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs, Resource res) { >> + super(ns, attrs, dirs, res); >> } >> >> /** >> - * Returns the resource declaring this capability. >> - * >> - * @return The resource declaring this capability. >> + * Create a capability based on an existing capability, providing the >> resource. >> + * The namespace, attributes and directives are copied from the >> provided capability. >> + * @param capability The capability to base the new requirement on. >> + * @param resource The resource to be associated with the capability >> */ >> - public Resource getResource() >> - { >> - return resource; >> - } >> - >> - /** >> - * Sets the resource associated with this capability. >> - * >> - * @param res The resource. >> - */ >> - public void setResource(Resource res) >> - { >> - resource = res; >> - } >> - >> - @Override >> - public int hashCode() { >> - final int prime = 31; >> - int result = 1; >> - result = prime * result + ((attributes == null) ? 0 : >> attributes.hashCode()); >> - result = prime * result + ((directives == null) ? 0 : >> directives.hashCode()); >> - result = prime * result + ((namespace == null) ? 0 : >> namespace.hashCode()); >> - result = prime * result + ((resource == null) ? 0 : >> resource.hashCode()); >> - return result; >> - } >> - >> - @Override >> - public boolean equals(Object obj) { >> - if (this == obj) >> - return true; >> - if (obj == null) >> - return false; >> - if (getClass() != obj.getClass()) >> - return false; >> - CapabilityImpl other = (CapabilityImpl) obj; >> - if (attributes == null) { >> - if (other.attributes != null) >> - return false; >> - } else if (!attributes.equals(other.attributes)) >> - return false; >> - if (directives == null) { >> - if (other.directives != null) >> - return false; >> - } else if (!directives.equals(other.directives)) >> - return false; >> - if (namespace == null) { >> - if (other.namespace != null) >> - return false; >> - } else if (!namespace.equals(other.namespace)) >> - return false; >> - if (resource == null) { >> - if (other.resource != null) >> - return false; >> - } else if (!resource.equals(other.resource)) >> - return false; >> - return true; >> + public CapabilityImpl(Resource resource, Capability capability) { >> + this(capability.getNamespace(), capability.getAttributes(), >> capability.getDirectives(), resource); >> } >> } >> >> Modified: felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/RequirementImpl.java >> URL: http://svn.apache.org/viewvc/felix/trunk/utils/src/main/ >> java/org/apache/felix/utils/capabilities/RequirementImpl. >> java?rev=1829625&r1=1829624&r2=1829625&view=diff >> ============================================================ >> ================== >> --- felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/RequirementImpl.java (original) >> +++ felix/trunk/utils/src/main/java/org/apache/felix/utils/ >> capabilities/RequirementImpl.java Fri Apr 20 06:34:25 2018 >> @@ -1,20 +1,18 @@ >> /* >> - * Licensed to the Apache Software Foundation (ASF) under one >> - * or more contributor license agreements. See the NOTICE file >> - * distributed with this work for additional information >> - * regarding copyright ownership. The ASF licenses this file >> - * to you 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 >> + * Licensed to the Apache Software Foundation (ASF) under one or more >> + * contributor license agreements. See the NOTICE file distributed with >> this >> + * work for additional information regarding copyright ownership. The ASF >> + * licenses this file to You 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 >> + * 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. >> + * 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. >> */ >> package org.apache.felix.utils.capabilities; >> >> @@ -28,154 +26,51 @@ import java.util.Map; >> /** >> * Implementation of the OSGi Requirement interface. >> */ >> -public class RequirementImpl implements Requirement >> -{ >> - private final String namespace; >> - private final Map<String, Object> attributes; >> - private final Map<String, String> directives; >> - private volatile Resource resource; >> - >> +public class RequirementImpl extends AbstractCapabilityRequirement >> implements Requirement { >> /** >> - * Create a requirement. >> - * >> + * Create a requirement that is not associated with a resource. >> + * @param res The resource associated with the requirement. >> * @param ns The namespace of the requirement. >> * @param attrs The attributes of the requirement. >> * @param dirs The directives of the requirement. >> */ >> - public RequirementImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs) >> - { >> + public RequirementImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs) { >> this(ns, attrs, dirs, null); >> } >> >> /** >> * Create a requirement. >> - * >> * @param ns The namespace of the requirement. >> * @param attrs The attributes of the requirement. >> * @param dirs The directives of the requirement. >> * @param res The resource associated with the requirement. >> */ >> - public RequirementImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs, Resource res) >> - { >> - namespace = ns; >> - attributes = attrs; >> - directives = dirs; >> - resource = res; >> - } >> - >> - /** >> - * Create a requirement with a namespace and a filter. >> - * >> - * This is a convenience method that creates a requirement with >> - * an empty attributes map and a single 'filter' directive. >> - * @param ns The namespace for the requirement. >> - * @param filter The filter. >> - */ >> - public RequirementImpl(String ns, String filter) >> - { >> - this(ns, Collections.<String, Object>emptyMap(), >> - filter == null ? Collections.<String, String> emptyMap() : >> - Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, >> filter)); >> + public RequirementImpl(String ns, Map<String, Object> attrs, >> Map<String, String> dirs, Resource res) { >> + super(ns, attrs, dirs, res); >> } >> >> /** >> - * Returns the namespace of this requirement. >> - * >> - * @return The namespace of this requirement. >> + * Create a requirement with a namespace and a filter. >> + * >> + * This is a convenience method that creates a requirement with >> + * an empty attributes map and a single 'filter' directive. >> + * @param ns The namespace for the requirement. >> + * @param filter The filter. >> + */ >> + public RequirementImpl(String ns, String filter) >> + { >> + this(ns, Collections.<String, Object>emptyMap(), >> + filter == null ? Collections.<String, String> emptyMap() : >> + >> Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, >> filter)); >> + } >> + >> + /** >> + * Create a requirement based on an existing requirement, providing >> the resource. >> + * The namespace, attributes and directives are copied from the >> provided requirement. >> + * @param requirement The requirement to base the new requirement on. >> + * @param resource The resource to be associated with the requirement >> */ >> - public String getNamespace() >> - { >> - return namespace; >> - } >> - >> - /** >> - * Returns the attributes of this requirement. >> - * >> - * <p> >> - * Requirement attributes have no specified semantics and are >> considered >> - * extra user defined information. >> - * >> - * @return An unmodifiable map of attribute names to attribute values >> for >> - * this requirement, or an empty map if this requirement has >> no >> - * attributes. >> - */ >> - public Map<String, Object> getAttributes() >> - { >> - return Collections.unmodifiableMap(attributes); >> - } >> - >> - /** >> - * Returns the directives of this requirement. >> - * >> - * @return An unmodifiable map of directive names to directive values >> for >> - * this requirement, or an empty map if this requirement has >> no >> - * directives. >> - */ >> - public Map<String, String> getDirectives() >> - { >> - return Collections.unmodifiableMap(directives); >> - } >> - >> - /** >> - * Returns the resource declaring this requirement. >> - * >> - * @return The resource declaring this requirement. This can be >> {@code null} >> - * if this requirement is synthesized. >> - */ >> - public Resource getResource() >> - { >> - return resource; >> - } >> - >> - /** >> - * Set the resource associated with this requirement. >> - * >> - * @param res The resource. >> - */ >> - public void setResource(Resource res) { >> - resource = res; >> - } >> - >> - @Override >> - public int hashCode() { >> - final int prime = 31; >> - int result = 1; >> - result = prime * result + ((attributes == null) ? 0 : >> attributes.hashCode()); >> - result = prime * result + ((directives == null) ? 0 : >> directives.hashCode()); >> - result = prime * result + ((namespace == null) ? 0 : >> namespace.hashCode()); >> - result = prime * result + ((resource == null) ? 0 : >> resource.hashCode()); >> - return result; >> - } >> - >> - @Override >> - public boolean equals(Object obj) { >> - if (this == obj) >> - return true; >> - if (obj == null) >> - return false; >> - if (getClass() != obj.getClass()) >> - return false; >> - RequirementImpl other = (RequirementImpl) obj; >> - if (attributes == null) { >> - if (other.attributes != null) >> - return false; >> - } else if (!attributes.equals(other.attributes)) >> - return false; >> - if (directives == null) { >> - if (other.directives != null) >> - return false; >> - } else if (!directives.equals(other.directives)) >> - return false; >> - if (namespace == null) { >> - if (other.namespace != null) >> - return false; >> - } else if (!namespace.equals(other.namespace)) >> - return false; >> - if (resource == null) { >> - if (other.resource != null) >> - return false; >> - } else if (!resource.equals(other.resource)) >> - return false; >> - return true; >> + public RequirementImpl(Resource resource, Requirement requirement) { >> + this(requirement.getNamespace(), requirement.getAttributes(), >> requirement.getDirectives(), resource); >> } >> } >> >> Modified: felix/trunk/utils/src/test/java/org/apache/felix/utils/ >> capabilities/CapabilityImplTest.java >> URL: http://svn.apache.org/viewvc/felix/trunk/utils/src/test/ >> java/org/apache/felix/utils/capabilities/CapabilityImplTest.java?rev= >> 1829625&r1=1829624&r2=1829625&view=diff >> ============================================================ >> ================== >> --- >> felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/CapabilityImplTest.java >> (original) >> +++ >> felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/CapabilityImplTest.java >> Fri Apr 20 06:34:25 2018 >> @@ -57,4 +57,18 @@ public class CapabilityImplTest extends >> assertFalse(c1.equals(c3)); >> assertFalse(c1.hashCode() == c3.hashCode()); >> } >> + >> + public void testCopyCapability() { >> + CapabilityImpl c = new CapabilityImpl("x.y.z", >> + Collections.<String, Object>singletonMap("a", 123), >> + Collections.<String, String>singletonMap("x", "y"), >> + Mockito.mock(Resource.class)); >> + >> + Resource res2 = Mockito.mock(Resource.class); >> + CapabilityImpl c2 = new CapabilityImpl(res2, c); >> + assertFalse("Should not be equal, the resources are different", >> c.equals(c2)); >> + >> + c.setResource(res2); >> + assertEquals(c, c2); >> + } >> } >> >> Modified: felix/trunk/utils/src/test/java/org/apache/felix/utils/ >> capabilities/RequirementImplTest.java >> URL: http://svn.apache.org/viewvc/felix/trunk/utils/src/test/ >> java/org/apache/felix/utils/capabilities/RequirementImplTest.java?rev= >> 1829625&r1=1829624&r2=1829625&view=diff >> ============================================================ >> ================== >> --- >> felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/RequirementImplTest.java >> (original) >> +++ >> felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/RequirementImplTest.java >> Fri Apr 20 06:34:25 2018 >> @@ -69,4 +69,18 @@ public class RequirementImplTest extends >> assertEquals(0, r2.getAttributes().size()); >> assertEquals(0, r2.getDirectives().size()); >> } >> + >> + public void testCopyRequirement() { >> + RequirementImpl r = new RequirementImpl("x.y.z", >> + Collections.<String, Object>singletonMap("a", 123), >> + Collections.<String, String>singletonMap("x", "y"), >> + Mockito.mock(Resource.class)); >> + >> + Resource res2 = Mockito.mock(Resource.class); >> + RequirementImpl r2 = new RequirementImpl(res2, r); >> + assertFalse("Should not be equal, the resources are different", >> r.equals(r2)); >> + >> + r.setResource(res2); >> + assertEquals(r, r2); >> + } >> } >> >> >> > > > -- > ------------------------ > Guillaume Nodet -- Karl Pauls [email protected]
