You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by dc...@apache.org on 2010/04/22 18:04:22 UTC

svn commit: r936922 [4/18] - in /incubator/chemistry/opencmis/trunk/chemistry-opencmis-client: chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/ chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/c...

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java?rev=936922&r1=936921&r2=936922&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java Thu Apr 22 16:04:19 2010
@@ -78,719 +78,719 @@ import org.apache.chemistry.opencmis.com
  */
 public class AbstractAtomPubService {
 
-	protected enum IdentifierType {
-		ID, PATH
-	};
-
-	protected static final String NAME_COLLECTION = "collection";
-	protected static final String NAME_URI_TEMPLATE = "uritemplate";
-	protected static final String NAME_PATH_SEGMENT = "pathSegment";
-	protected static final String NAME_RELATIVE_PATH_SEGMENT = "relativePathSegment";
-	protected static final String NAME_NUM_ITEMS = "numItems";
-
-	private Session fSession;
-
-	/**
-	 * Sets the current session.
-	 */
-	protected void setSession(Session session) {
-		fSession = session;
-	}
-
-	/**
-	 * Gets the current session.
-	 */
-	protected Session getSession() {
-		return fSession;
-	}
-
-	/**
-	 * Returns the service document URL of this session.
-	 */
-	protected String getServiceDocURL() {
-		Object url = fSession.get(SessionParameter.ATOMPUB_URL);
-		if (url instanceof String) {
-			return (String) url;
-		}
-
-		return null;
-	}
-
-	// ---- link cache ----
-
-	/**
-	 * Returns the link cache or creates a new cache if it doesn't exist.
-	 */
-	protected LinkCache getLinkCache() {
-		LinkCache linkCache = (LinkCache) getSession().get(SpiSessionParameter.LINK_CACHE);
-		if (linkCache == null) {
-			linkCache = new LinkCache(getSession());
-			getSession().put(SpiSessionParameter.LINK_CACHE, linkCache);
-		}
-
-		return linkCache;
-	}
-
-	/**
-	 * Gets a link from the cache.
-	 */
-	protected String getLink(String repositoryId, String id, String rel, String type) {
-		if (repositoryId == null) {
-			throw new CmisInvalidArgumentException("Repository id must be set!");
-		}
-
-		if (id == null) {
-			throw new CmisInvalidArgumentException("Object id must be set!");
-		}
-
-		return getLinkCache().getLink(repositoryId, id, rel, type);
-	}
-
-	/**
-	 * Gets a link from the cache.
-	 */
-	protected String getLink(String repositoryId, String id, String rel) {
-		return getLink(repositoryId, id, rel, null);
-	}
-
-	/**
-	 * Gets a link from the cache if it is there or loads it into the cache if
-	 * it is not there.
-	 */
-	protected String loadLink(String repositoryId, String id, String rel, String type) {
-		String link = getLink(repositoryId, id, rel, type);
-		if (link == null) {
-			getObjectInternal(repositoryId, IdentifierType.ID, id, ReturnVersion.THIS, null, null, null, null, null,
-					null, null);
-			link = getLink(repositoryId, id, rel, type);
-		}
-
-		return link;
-	}
-
-	/**
-	 * Adds a link to the cache.
-	 */
-	protected void addLink(String repositoryId, String id, String rel, String type, String link) {
-		getLinkCache().addLink(repositoryId, id, rel, type, link);
-	}
-
-	/**
-	 * Adds a link to the cache.
-	 */
-	protected void addLink(String repositoryId, String id, AtomLink link) {
-		getLinkCache().addLink(repositoryId, id, link.getRel(), link.getType(), link.getHref());
-	}
-
-	/**
-	 * Removes all links of an object.
-	 */
-	protected void removeLinks(String repositoryId, String id) {
-		getLinkCache().removeLinks(repositoryId, id);
-	}
-
-	/**
-	 * Locks the link cache.
-	 */
-	protected void lockLinks() {
-		getLinkCache().lockLinks();
-	}
-
-	/**
-	 * Unlocks the link cache.
-	 */
-	protected void unlockLinks() {
-		getLinkCache().unlockLinks();
-	}
-
-	/**
-	 * Checks a link throw an appropriate exception.
-	 */
-	protected void throwLinkException(String repositoryId, String id, String rel, String type) {
-		int index = getLinkCache().checkLink(repositoryId, id, rel, type);
-
-		switch (index) {
-		case 0:
-			throw new CmisObjectNotFoundException("Unknown repository!");
-		case 1:
-			throw new CmisObjectNotFoundException("Unknown object!");
-		case 2:
-			throw new CmisNotSupportedException("Operation not supported by the repository for this object!");
-		case 3:
-			throw new CmisNotSupportedException("No link with matching media type!");
-		case 4:
-			throw new CmisRuntimeException("Nothing wrong! Either this is a bug or threading issue.");
-		default:
-			throw new CmisRuntimeException("Unknown error!");
-		}
-	}
-
-	/**
-	 * Gets a type link from the cache.
-	 */
-	protected String getTypeLink(String repositoryId, String typeId, String rel, String type) {
-		if (repositoryId == null) {
-			throw new CmisInvalidArgumentException("Repository id must be set!");
-		}
-
-		if (typeId == null) {
-			throw new CmisInvalidArgumentException("Type id must be set!");
-		}
-
-		return getLinkCache().getTypeLink(repositoryId, typeId, rel, type);
-	}
-
-	/**
-	 * Gets a type link from the cache.
-	 */
-	protected String getTypeLink(String repositoryId, String typeId, String rel) {
-		return getTypeLink(repositoryId, typeId, rel, null);
-	}
-
-	/**
-	 * Gets a link from the cache if it is there or loads it into the cache if
-	 * it is not there.
-	 */
-	protected String loadTypeLink(String repositoryId, String typeId, String rel, String type) {
-		String link = getTypeLink(repositoryId, typeId, rel, type);
-		if (link == null) {
-			getTypeDefinitionInternal(repositoryId, typeId);
-			link = getTypeLink(repositoryId, typeId, rel, type);
-		}
-
-		return link;
-	}
-
-	/**
-	 * Adds a type link to the cache.
-	 */
-	protected void addTypeLink(String repositoryId, String typeId, String rel, String type, String link) {
-		getLinkCache().addTypeLink(repositoryId, typeId, rel, type, link);
-	}
-
-	/**
-	 * Adds a type link to the cache.
-	 */
-	protected void addTypeLink(String repositoryId, String typeId, AtomLink link) {
-		getLinkCache().addTypeLink(repositoryId, typeId, link.getRel(), link.getType(), link.getHref());
-	}
-
-	/**
-	 * Removes all links of a type.
-	 */
-	protected void removeTypeLinks(String repositoryId, String id) {
-		getLinkCache().removeTypeLinks(repositoryId, id);
-	}
-
-	/**
-	 * Locks the type link cache.
-	 */
-	protected void lockTypeLinks() {
-		getLinkCache().lockTypeLinks();
-	}
-
-	/**
-	 * Unlocks the type link cache.
-	 */
-	protected void unlockTypeLinks() {
-		getLinkCache().unlockTypeLinks();
-	}
-
-	/**
-	 * Gets a collection from the cache.
-	 */
-	protected String getCollection(String repositoryId, String collection) {
-		return getLinkCache().getCollection(repositoryId, collection);
-	}
-
-	/**
-	 * Gets a collection from the cache if it is there or loads it into the
-	 * cache if it is not there.
-	 */
-	protected String loadCollection(String repositoryId, String collection) {
-		String link = getCollection(repositoryId, collection);
-		if (link == null) {
-			// cache repository info
-			getRepositoriesInternal(repositoryId);
-			link = getCollection(repositoryId, collection);
-		}
-
-		return link;
-	}
-
-	/**
-	 * Adds a collection to the cache.
-	 */
-	protected void addCollection(String repositoryId, String collection, String link) {
-		getLinkCache().addCollection(repositoryId, collection, link);
-	}
-
-	/**
-	 * Gets a repository link from the cache.
-	 */
-	protected String getRepositoryLink(String repositoryId, String rel) {
-		return getLinkCache().getRepositoryLink(repositoryId, rel);
-	}
-
-	/**
-	 * Gets a repository link from the cache if it is there or loads it into the
-	 * cache if it is not there.
-	 */
-	protected String loadRepositoryLink(String repositoryId, String rel) {
-		String link = getRepositoryLink(repositoryId, rel);
-		if (link == null) {
-			// cache repository info
-			getRepositoriesInternal(repositoryId);
-			link = getRepositoryLink(repositoryId, rel);
-		}
-
-		return link;
-	}
-
-	/**
-	 * Adds a repository link to the cache.
-	 */
-	protected void addRepositoryLink(String repositoryId, String rel, String link) {
-		getLinkCache().addRepositoryLink(repositoryId, rel, link);
-	}
-
-	/**
-	 * Adds a repository link to the cache.
-	 */
-	protected void addRepositoryLink(String repositoryId, AtomLink link) {
-		addRepositoryLink(repositoryId, link.getRel(), link.getHref());
-	}
-
-	/**
-	 * Gets an URI template from the cache.
-	 */
-	protected String getTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
-		return getLinkCache().getTemplateLink(repositoryId, type, parameters);
-	}
-
-	/**
-	 * Gets a template link from the cache if it is there or loads it into the
-	 * cache if it is not there.
-	 */
-	protected String loadTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
-		String link = getTemplateLink(repositoryId, type, parameters);
-		if (link == null) {
-			// cache repository info
-			getRepositoriesInternal(repositoryId);
-			link = getTemplateLink(repositoryId, type, parameters);
-		}
-
-		return link;
-	}
-
-	/**
-	 * Adds an URI template to the cache.
-	 */
-	protected void addTemplate(String repositoryId, String type, String link) {
-		getLinkCache().addTemplate(repositoryId, type, link);
-	}
-
-	// ---- exceptions ----
-
-	/**
-	 * Converts a HTTP status code into an Exception.
-	 */
-	protected CmisBaseException convertStatusCode(int code, String message, String errorContent, Throwable t) {
-		switch (code) {
-		case 400:
-			return new CmisInvalidArgumentException(message, errorContent, t);
-		case 404:
-			return new CmisObjectNotFoundException(message, errorContent, t);
-		case 403:
-			return new CmisPermissionDeniedException(message, errorContent, t);
-		case 405:
-			return new CmisNotSupportedException(message, errorContent, t);
-		case 409:
-			return new CmisConstraintException(message, errorContent, t);
-		default:
-			return new CmisRuntimeException(message, errorContent, t);
-		}
-	}
-
-	// ---- helpers ----
-
-	protected boolean is(String name, AtomElement element) {
-		return name.equals(element.getName().getLocalPart());
-	}
-
-	protected boolean isStr(String name, AtomElement element) {
-		return is(name, element) && (element.getObject() instanceof String);
-	}
-
-	protected boolean isInt(String name, AtomElement element) {
-		return is(name, element) && (element.getObject() instanceof BigInteger);
-	}
-
-	protected boolean isNextLink(AtomElement element) {
-		return Constants.REL_NEXT.equals(((AtomLink) element.getObject()).getRel());
-	}
-
-	/**
-	 * Creates a CMIS object that only contains an id in the property list.
-	 */
-	protected CmisObjectType createIdObject(String objectId) {
-		CmisObjectType object = new CmisObjectType();
-
-		CmisPropertiesType properties = new CmisPropertiesType();
-		object.setProperties(properties);
-
-		CmisPropertyId idProperty = new CmisPropertyId();
-		properties.getProperty().add(idProperty);
-		idProperty.setPropertyDefinitionId(PropertyIds.OBJECT_ID);
-		idProperty.getValue().add(objectId);
-
-		return object;
-	}
-
-	/**
-	 * Parses an input stream.
-	 */
-	@SuppressWarnings("unchecked")
-	protected <T extends AtomBase> T parse(InputStream stream, Class<T> clazz) {
-		AtomPubParser parser = new AtomPubParser(stream);
-
-		try {
-			parser.parse();
-		} catch (Exception e) {
-			throw new CmisConnectionException("Parsing exception!", e);
-		}
-
-		AtomBase parseResult = parser.getResults();
-
-		if (!clazz.isInstance(parseResult)) {
-			throw new CmisConnectionException("Unexpected document! Received "
-					+ (parseResult == null ? "something unknown" : parseResult.getType()) + "!");
-		}
-
-		return (T) parseResult;
-	}
-
-	/**
-	 * Performs a GET on an URL, checks the response code and returns the
-	 * result.
-	 */
-	protected HttpUtils.Response read(UrlBuilder url) {
-		// make the call
-		HttpUtils.Response resp = HttpUtils.invokeGET(url, fSession);
-
-		// check response code
-		if (resp.getResponseCode() != 200) {
-			throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
-		}
-
-		return resp;
-	}
-
-	/**
-	 * Performs a POST on an URL, checks the response code and returns the
-	 * result.
-	 */
-	protected HttpUtils.Response post(UrlBuilder url, String contentType, HttpUtils.Output writer) {
-		// make the call
-		HttpUtils.Response resp = HttpUtils.invokePOST(url, contentType, writer, fSession);
-
-		// check response code
-		if (resp.getResponseCode() != 201) {
-			throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
-		}
-
-		return resp;
-	}
-
-	/**
-	 * Performs a PUT on an URL, checks the response code and returns the
-	 * result.
-	 */
-	protected HttpUtils.Response put(UrlBuilder url, String contentType, HttpUtils.Output writer) {
-		// make the call
-		HttpUtils.Response resp = HttpUtils.invokePUT(url, contentType, writer, fSession);
-
-		// check response code
-		if ((resp.getResponseCode() < 200) || (resp.getResponseCode() > 299)) {
-			throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
-		}
-
-		return resp;
-	}
-
-	/**
-	 * Performs a DELETE on an URL, checks the response code and returns the
-	 * result.
-	 */
-	protected void delete(UrlBuilder url) {
-		// make the call
-		HttpUtils.Response resp = HttpUtils.invokeDELETE(url, fSession);
-
-		// check response code
-		if (resp.getResponseCode() != 204) {
-			throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
-		}
-	}
-
-	// ---- common operations ----
-
-	/**
-	 * Checks if at least one ACE list is not empty.
-	 */
-	protected boolean isAclMergeRequired(Acl addAces, Acl removeAces) {
-		return (addAces != null && addAces.getAces() != null && !addAces.getAces().isEmpty())
-				|| (removeAces != null && removeAces.getAces() != null && !removeAces.getAces().isEmpty());
-	}
-
-	/**
-	 * Merges the new ACL from original, add and remove ACEs lists.
-	 */
-	protected Acl mergeAcls(Acl originalAces, Acl addAces, Acl removeAces) {
-		Map<String, Set<String>> originals = convertAclToMap(originalAces);
-		Map<String, Set<String>> adds = convertAclToMap(addAces);
-		Map<String, Set<String>> removes = convertAclToMap(removeAces);
-		List<Ace> newACEs = new ArrayList<Ace>();
-
-		// iterate through the original ACEs
-		for (Map.Entry<String, Set<String>> ace : originals.entrySet()) {
-
-			// add permissions
-			Set<String> addPermissions = adds.get(ace.getKey());
-			if (addPermissions != null) {
-				ace.getValue().addAll(addPermissions);
-			}
-
-			// remove permissions
-			Set<String> removePermissions = removes.get(ace.getKey());
-			if (removePermissions != null) {
-				ace.getValue().removeAll(removePermissions);
-			}
-
-			// create new ACE
-			if (!ace.getValue().isEmpty()) {
-				newACEs.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
-						new ArrayList<String>(ace.getValue())));
-			}
-		}
-
-		// find all ACEs that should be added but are not in the original ACE
-		// list
-		for (Map.Entry<String, Set<String>> ace : adds.entrySet()) {
-			if (!originals.containsKey(ace.getKey()) && !ace.getValue().isEmpty()) {
-				newACEs.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
-						new ArrayList<String>(ace.getValue())));
-			}
-		}
-
-		return new AccessControlListImpl(newACEs);
-	}
-
-	/**
-	 * Converts a list of ACEs into Map for better handling.
-	 */
-	private Map<String, Set<String>> convertAclToMap(Acl acl) {
-		Map<String, Set<String>> result = new HashMap<String, Set<String>>();
-
-		if ((acl == null) || (acl.getAces() == null)) {
-			return result;
-		}
-
-		for (Ace ace : acl.getAces()) {
-			// don't consider indirect ACEs - we can't change them
-			if (!ace.isDirect()) {
-				// ignore
-				continue;
-			}
-
-			// although a principal must not be null, check it
-			if ((ace.getPrincipal() == null) || (ace.getPrincipal().getId() == null)) {
-				// ignore
-				continue;
-			}
-
-			Set<String> permissions = new HashSet<String>();
-			if (ace.getPermissions() != null) {
-				permissions.addAll(ace.getPermissions());
-			}
-
-			result.put(ace.getPrincipal().getId(), permissions);
-		}
-
-		return result;
-	}
-
-	/**
-	 * Retrieves the Service Document from the server and caches the repository
-	 * info objects, collections, links, URI templates, etc.
-	 */
-	@SuppressWarnings("unchecked")
-	protected List<RepositoryInfo> getRepositoriesInternal(String repositoryId) {
-		List<RepositoryInfo> repInfos = new ArrayList<RepositoryInfo>();
-
-		// retrieve service doc
-		UrlBuilder url = new UrlBuilder(getServiceDocURL());
-		url.addParameter(Constants.PARAM_REPOSITORY_ID, repositoryId);
-
-		// read and parse
-		HttpUtils.Response resp = read(url);
-		ServiceDoc serviceDoc = parse(resp.getStream(), ServiceDoc.class);
-
-		// walk through the workspaces
-		for (RepositoryWorkspace ws : serviceDoc.getWorkspaces()) {
-			if (ws.getId() == null) {
-				// found a non-CMIS workspace
-				continue;
-			}
-
-			for (AtomElement element : ws.getElements()) {
-				if (is(NAME_COLLECTION, element)) {
-					Map<String, String> colMap = (Map<String, String>) element.getObject();
-					addCollection(ws.getId(), colMap.get("collectionType"), colMap.get("href"));
-				} else if (element.getObject() instanceof AtomLink) {
-					addRepositoryLink(ws.getId(), (AtomLink) element.getObject());
-				} else if (is(NAME_URI_TEMPLATE, element)) {
-					Map<String, String> tempMap = (Map<String, String>) element.getObject();
-					addTemplate(ws.getId(), tempMap.get("type"), tempMap.get("template"));
-				} else if (element.getObject() instanceof CmisRepositoryInfoType) {
-					repInfos.add(convert((CmisRepositoryInfoType) element.getObject()));
-				}
-			}
-		}
-
-		return repInfos;
-	}
-
-	/**
-	 * Retrieves an object from the server and caches the links.
-	 */
-	protected ObjectData getObjectInternal(String repositoryId, IdentifierType idOrPath, String objectIdOrPath,
-			ReturnVersion returnVersion, String filter, Boolean includeAllowableActions,
-			IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
-			Boolean includeAcl, ExtensionsData extension) {
-		ObjectData result = null;
-
-		Map<String, Object> parameters = new HashMap<String, Object>();
-		parameters.put(Constants.PARAM_ID, objectIdOrPath);
-		parameters.put(Constants.PARAM_PATH, objectIdOrPath);
-		parameters.put(Constants.PARAM_RETURN_VERSION, returnVersion);
-		parameters.put(Constants.PARAM_FILTER, filter);
-		parameters.put(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
-		parameters.put(Constants.PARAM_ACL, includeAcl);
-		parameters.put(Constants.PARAM_POLICY_IDS, includePolicyIds);
-		parameters.put(Constants.PARAM_RELATIONSHIPS, includeRelationships);
-		parameters.put(Constants.PARAM_RENDITION_FILTER, renditionFilter);
-
-		String link = loadTemplateLink(repositoryId, (idOrPath == IdentifierType.ID ? Constants.TEMPLATE_OBJECT_BY_ID
-				: Constants.TEMPLATE_OBJECT_BY_PATH), parameters);
-		if (link == null) {
-			throw new CmisObjectNotFoundException("Unknown repository!");
-		}
-
-		UrlBuilder url = new UrlBuilder(link);
-		// workaround for missing template parameter in the CMIS spec
-		if ((returnVersion != null) && (returnVersion != ReturnVersion.THIS)) {
-			url.addParameter(Constants.PARAM_RETURN_VERSION, returnVersion);
-		}
-
-		// read and parse
-		HttpUtils.Response resp = read(url);
-		AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
-
-		// we expect a CMIS entry
-		if (entry.getId() == null) {
-			throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
-		}
-
-		lockLinks();
-		try {
-			// clean up cache
-			removeLinks(repositoryId, entry.getId());
-
-			// walk through the entry
-			for (AtomElement element : entry.getElements()) {
-				if (element.getObject() instanceof AtomLink) {
-					addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
-				} else if (element.getObject() instanceof CmisObjectType) {
-					result = convert((CmisObjectType) element.getObject());
-				}
-			}
-		} finally {
-			unlockLinks();
-		}
-
-		return result;
-	}
-
-	/**
-	 * Retrieves a type definition.
-	 */
-	protected TypeDefinition getTypeDefinitionInternal(String repositoryId, String typeId) {
-		TypeDefinition result = null;
-
-		Map<String, Object> parameters = new HashMap<String, Object>();
-		parameters.put(Constants.PARAM_ID, typeId);
-
-		String link = loadTemplateLink(repositoryId, Constants.TEMPLATE_TYPE_BY_ID, parameters);
-		if (link == null) {
-			throw new CmisObjectNotFoundException("Unknown repository!");
-		}
-
-		// read and parse
-		HttpUtils.Response resp = read(new UrlBuilder(link));
-		AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
-
-		// we expect a CMIS entry
-		if (entry.getId() == null) {
-			throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
-		}
-
-		lockTypeLinks();
-		try {
-			// clean up cache
-			removeTypeLinks(repositoryId, entry.getId());
-
-			// walk through the entry
-			for (AtomElement element : entry.getElements()) {
-				if (element.getObject() instanceof AtomLink) {
-					addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
-				} else if (element.getObject() instanceof CmisTypeDefinitionType) {
-					result = convert((CmisTypeDefinitionType) element.getObject());
-				}
-			}
-		} finally {
-			unlockTypeLinks();
-		}
-
-		return result;
-	}
-
-	/**
-	 * Updates the ACL of an object.
-	 */
-	protected AtomAcl updateAcl(String repositoryId, String objectId, Acl acl, AclPropagation aclPropagation) {
-
-		// find the link
-		String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
-
-		if (link == null) {
-			throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
-		}
-
-		UrlBuilder aclUrl = new UrlBuilder(link);
-		aclUrl.addParameter(Constants.PARAM_ACL_PROPAGATION, aclPropagation);
-
-		// set up object and writer
-		final CmisAccessControlListType aclJaxb = convert(acl);
-
-		// update
-		HttpUtils.Response resp = put(aclUrl, Constants.MEDIATYPE_ACL, new HttpUtils.Output() {
-			public void write(OutputStream out) throws Exception {
-				JaxBHelper.marshal(JaxBHelper.CMIS_OBJECT_FACTORY.createAcl(aclJaxb), out, false);
-			}
-		});
-
-		// parse new entry
-		return parse(resp.getStream(), AtomAcl.class);
-	}
+    protected enum IdentifierType {
+        ID, PATH
+    };
+
+    protected static final String NAME_COLLECTION = "collection";
+    protected static final String NAME_URI_TEMPLATE = "uritemplate";
+    protected static final String NAME_PATH_SEGMENT = "pathSegment";
+    protected static final String NAME_RELATIVE_PATH_SEGMENT = "relativePathSegment";
+    protected static final String NAME_NUM_ITEMS = "numItems";
+
+    private Session fSession;
+
+    /**
+     * Sets the current session.
+     */
+    protected void setSession(Session session) {
+        fSession = session;
+    }
+
+    /**
+     * Gets the current session.
+     */
+    protected Session getSession() {
+        return fSession;
+    }
+
+    /**
+     * Returns the service document URL of this session.
+     */
+    protected String getServiceDocURL() {
+        Object url = fSession.get(SessionParameter.ATOMPUB_URL);
+        if (url instanceof String) {
+            return (String) url;
+        }
+
+        return null;
+    }
+
+    // ---- link cache ----
+
+    /**
+     * Returns the link cache or creates a new cache if it doesn't exist.
+     */
+    protected LinkCache getLinkCache() {
+        LinkCache linkCache = (LinkCache) getSession().get(SpiSessionParameter.LINK_CACHE);
+        if (linkCache == null) {
+            linkCache = new LinkCache(getSession());
+            getSession().put(SpiSessionParameter.LINK_CACHE, linkCache);
+        }
+
+        return linkCache;
+    }
+
+    /**
+     * Gets a link from the cache.
+     */
+    protected String getLink(String repositoryId, String id, String rel, String type) {
+        if (repositoryId == null) {
+            throw new CmisInvalidArgumentException("Repository id must be set!");
+        }
+
+        if (id == null) {
+            throw new CmisInvalidArgumentException("Object id must be set!");
+        }
+
+        return getLinkCache().getLink(repositoryId, id, rel, type);
+    }
+
+    /**
+     * Gets a link from the cache.
+     */
+    protected String getLink(String repositoryId, String id, String rel) {
+        return getLink(repositoryId, id, rel, null);
+    }
+
+    /**
+     * Gets a link from the cache if it is there or loads it into the cache if
+     * it is not there.
+     */
+    protected String loadLink(String repositoryId, String id, String rel, String type) {
+        String link = getLink(repositoryId, id, rel, type);
+        if (link == null) {
+            getObjectInternal(repositoryId, IdentifierType.ID, id, ReturnVersion.THIS, null, null, null, null, null,
+                    null, null);
+            link = getLink(repositoryId, id, rel, type);
+        }
+
+        return link;
+    }
+
+    /**
+     * Adds a link to the cache.
+     */
+    protected void addLink(String repositoryId, String id, String rel, String type, String link) {
+        getLinkCache().addLink(repositoryId, id, rel, type, link);
+    }
+
+    /**
+     * Adds a link to the cache.
+     */
+    protected void addLink(String repositoryId, String id, AtomLink link) {
+        getLinkCache().addLink(repositoryId, id, link.getRel(), link.getType(), link.getHref());
+    }
+
+    /**
+     * Removes all links of an object.
+     */
+    protected void removeLinks(String repositoryId, String id) {
+        getLinkCache().removeLinks(repositoryId, id);
+    }
+
+    /**
+     * Locks the link cache.
+     */
+    protected void lockLinks() {
+        getLinkCache().lockLinks();
+    }
+
+    /**
+     * Unlocks the link cache.
+     */
+    protected void unlockLinks() {
+        getLinkCache().unlockLinks();
+    }
+
+    /**
+     * Checks a link throw an appropriate exception.
+     */
+    protected void throwLinkException(String repositoryId, String id, String rel, String type) {
+        int index = getLinkCache().checkLink(repositoryId, id, rel, type);
+
+        switch (index) {
+        case 0:
+            throw new CmisObjectNotFoundException("Unknown repository!");
+        case 1:
+            throw new CmisObjectNotFoundException("Unknown object!");
+        case 2:
+            throw new CmisNotSupportedException("Operation not supported by the repository for this object!");
+        case 3:
+            throw new CmisNotSupportedException("No link with matching media type!");
+        case 4:
+            throw new CmisRuntimeException("Nothing wrong! Either this is a bug or threading issue.");
+        default:
+            throw new CmisRuntimeException("Unknown error!");
+        }
+    }
+
+    /**
+     * Gets a type link from the cache.
+     */
+    protected String getTypeLink(String repositoryId, String typeId, String rel, String type) {
+        if (repositoryId == null) {
+            throw new CmisInvalidArgumentException("Repository id must be set!");
+        }
+
+        if (typeId == null) {
+            throw new CmisInvalidArgumentException("Type id must be set!");
+        }
+
+        return getLinkCache().getTypeLink(repositoryId, typeId, rel, type);
+    }
+
+    /**
+     * Gets a type link from the cache.
+     */
+    protected String getTypeLink(String repositoryId, String typeId, String rel) {
+        return getTypeLink(repositoryId, typeId, rel, null);
+    }
+
+    /**
+     * Gets a link from the cache if it is there or loads it into the cache if
+     * it is not there.
+     */
+    protected String loadTypeLink(String repositoryId, String typeId, String rel, String type) {
+        String link = getTypeLink(repositoryId, typeId, rel, type);
+        if (link == null) {
+            getTypeDefinitionInternal(repositoryId, typeId);
+            link = getTypeLink(repositoryId, typeId, rel, type);
+        }
+
+        return link;
+    }
+
+    /**
+     * Adds a type link to the cache.
+     */
+    protected void addTypeLink(String repositoryId, String typeId, String rel, String type, String link) {
+        getLinkCache().addTypeLink(repositoryId, typeId, rel, type, link);
+    }
+
+    /**
+     * Adds a type link to the cache.
+     */
+    protected void addTypeLink(String repositoryId, String typeId, AtomLink link) {
+        getLinkCache().addTypeLink(repositoryId, typeId, link.getRel(), link.getType(), link.getHref());
+    }
+
+    /**
+     * Removes all links of a type.
+     */
+    protected void removeTypeLinks(String repositoryId, String id) {
+        getLinkCache().removeTypeLinks(repositoryId, id);
+    }
+
+    /**
+     * Locks the type link cache.
+     */
+    protected void lockTypeLinks() {
+        getLinkCache().lockTypeLinks();
+    }
+
+    /**
+     * Unlocks the type link cache.
+     */
+    protected void unlockTypeLinks() {
+        getLinkCache().unlockTypeLinks();
+    }
+
+    /**
+     * Gets a collection from the cache.
+     */
+    protected String getCollection(String repositoryId, String collection) {
+        return getLinkCache().getCollection(repositoryId, collection);
+    }
+
+    /**
+     * Gets a collection from the cache if it is there or loads it into the
+     * cache if it is not there.
+     */
+    protected String loadCollection(String repositoryId, String collection) {
+        String link = getCollection(repositoryId, collection);
+        if (link == null) {
+            // cache repository info
+            getRepositoriesInternal(repositoryId);
+            link = getCollection(repositoryId, collection);
+        }
+
+        return link;
+    }
+
+    /**
+     * Adds a collection to the cache.
+     */
+    protected void addCollection(String repositoryId, String collection, String link) {
+        getLinkCache().addCollection(repositoryId, collection, link);
+    }
+
+    /**
+     * Gets a repository link from the cache.
+     */
+    protected String getRepositoryLink(String repositoryId, String rel) {
+        return getLinkCache().getRepositoryLink(repositoryId, rel);
+    }
+
+    /**
+     * Gets a repository link from the cache if it is there or loads it into the
+     * cache if it is not there.
+     */
+    protected String loadRepositoryLink(String repositoryId, String rel) {
+        String link = getRepositoryLink(repositoryId, rel);
+        if (link == null) {
+            // cache repository info
+            getRepositoriesInternal(repositoryId);
+            link = getRepositoryLink(repositoryId, rel);
+        }
+
+        return link;
+    }
+
+    /**
+     * Adds a repository link to the cache.
+     */
+    protected void addRepositoryLink(String repositoryId, String rel, String link) {
+        getLinkCache().addRepositoryLink(repositoryId, rel, link);
+    }
+
+    /**
+     * Adds a repository link to the cache.
+     */
+    protected void addRepositoryLink(String repositoryId, AtomLink link) {
+        addRepositoryLink(repositoryId, link.getRel(), link.getHref());
+    }
+
+    /**
+     * Gets an URI template from the cache.
+     */
+    protected String getTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
+        return getLinkCache().getTemplateLink(repositoryId, type, parameters);
+    }
+
+    /**
+     * Gets a template link from the cache if it is there or loads it into the
+     * cache if it is not there.
+     */
+    protected String loadTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
+        String link = getTemplateLink(repositoryId, type, parameters);
+        if (link == null) {
+            // cache repository info
+            getRepositoriesInternal(repositoryId);
+            link = getTemplateLink(repositoryId, type, parameters);
+        }
+
+        return link;
+    }
+
+    /**
+     * Adds an URI template to the cache.
+     */
+    protected void addTemplate(String repositoryId, String type, String link) {
+        getLinkCache().addTemplate(repositoryId, type, link);
+    }
+
+    // ---- exceptions ----
+
+    /**
+     * Converts a HTTP status code into an Exception.
+     */
+    protected CmisBaseException convertStatusCode(int code, String message, String errorContent, Throwable t) {
+        switch (code) {
+        case 400:
+            return new CmisInvalidArgumentException(message, errorContent, t);
+        case 404:
+            return new CmisObjectNotFoundException(message, errorContent, t);
+        case 403:
+            return new CmisPermissionDeniedException(message, errorContent, t);
+        case 405:
+            return new CmisNotSupportedException(message, errorContent, t);
+        case 409:
+            return new CmisConstraintException(message, errorContent, t);
+        default:
+            return new CmisRuntimeException(message, errorContent, t);
+        }
+    }
+
+    // ---- helpers ----
+
+    protected boolean is(String name, AtomElement element) {
+        return name.equals(element.getName().getLocalPart());
+    }
+
+    protected boolean isStr(String name, AtomElement element) {
+        return is(name, element) && (element.getObject() instanceof String);
+    }
+
+    protected boolean isInt(String name, AtomElement element) {
+        return is(name, element) && (element.getObject() instanceof BigInteger);
+    }
+
+    protected boolean isNextLink(AtomElement element) {
+        return Constants.REL_NEXT.equals(((AtomLink) element.getObject()).getRel());
+    }
+
+    /**
+     * Creates a CMIS object that only contains an id in the property list.
+     */
+    protected CmisObjectType createIdObject(String objectId) {
+        CmisObjectType object = new CmisObjectType();
+
+        CmisPropertiesType properties = new CmisPropertiesType();
+        object.setProperties(properties);
+
+        CmisPropertyId idProperty = new CmisPropertyId();
+        properties.getProperty().add(idProperty);
+        idProperty.setPropertyDefinitionId(PropertyIds.OBJECT_ID);
+        idProperty.getValue().add(objectId);
+
+        return object;
+    }
+
+    /**
+     * Parses an input stream.
+     */
+    @SuppressWarnings("unchecked")
+    protected <T extends AtomBase> T parse(InputStream stream, Class<T> clazz) {
+        AtomPubParser parser = new AtomPubParser(stream);
+
+        try {
+            parser.parse();
+        } catch (Exception e) {
+            throw new CmisConnectionException("Parsing exception!", e);
+        }
+
+        AtomBase parseResult = parser.getResults();
+
+        if (!clazz.isInstance(parseResult)) {
+            throw new CmisConnectionException("Unexpected document! Received "
+                    + (parseResult == null ? "something unknown" : parseResult.getType()) + "!");
+        }
+
+        return (T) parseResult;
+    }
+
+    /**
+     * Performs a GET on an URL, checks the response code and returns the
+     * result.
+     */
+    protected HttpUtils.Response read(UrlBuilder url) {
+        // make the call
+        HttpUtils.Response resp = HttpUtils.invokeGET(url, fSession);
+
+        // check response code
+        if (resp.getResponseCode() != 200) {
+            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
+        }
+
+        return resp;
+    }
+
+    /**
+     * Performs a POST on an URL, checks the response code and returns the
+     * result.
+     */
+    protected HttpUtils.Response post(UrlBuilder url, String contentType, HttpUtils.Output writer) {
+        // make the call
+        HttpUtils.Response resp = HttpUtils.invokePOST(url, contentType, writer, fSession);
+
+        // check response code
+        if (resp.getResponseCode() != 201) {
+            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
+        }
+
+        return resp;
+    }
+
+    /**
+     * Performs a PUT on an URL, checks the response code and returns the
+     * result.
+     */
+    protected HttpUtils.Response put(UrlBuilder url, String contentType, HttpUtils.Output writer) {
+        // make the call
+        HttpUtils.Response resp = HttpUtils.invokePUT(url, contentType, writer, fSession);
+
+        // check response code
+        if ((resp.getResponseCode() < 200) || (resp.getResponseCode() > 299)) {
+            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
+        }
+
+        return resp;
+    }
+
+    /**
+     * Performs a DELETE on an URL, checks the response code and returns the
+     * result.
+     */
+    protected void delete(UrlBuilder url) {
+        // make the call
+        HttpUtils.Response resp = HttpUtils.invokeDELETE(url, fSession);
+
+        // check response code
+        if (resp.getResponseCode() != 204) {
+            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
+        }
+    }
+
+    // ---- common operations ----
+
+    /**
+     * Checks if at least one ACE list is not empty.
+     */
+    protected boolean isAclMergeRequired(Acl addAces, Acl removeAces) {
+        return (addAces != null && addAces.getAces() != null && !addAces.getAces().isEmpty())
+                || (removeAces != null && removeAces.getAces() != null && !removeAces.getAces().isEmpty());
+    }
+
+    /**
+     * Merges the new ACL from original, add and remove ACEs lists.
+     */
+    protected Acl mergeAcls(Acl originalAces, Acl addAces, Acl removeAces) {
+        Map<String, Set<String>> originals = convertAclToMap(originalAces);
+        Map<String, Set<String>> adds = convertAclToMap(addAces);
+        Map<String, Set<String>> removes = convertAclToMap(removeAces);
+        List<Ace> newACEs = new ArrayList<Ace>();
+
+        // iterate through the original ACEs
+        for (Map.Entry<String, Set<String>> ace : originals.entrySet()) {
+
+            // add permissions
+            Set<String> addPermissions = adds.get(ace.getKey());
+            if (addPermissions != null) {
+                ace.getValue().addAll(addPermissions);
+            }
+
+            // remove permissions
+            Set<String> removePermissions = removes.get(ace.getKey());
+            if (removePermissions != null) {
+                ace.getValue().removeAll(removePermissions);
+            }
+
+            // create new ACE
+            if (!ace.getValue().isEmpty()) {
+                newACEs.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
+                        new ArrayList<String>(ace.getValue())));
+            }
+        }
+
+        // find all ACEs that should be added but are not in the original ACE
+        // list
+        for (Map.Entry<String, Set<String>> ace : adds.entrySet()) {
+            if (!originals.containsKey(ace.getKey()) && !ace.getValue().isEmpty()) {
+                newACEs.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
+                        new ArrayList<String>(ace.getValue())));
+            }
+        }
+
+        return new AccessControlListImpl(newACEs);
+    }
+
+    /**
+     * Converts a list of ACEs into Map for better handling.
+     */
+    private Map<String, Set<String>> convertAclToMap(Acl acl) {
+        Map<String, Set<String>> result = new HashMap<String, Set<String>>();
+
+        if ((acl == null) || (acl.getAces() == null)) {
+            return result;
+        }
+
+        for (Ace ace : acl.getAces()) {
+            // don't consider indirect ACEs - we can't change them
+            if (!ace.isDirect()) {
+                // ignore
+                continue;
+            }
+
+            // although a principal must not be null, check it
+            if ((ace.getPrincipal() == null) || (ace.getPrincipal().getId() == null)) {
+                // ignore
+                continue;
+            }
+
+            Set<String> permissions = new HashSet<String>();
+            if (ace.getPermissions() != null) {
+                permissions.addAll(ace.getPermissions());
+            }
+
+            result.put(ace.getPrincipal().getId(), permissions);
+        }
+
+        return result;
+    }
+
+    /**
+     * Retrieves the Service Document from the server and caches the repository
+     * info objects, collections, links, URI templates, etc.
+     */
+    @SuppressWarnings("unchecked")
+    protected List<RepositoryInfo> getRepositoriesInternal(String repositoryId) {
+        List<RepositoryInfo> repInfos = new ArrayList<RepositoryInfo>();
+
+        // retrieve service doc
+        UrlBuilder url = new UrlBuilder(getServiceDocURL());
+        url.addParameter(Constants.PARAM_REPOSITORY_ID, repositoryId);
+
+        // read and parse
+        HttpUtils.Response resp = read(url);
+        ServiceDoc serviceDoc = parse(resp.getStream(), ServiceDoc.class);
+
+        // walk through the workspaces
+        for (RepositoryWorkspace ws : serviceDoc.getWorkspaces()) {
+            if (ws.getId() == null) {
+                // found a non-CMIS workspace
+                continue;
+            }
+
+            for (AtomElement element : ws.getElements()) {
+                if (is(NAME_COLLECTION, element)) {
+                    Map<String, String> colMap = (Map<String, String>) element.getObject();
+                    addCollection(ws.getId(), colMap.get("collectionType"), colMap.get("href"));
+                } else if (element.getObject() instanceof AtomLink) {
+                    addRepositoryLink(ws.getId(), (AtomLink) element.getObject());
+                } else if (is(NAME_URI_TEMPLATE, element)) {
+                    Map<String, String> tempMap = (Map<String, String>) element.getObject();
+                    addTemplate(ws.getId(), tempMap.get("type"), tempMap.get("template"));
+                } else if (element.getObject() instanceof CmisRepositoryInfoType) {
+                    repInfos.add(convert((CmisRepositoryInfoType) element.getObject()));
+                }
+            }
+        }
+
+        return repInfos;
+    }
+
+    /**
+     * Retrieves an object from the server and caches the links.
+     */
+    protected ObjectData getObjectInternal(String repositoryId, IdentifierType idOrPath, String objectIdOrPath,
+            ReturnVersion returnVersion, String filter, Boolean includeAllowableActions,
+            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
+            Boolean includeAcl, ExtensionsData extension) {
+        ObjectData result = null;
+
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        parameters.put(Constants.PARAM_ID, objectIdOrPath);
+        parameters.put(Constants.PARAM_PATH, objectIdOrPath);
+        parameters.put(Constants.PARAM_RETURN_VERSION, returnVersion);
+        parameters.put(Constants.PARAM_FILTER, filter);
+        parameters.put(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+        parameters.put(Constants.PARAM_ACL, includeAcl);
+        parameters.put(Constants.PARAM_POLICY_IDS, includePolicyIds);
+        parameters.put(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+        parameters.put(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+
+        String link = loadTemplateLink(repositoryId, (idOrPath == IdentifierType.ID ? Constants.TEMPLATE_OBJECT_BY_ID
+                : Constants.TEMPLATE_OBJECT_BY_PATH), parameters);
+        if (link == null) {
+            throw new CmisObjectNotFoundException("Unknown repository!");
+        }
+
+        UrlBuilder url = new UrlBuilder(link);
+        // workaround for missing template parameter in the CMIS spec
+        if ((returnVersion != null) && (returnVersion != ReturnVersion.THIS)) {
+            url.addParameter(Constants.PARAM_RETURN_VERSION, returnVersion);
+        }
+
+        // read and parse
+        HttpUtils.Response resp = read(url);
+        AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+        // we expect a CMIS entry
+        if (entry.getId() == null) {
+            throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
+        }
+
+        lockLinks();
+        try {
+            // clean up cache
+            removeLinks(repositoryId, entry.getId());
+
+            // walk through the entry
+            for (AtomElement element : entry.getElements()) {
+                if (element.getObject() instanceof AtomLink) {
+                    addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+                } else if (element.getObject() instanceof CmisObjectType) {
+                    result = convert((CmisObjectType) element.getObject());
+                }
+            }
+        } finally {
+            unlockLinks();
+        }
+
+        return result;
+    }
+
+    /**
+     * Retrieves a type definition.
+     */
+    protected TypeDefinition getTypeDefinitionInternal(String repositoryId, String typeId) {
+        TypeDefinition result = null;
+
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        parameters.put(Constants.PARAM_ID, typeId);
+
+        String link = loadTemplateLink(repositoryId, Constants.TEMPLATE_TYPE_BY_ID, parameters);
+        if (link == null) {
+            throw new CmisObjectNotFoundException("Unknown repository!");
+        }
+
+        // read and parse
+        HttpUtils.Response resp = read(new UrlBuilder(link));
+        AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+        // we expect a CMIS entry
+        if (entry.getId() == null) {
+            throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
+        }
+
+        lockTypeLinks();
+        try {
+            // clean up cache
+            removeTypeLinks(repositoryId, entry.getId());
+
+            // walk through the entry
+            for (AtomElement element : entry.getElements()) {
+                if (element.getObject() instanceof AtomLink) {
+                    addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+                } else if (element.getObject() instanceof CmisTypeDefinitionType) {
+                    result = convert((CmisTypeDefinitionType) element.getObject());
+                }
+            }
+        } finally {
+            unlockTypeLinks();
+        }
+
+        return result;
+    }
+
+    /**
+     * Updates the ACL of an object.
+     */
+    protected AtomAcl updateAcl(String repositoryId, String objectId, Acl acl, AclPropagation aclPropagation) {
+
+        // find the link
+        String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+
+        if (link == null) {
+            throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+        }
+
+        UrlBuilder aclUrl = new UrlBuilder(link);
+        aclUrl.addParameter(Constants.PARAM_ACL_PROPAGATION, aclPropagation);
+
+        // set up object and writer
+        final CmisAccessControlListType aclJaxb = convert(acl);
+
+        // update
+        HttpUtils.Response resp = put(aclUrl, Constants.MEDIATYPE_ACL, new HttpUtils.Output() {
+            public void write(OutputStream out) throws Exception {
+                JaxBHelper.marshal(JaxBHelper.CMIS_OBJECT_FACTORY.createAcl(aclJaxb), out, false);
+            }
+        });
+
+        // parse new entry
+        return parse(resp.getStream(), AtomAcl.class);
+    }
 
 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java?rev=936922&r1=936921&r2=936922&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java Thu Apr 22 16:04:19 2010
@@ -37,71 +37,71 @@ import org.apache.chemistry.opencmis.com
  */
 public class AclServiceImpl extends AbstractAtomPubService implements AclService {
 
-	/**
-	 * Constructor.
-	 */
-	public AclServiceImpl(Session session) {
-		setSession(session);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.provider.ACLService#applyACL(java.lang.String,
-	 * java.lang.String, org.apache.opencmis.client.provider.AccessControlList,
-	 * org.apache.opencmis.client.provider.AccessControlList,
-	 * org.apache.opencmis.commons.enums.ACLPropagation,
-	 * org.apache.opencmis.client.provider.ExtensionsData)
-	 */
-	public Acl applyAcl(String repositoryId, String objectId, Acl addAces, Acl removeAces,
-			AclPropagation aclPropagation, ExtensionsData extension) {
-		Acl result = null;
-
-		// fetch the current ACL
-		Acl originalAces = getAcl(repositoryId, objectId, false, null);
-
-		// if no changes required, just return the ACL
-		if (!isAclMergeRequired(addAces, removeAces)) {
-			return originalAces;
-		}
-
-		// merge ACLs
-		Acl newACL = mergeAcls(originalAces, addAces, removeAces);
-
-		// update ACL
-		AtomAcl acl = updateAcl(repositoryId, objectId, newACL, aclPropagation);
-		result = convert(acl.getACL(), null);
-
-		return result;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.provider.ACLService#getACL(java.lang.String,
-	 * java.lang.String, java.lang.Boolean,
-	 * org.apache.opencmis.client.provider.ExtensionsData)
-	 */
-	public org.apache.chemistry.opencmis.commons.api.Acl getAcl(String repositoryId, String objectId,
-			Boolean onlyBasicPermissions, ExtensionsData extension) {
-
-		// find the link
-		String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
-
-		if (link == null) {
-			throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
-		}
-
-		UrlBuilder url = new UrlBuilder(link);
-		url.addParameter(Constants.PARAM_ONLY_BASIC_PERMISSIONS, onlyBasicPermissions);
-
-		// read and parse
-		HttpUtils.Response resp = read(url);
-		AtomAcl acl = parse(resp.getStream(), AtomAcl.class);
+    /**
+     * Constructor.
+     */
+    public AclServiceImpl(Session session) {
+        setSession(session);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.provider.ACLService#applyACL(java.lang.String,
+     * java.lang.String, org.apache.opencmis.client.provider.AccessControlList,
+     * org.apache.opencmis.client.provider.AccessControlList,
+     * org.apache.opencmis.commons.enums.ACLPropagation,
+     * org.apache.opencmis.client.provider.ExtensionsData)
+     */
+    public Acl applyAcl(String repositoryId, String objectId, Acl addAces, Acl removeAces,
+            AclPropagation aclPropagation, ExtensionsData extension) {
+        Acl result = null;
+
+        // fetch the current ACL
+        Acl originalAces = getAcl(repositoryId, objectId, false, null);
+
+        // if no changes required, just return the ACL
+        if (!isAclMergeRequired(addAces, removeAces)) {
+            return originalAces;
+        }
+
+        // merge ACLs
+        Acl newACL = mergeAcls(originalAces, addAces, removeAces);
+
+        // update ACL
+        AtomAcl acl = updateAcl(repositoryId, objectId, newACL, aclPropagation);
+        result = convert(acl.getACL(), null);
+
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.provider.ACLService#getACL(java.lang.String,
+     * java.lang.String, java.lang.Boolean,
+     * org.apache.opencmis.client.provider.ExtensionsData)
+     */
+    public org.apache.chemistry.opencmis.commons.api.Acl getAcl(String repositoryId, String objectId,
+            Boolean onlyBasicPermissions, ExtensionsData extension) {
+
+        // find the link
+        String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+
+        if (link == null) {
+            throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+        }
+
+        UrlBuilder url = new UrlBuilder(link);
+        url.addParameter(Constants.PARAM_ONLY_BASIC_PERMISSIONS, onlyBasicPermissions);
+
+        // read and parse
+        HttpUtils.Response resp = read(url);
+        AtomAcl acl = parse(resp.getStream(), AtomAcl.class);
 
-		return convert(acl.getACL(), null);
-	}
+        return convert(acl.getACL(), null);
+    }
 
 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AtomEntryWriter.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AtomEntryWriter.java?rev=936922&r1=936921&r2=936922&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AtomEntryWriter.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AtomEntryWriter.java Thu Apr 22 16:04:19 2010
@@ -45,133 +45,133 @@ import org.apache.commons.codec.binary.B
  */
 public class AtomEntryWriter implements CmisAtomPubConstants {
 
-	private static final String PREFIX_ATOM = "atom";
-	private static final String PREFIX_CMIS = "cmis";
-	private static final String PREFIX_RESTATOM = "cmisra";
-
-	private static final int BUFFER_SIZE = 4096;
-
-	private CmisObjectType fObject;
-	private InputStream fStream;
-	private String fMediaType;
-
-	/**
-	 * Constructor.
-	 */
-	public AtomEntryWriter(CmisObjectType object) {
-		this(object, null, null);
-	}
-
-	/**
-	 * Constructor.
-	 */
-	public AtomEntryWriter(CmisObjectType object, String mediaType, InputStream stream) {
-		if ((object == null) || (object.getProperties() == null)) {
-			throw new CmisInvalidArgumentException("Object and properties must not be null!");
-		}
-
-		if ((stream != null) && (mediaType == null)) {
-			throw new CmisInvalidArgumentException("Media type must be set if a stream is present!");
-		}
-
-		fObject = object;
-		fMediaType = mediaType;
-		fStream = stream;
-	}
-
-	/**
-	 * Writes the entry to an output stream.
-	 */
-	public void write(OutputStream out) throws Exception {
-		XMLOutputFactory factory = XMLOutputFactory.newInstance();
-		XMLStreamWriter writer = factory.createXMLStreamWriter(out, "UTF-8");
-
-		writer.setPrefix(PREFIX_ATOM, Constants.NAMESPACE_ATOM);
-		writer.setPrefix(PREFIX_CMIS, Constants.NAMESPACE_CMIS);
-		writer.setPrefix(PREFIX_RESTATOM, Constants.NAMESPACE_RESTATOM);
-
-		// start doc
-		writer.writeStartDocument();
-
-		// start entry
-		writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ENTRY);
-		writer.writeNamespace(PREFIX_ATOM, Constants.NAMESPACE_ATOM);
-		writer.writeNamespace(PREFIX_CMIS, Constants.NAMESPACE_CMIS);
-		writer.writeNamespace(PREFIX_RESTATOM, Constants.NAMESPACE_RESTATOM);
-
-		// atom:id
-		writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ATOM_ID);
-		writer.writeCharacters("urn:uuid:00000000-0000-0000-0000-00000000000");
-		writer.writeEndElement();
-
-		// atom:title
-		writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ATOM_TITLE);
-		writer.writeCharacters(getTitle());
-		writer.writeEndElement();
-
-		// atom:updated
-		writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ATOM_UPDATED);
-		writer.writeCharacters(getUpdated());
-		writer.writeEndElement();
-
-		// content
-		if (fStream != null) {
-			writer.writeStartElement(Constants.NAMESPACE_RESTATOM, TAG_CONTENT);
-
-			writer.writeStartElement(Constants.NAMESPACE_RESTATOM, TAG_CONTENT_MEDIATYPE);
-			writer.writeCharacters(fMediaType);
-			writer.writeEndElement();
-
-			writer.writeStartElement(Constants.NAMESPACE_RESTATOM, TAG_CONTENT_BASE64);
-			writer.writeCharacters(getContent());
-			writer.writeEndElement();
-
-			writer.writeEndElement();
-		}
-
-		// object
-		JaxBHelper.marshal(JaxBHelper.CMIS_EXTRA_OBJECT_FACTORY.createObject(fObject), writer, true);
-
-		// end entry
-		writer.writeEndElement();
-
-		// end document
-		writer.writeEndDocument();
-
-		writer.flush();
-	}
-
-	// ---- internal ----
-
-	private String getTitle() {
-		String result = "";
-
-		for (CmisProperty property : fObject.getProperties().getProperty()) {
-			if (PropertyIds.NAME.equals(property.getPropertyDefinitionId()) && (property instanceof CmisPropertyString)) {
-				List<String> values = ((CmisPropertyString) property).getValue();
-				if (!values.isEmpty()) {
-					return values.get(0);
-				}
-			}
-		}
-
-		return result;
-	}
-
-	private String getUpdated() {
-		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-		return sdf.format(new Date());
-	}
-
-	private String getContent() throws Exception {
-		ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
-		byte[] buffer = new byte[BUFFER_SIZE];
-		int b;
-		while ((b = fStream.read(buffer)) > -1) {
-			baos.write(buffer, 0, b);
-		}
+    private static final String PREFIX_ATOM = "atom";
+    private static final String PREFIX_CMIS = "cmis";
+    private static final String PREFIX_RESTATOM = "cmisra";
+
+    private static final int BUFFER_SIZE = 4096;
+
+    private CmisObjectType fObject;
+    private InputStream fStream;
+    private String fMediaType;
+
+    /**
+     * Constructor.
+     */
+    public AtomEntryWriter(CmisObjectType object) {
+        this(object, null, null);
+    }
+
+    /**
+     * Constructor.
+     */
+    public AtomEntryWriter(CmisObjectType object, String mediaType, InputStream stream) {
+        if ((object == null) || (object.getProperties() == null)) {
+            throw new CmisInvalidArgumentException("Object and properties must not be null!");
+        }
+
+        if ((stream != null) && (mediaType == null)) {
+            throw new CmisInvalidArgumentException("Media type must be set if a stream is present!");
+        }
+
+        fObject = object;
+        fMediaType = mediaType;
+        fStream = stream;
+    }
+
+    /**
+     * Writes the entry to an output stream.
+     */
+    public void write(OutputStream out) throws Exception {
+        XMLOutputFactory factory = XMLOutputFactory.newInstance();
+        XMLStreamWriter writer = factory.createXMLStreamWriter(out, "UTF-8");
+
+        writer.setPrefix(PREFIX_ATOM, Constants.NAMESPACE_ATOM);
+        writer.setPrefix(PREFIX_CMIS, Constants.NAMESPACE_CMIS);
+        writer.setPrefix(PREFIX_RESTATOM, Constants.NAMESPACE_RESTATOM);
+
+        // start doc
+        writer.writeStartDocument();
+
+        // start entry
+        writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ENTRY);
+        writer.writeNamespace(PREFIX_ATOM, Constants.NAMESPACE_ATOM);
+        writer.writeNamespace(PREFIX_CMIS, Constants.NAMESPACE_CMIS);
+        writer.writeNamespace(PREFIX_RESTATOM, Constants.NAMESPACE_RESTATOM);
+
+        // atom:id
+        writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ATOM_ID);
+        writer.writeCharacters("urn:uuid:00000000-0000-0000-0000-00000000000");
+        writer.writeEndElement();
+
+        // atom:title
+        writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ATOM_TITLE);
+        writer.writeCharacters(getTitle());
+        writer.writeEndElement();
+
+        // atom:updated
+        writer.writeStartElement(Constants.NAMESPACE_ATOM, TAG_ATOM_UPDATED);
+        writer.writeCharacters(getUpdated());
+        writer.writeEndElement();
+
+        // content
+        if (fStream != null) {
+            writer.writeStartElement(Constants.NAMESPACE_RESTATOM, TAG_CONTENT);
+
+            writer.writeStartElement(Constants.NAMESPACE_RESTATOM, TAG_CONTENT_MEDIATYPE);
+            writer.writeCharacters(fMediaType);
+            writer.writeEndElement();
+
+            writer.writeStartElement(Constants.NAMESPACE_RESTATOM, TAG_CONTENT_BASE64);
+            writer.writeCharacters(getContent());
+            writer.writeEndElement();
+
+            writer.writeEndElement();
+        }
+
+        // object
+        JaxBHelper.marshal(JaxBHelper.CMIS_EXTRA_OBJECT_FACTORY.createObject(fObject), writer, true);
+
+        // end entry
+        writer.writeEndElement();
+
+        // end document
+        writer.writeEndDocument();
+
+        writer.flush();
+    }
+
+    // ---- internal ----
+
+    private String getTitle() {
+        String result = "";
+
+        for (CmisProperty property : fObject.getProperties().getProperty()) {
+            if (PropertyIds.NAME.equals(property.getPropertyDefinitionId()) && (property instanceof CmisPropertyString)) {
+                List<String> values = ((CmisPropertyString) property).getValue();
+                if (!values.isEmpty()) {
+                    return values.get(0);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private String getUpdated() {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+        return sdf.format(new Date());
+    }
+
+    private String getContent() throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        byte[] buffer = new byte[BUFFER_SIZE];
+        int b;
+        while ((b = fStream.read(buffer)) > -1) {
+            baos.write(buffer, 0, b);
+        }
 
-		return new String(Base64.encodeBase64Chunked(baos.toByteArray()), "UTF-8");
-	}
+        return new String(Base64.encodeBase64Chunked(baos.toByteArray()), "UTF-8");
+    }
 }