Author: fguillaume
Date: Wed Feb 10 16:35:57 2010
New Revision: 908573
URL: http://svn.apache.org/viewvc?rev=908573&view=rev
Log:
CMIS-103: APPConnection and SimpleTypeManager thread-safety
Modified:
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPContentManager.java
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPRepository.java
incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleTypeManager.java
Modified:
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPContentManager.java
URL:
http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPContentManager.java?rev=908573&r1=908572&r2=908573&view=diff
==============================================================================
---
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPContentManager.java
(original)
+++
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPContentManager.java
Wed Feb 10 16:35:57 2010
@@ -14,6 +14,7 @@
* Authors:
* Bogdan Stefanescu, Nuxeo
* Florent Guillaume, Nuxeo
+ * Chris Hubick
*/
package org.apache.chemistry.atompub.client;
@@ -21,8 +22,10 @@
import org.apache.chemistry.atompub.client.stax.ReadContext;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScheme;
+import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.auth.CredentialsProvider;
/**
@@ -41,8 +44,7 @@
public APPContentManager(String url) {
this.baseUrl = url;
client = new HttpClient();
- // client.setHttpConnectionManager(new
- // MultiThreadedHttpConnectionManager());
+ client.setHttpConnectionManager(new
MultiThreadedHttpConnectionManager());
}
public String getBaseUrl() {
@@ -87,16 +89,19 @@
// TODO have another login method with more generic Credentials
public void login(String username, String password) {
this.username = username;
- CredentialsProvider cp = new UsernamePasswordCredentialsProvider(
- username, password);
- client.getParams().setAuthenticationPreemptive(true);
+ Credentials credentials = new UsernamePasswordCredentials(username,
+ password);
+ CredentialsProvider cp = new FixedCredentialsProvider(credentials);
+ client.getState().setCredentials(AuthScope.ANY, credentials);
client.getParams().setParameter(CredentialsProvider.PROVIDER, cp);
+ client.getParams().setAuthenticationPreemptive(true);
}
public void logout() {
username = null;
- client.getParams().setAuthenticationPreemptive(true);
+ client.getState().setCredentials(AuthScope.ANY, null);
client.getParams().setParameter(CredentialsProvider.PROVIDER, null);
+ client.getParams().setAuthenticationPreemptive(false);
}
public String getCurrentLogin() {
@@ -104,18 +109,15 @@
}
/**
- * Simple credentials provider using fixed username/password credentials.
- * Other implementations could query the user through a GUI.
+ * Simple credentials provider using fixed credentials. Other
+ * implementations could query the user through a GUI.
*/
- public static class UsernamePasswordCredentialsProvider implements
- CredentialsProvider {
+ public static class FixedCredentialsProvider implements
CredentialsProvider {
protected final Credentials credentials;
- public UsernamePasswordCredentialsProvider(String username,
- String password) {
- this.credentials = new UsernamePasswordCredentials(username,
- password);
+ public FixedCredentialsProvider(Credentials credentials) {
+ this.credentials = credentials;
}
public Credentials getCredentials(AuthScheme scheme, String host,
Modified:
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPRepository.java
URL:
http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPRepository.java?rev=908573&r1=908572&r2=908573&view=diff
==============================================================================
---
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPRepository.java
(original)
+++
incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPRepository.java
Wed Feb 10 16:35:57 2010
@@ -174,7 +174,7 @@
typeManager.addType(type);
}
- protected void loadTypes() {
+ protected synchronized void loadTypes() {
if (typeManager != null) {
return;
}
Modified:
incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleTypeManager.java
URL:
http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleTypeManager.java?rev=908573&r1=908572&r2=908573&view=diff
==============================================================================
---
incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleTypeManager.java
(original)
+++
incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleTypeManager.java
Wed Feb 10 16:35:57 2010
@@ -25,6 +25,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.chemistry.BaseType;
import org.apache.chemistry.ListPage;
@@ -46,6 +48,16 @@
protected final Map<String, Collection<Type>> typesChildren;
+ /**
+ * Read-write lock protecting access to {...@link #types},
+ * {...@link #propertyDefinitions} and {...@link #typesChildren}.
+ */
+ private final ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
+
+ private final Lock rlock = rwlock.readLock();
+
+ private final Lock wlock = rwlock.writeLock();
+
public SimpleTypeManager() {
typesChildren = new HashMap<String, Collection<Type>>();
// make sure base types are there
@@ -55,32 +67,37 @@
}
public void addType(Type type) {
- String typeId = type.getId();
- if (types.containsKey(typeId)) {
- throw new RuntimeException("Type already defined: " + typeId);
- }
- types.put(typeId, type);
- for (PropertyDefinition pdef : type.getPropertyDefinitions()) {
- addPropertyDefinition(pdef);
- }
- typesChildren.put(typeId, new LinkedList<Type>());
- String parentId = type.getParentId();
- if (parentId == null) {
- // check it's a base type
- try {
- BaseType.get(typeId);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Type: " + typeId
- + " must have a parent type");
- }
- } else {
- Collection<Type> siblings = typesChildren.get(parentId);
- if (siblings == null) {
- throw new IllegalArgumentException("Type: " + typeId
- + " refers to unknown parent: " + parentId);
+ wlock.lock();
+ try {
+ String typeId = type.getId();
+ if (types.containsKey(typeId)) {
+ throw new RuntimeException("Type already defined: " + typeId);
+ }
+ types.put(typeId, type);
+ for (PropertyDefinition pdef : type.getPropertyDefinitions()) {
+ addPropertyDefinition(pdef);
+ }
+ typesChildren.put(typeId, new LinkedList<Type>());
+ String parentId = type.getParentId();
+ if (parentId == null) {
+ // check it's a base type
+ try {
+ BaseType.get(typeId);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Type: " + typeId
+ + " must have a parent type");
+ }
+ } else {
+ Collection<Type> siblings = typesChildren.get(parentId);
+ if (siblings == null) {
+ throw new IllegalArgumentException("Type: " + typeId
+ + " refers to unknown parent: " + parentId);
+ }
+ siblings.add(type);
+ // TODO check no cycle
}
- siblings.add(type);
- // TODO check no cycle
+ } finally {
+ wlock.unlock();
}
}
@@ -105,15 +122,30 @@
}
public Type getType(String typeId) {
- return types.get(typeId);
+ rlock.lock();
+ try {
+ return types.get(typeId);
+ } finally {
+ rlock.unlock();
+ }
}
public PropertyDefinition getPropertyDefinition(String id) {
- return propertyDefinitions.get(id);
+ rlock.lock();
+ try {
+ return propertyDefinitions.get(id);
+ } finally {
+ rlock.unlock();
+ }
}
public Collection<Type> getTypes() {
- return new ArrayList<Type>(types.values());
+ rlock.lock();
+ try {
+ return new ArrayList<Type>(types.values());
+ } finally {
+ rlock.unlock();
+ }
}
public Collection<Type> getTypeDescendants(String typeId) {
@@ -129,23 +161,29 @@
public ListPage<Type> getTypeChildren(String typeId,
boolean includePropertyDefinitions, Paging paging) {
// TODO includePropertyDefinitions, paging
- List<Type> list;
- if (typeId == null) {
- list = new ArrayList<Type>(4);
- for (String id : BaseType.ALL_IDS) {
- Type type = types.get(id);
- if (type != null) {
- list.add(type);
+ rlock.lock();
+ try {
+ List<Type> list;
+ if (typeId == null) {
+ list = new ArrayList<Type>(4);
+ for (String id : BaseType.ALL_IDS) {
+ Type type = types.get(id);
+ if (type != null) {
+ list.add(type);
+ }
}
+ } else {
+ Collection<Type> children = typesChildren.get(typeId);
+ if (children == null) {
+ throw new IllegalArgumentException("No such type: "
+ + typeId);
+ }
+ list = new ArrayList<Type>(children);
}
- } else {
- Collection<Type> children = typesChildren.get(typeId);
- if (children == null) {
- throw new IllegalArgumentException("No such type: " + typeId);
- }
- list = new ArrayList<Type>(children);
+ return new SimpleListPage<Type>(list);
+ } finally {
+ rlock.unlock();
}
- return new SimpleListPage<Type>(list);
}
/*
@@ -153,32 +191,40 @@
*/
public Collection<Type> getTypeDescendants(String typeId, int depth,
boolean returnPropertyDefinitions) {
- if (depth == 0) {
- throw new IllegalArgumentException("Depth 0 invalid");
- }
- List<Type> list = new LinkedList<Type>();
- Set<String> done = new HashSet<String>();
- if (typeId == null) {
- // return all types
- for (String tid : BaseType.ALL_IDS) {
- Type type = types.get(tid);
- if (type == null) {
- // some optional base types may be absent
- continue;
- }
- list.add(type);
- collectSubTypes(tid, -1, returnPropertyDefinitions, list,
done);
- }
- } else {
- if (!types.containsKey(typeId)) {
- throw new IllegalArgumentException("No such type: " + typeId);
+ rlock.lock();
+ try {
+ if (depth == 0) {
+ throw new IllegalArgumentException("Depth 0 invalid");
+ }
+ List<Type> list = new LinkedList<Type>();
+ Set<String> done = new HashSet<String>();
+ if (typeId == null) {
+ // return all types
+ for (String tid : BaseType.ALL_IDS) {
+ Type type = types.get(tid);
+ if (type == null) {
+ // some optional base types may be absent
+ continue;
+ }
+ list.add(type);
+ collectSubTypes(tid, -1, returnPropertyDefinitions, list,
+ done);
+ }
+ } else {
+ if (!types.containsKey(typeId)) {
+ throw new IllegalArgumentException("No such type: "
+ + typeId);
+ }
+ collectSubTypes(typeId, depth, returnPropertyDefinitions, list,
+ done);
}
- collectSubTypes(typeId, depth, returnPropertyDefinitions, list,
- done);
+ return list;
+ } finally {
+ rlock.unlock();
}
- return list;
}
+ // rlock already held by caller
protected void collectSubTypes(String typeId, int depth,
boolean returnPropertyDefinitions, List<Type> list, Set<String>
done) {
// TODO returnPropertyDefinitions