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

svn commit: r1740350 [2/6] - in /chemistry/portcmis/trunk: PortCMIS/ PortCMIS/binding/ PortCMIS/binding/atompub/ PortCMIS/binding/browser/ PortCMIS/binding/browser/json/ PortCMIS/client/ PortCMIS/const/ PortCMIS/data/ PortCMIS/enum/ PortCMIS/exceptions...

Added: chemistry/portcmis/trunk/PortCMIS/binding/atompub/AtomPubUtils.cs
URL: http://svn.apache.org/viewvc/chemistry/portcmis/trunk/PortCMIS/binding/atompub/AtomPubUtils.cs?rev=1740350&view=auto
==============================================================================
--- chemistry/portcmis/trunk/PortCMIS/binding/atompub/AtomPubUtils.cs (added)
+++ chemistry/portcmis/trunk/PortCMIS/binding/atompub/AtomPubUtils.cs Thu Apr 21 16:29:04 2016
@@ -0,0 +1,1404 @@
+/*
+* 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.
+*/
+
+using PortCMIS.binding;
+using PortCMIS.Binding.Impl;
+using PortCMIS.Client;
+using PortCMIS.Data;
+using PortCMIS.Enums;
+using PortCMIS.Exceptions;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace PortCMIS.Binding.AtomPub
+{
+
+    internal class AtomPubParser
+    {
+        public const string LinkRelContent = "@@content@@";
+
+        private Stream stream;
+        private AtomBase parseResult;
+
+        public AtomPubParser(Stream stream)
+        {
+            if (stream == null)
+            {
+                throw new ArgumentNullException("stream");
+            }
+
+            this.stream = stream;
+        }
+
+        /// <summary>
+        /// Parses the stream.
+        /// </summary>
+        public void Parse()
+        {
+            XmlReader parser = XmlUtils.CreateParser(stream);
+
+            try
+            {
+                while (true)
+                {
+                    XmlNodeType nodeType = parser.NodeType;
+                    if (nodeType == XmlNodeType.Element)
+                    {
+                        string uri = parser.NamespaceURI;
+                        string local = parser.LocalName;
+
+                        if (uri == XmlConstants.NAMESPACE_ATOM)
+                        {
+                            if (local == XmlConstants.TAG_FEED)
+                            {
+                                parseResult = ParseFeed(parser);
+                                break;
+                            }
+                            else if (local == XmlConstants.TAG_ENTRY)
+                            {
+                                parseResult = ParseEntry(parser);
+                                break;
+                            }
+                        }
+                        else if (uri == XmlConstants.NAMESPACE_CMIS)
+                        {
+                            if (local == XmlConstants.TAG_ALLOWABLEACTIONS)
+                            {
+                                parseResult = ParseAllowableActions(parser);
+                                break;
+                            }
+                            else if (local == XmlConstants.TAG_ACL)
+                            {
+                                parseResult = ParseACL(parser);
+                                break;
+                            }
+                        }
+                        else if (uri == XmlConstants.NAMESPACE_APP)
+                        {
+                            if (local == XmlConstants.TAG_SERVICE)
+                            {
+                                parseResult = ParseServiceDoc(parser);
+                                break;
+                            }
+                        }
+                        else if (string.Equals(XmlConstants.TAG_HTML, local, StringComparison.OrdinalIgnoreCase))
+                        {
+                            parseResult = new HtmlDoc();
+                            break;
+                        }
+                    }
+
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+            finally
+            {
+                parser.Dispose();
+
+                // make sure the stream is read and closed in all cases
+                IOUtils.ConsumeAndClose(stream);
+            }
+        }
+
+        /// <summary>
+        /// Return the parse results.
+        /// </summary>
+        public AtomBase GetResults()
+        {
+            return parseResult;
+        }
+
+        /// <summary>
+        /// Parses a service document.
+        /// </summary>
+        private static ServiceDoc ParseServiceDoc(XmlReader parser)
+        {
+            ServiceDoc result = new ServiceDoc();
+
+            XmlUtils.Next(parser);
+
+            while (true)
+            {
+                XmlNodeType nodeType = parser.NodeType;
+                if (nodeType == XmlNodeType.Element)
+                {
+                    string uri = parser.NamespaceURI;
+                    string local = parser.LocalName;
+
+                    if (uri == XmlConstants.NAMESPACE_APP)
+                    {
+                        if (local == XmlConstants.TAG_WORKSPACE)
+                        {
+                            result.AddWorkspace(ParseWorkspace(parser));
+                        }
+                        else
+                        {
+                            XmlUtils.Skip(parser);
+                        }
+                    }
+                    else
+                    {
+                        XmlUtils.Skip(parser);
+                    }
+                }
+                else if (nodeType == XmlNodeType.EndElement)
+                {
+                    break;
+                }
+                else
+                {
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// Parses a workspace element in a service document.
+        /// </summary>
+        private static RepositoryWorkspace ParseWorkspace(XmlReader parser)
+        {
+            RepositoryWorkspace workspace = new RepositoryWorkspace();
+
+            XmlUtils.Next(parser);
+
+            while (true)
+            {
+                XmlNodeType nodeType = parser.NodeType;
+                if (nodeType == XmlNodeType.Element)
+                {
+                    AtomElement element = ParseWorkspaceElement(parser);
+
+                    // check if we can extract the workspace id
+                    if (element != null && (element.Object is IRepositoryInfo))
+                    {
+                        workspace.Id = ((IRepositoryInfo)element.Object).Id;
+                    }
+
+                    // add to workspace
+                    workspace.AddElement(element);
+                }
+                else if (nodeType == XmlNodeType.EndElement)
+                {
+                    break;
+                }
+                else
+                {
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+
+            XmlUtils.Next(parser);
+
+            return workspace;
+        }
+
+        /// <summary>
+        /// Parses an Atom feed.
+        /// </summary>
+        private AtomFeed ParseFeed(XmlReader parser)
+        {
+            AtomFeed result = new AtomFeed();
+
+            XmlUtils.Next(parser);
+
+            while (true)
+            {
+                XmlNodeType nodeType = parser.NodeType;
+                if (nodeType == XmlNodeType.Element)
+                {
+                    string uri = parser.NamespaceURI;
+                    string local = parser.LocalName;
+
+                    if (uri == XmlConstants.NAMESPACE_ATOM)
+                    {
+                        if (local == XmlConstants.TAG_LINK)
+                        {
+                            result.AddElement(ParseLink(parser));
+                        }
+                        else if (local == XmlConstants.TAG_ENTRY)
+                        {
+                            result.AddEntry(ParseEntry(parser));
+                        }
+                        else
+                        {
+                            XmlUtils.Skip(parser);
+                        }
+                    }
+                    else if (uri == XmlConstants.NAMESPACE_RESTATOM)
+                    {
+                        if (local == XmlConstants.TAG_NUM_ITEMS)
+                        {
+                            result.AddElement(ParseBigInteger(parser));
+                        }
+                        else
+                        {
+                            XmlUtils.Skip(parser);
+                        }
+                    }
+                    else if (uri == XmlConstants.NAMESPACE_APACHE_CHEMISTRY)
+                    {
+                        result.AddElement(ParseText(parser));
+                    }
+                    else
+                    {
+                        XmlUtils.Skip(parser);
+                    }
+                }
+                else if (nodeType == XmlNodeType.EndElement)
+                {
+                    break;
+                }
+                else
+                {
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+
+            XmlUtils.Next(parser);
+
+            return result;
+        }
+
+        /// <summary>
+        /// Parses an Atom entry.
+        /// </summary>
+        private AtomEntry ParseEntry(XmlReader parser)
+        {
+            AtomEntry result = new AtomEntry();
+
+            XmlUtils.Next(parser);
+
+            // walk through all tags in entry
+            while (true)
+            {
+                XmlNodeType nodeType = parser.NodeType;
+                if (nodeType == XmlNodeType.Element)
+                {
+                    AtomElement element = ParseElement(parser);
+                    if (element != null)
+                    {
+                        // add to entry
+                        result.AddElement(element);
+
+                        // find and set object id
+                        if (element.Object is IObjectData)
+                        {
+                            result.Id = ((IObjectData)element.Object).Id;
+                        }
+                        else if (element.Object is ITypeDefinition)
+                        {
+                            result.Id = ((ITypeDefinition)element.Object).Id;
+                        }
+                    }
+                }
+                else if (nodeType == XmlNodeType.EndElement)
+                {
+                    break;
+                }
+                else
+                {
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+
+            XmlUtils.Next(parser);
+
+            return result;
+        }
+
+        /// <summary>
+        /// Parses an Allowable Actions document.
+        /// </summary>
+        private static AtomAllowableActions ParseAllowableActions(XmlReader parser)
+        {
+            return new AtomAllowableActions() { AllowableActions = XmlConverter.convertAllowableActions(parser) };
+        }
+
+        /// <summary>
+        /// Parses an ACL document.
+        /// </summary>
+        private static AtomAcl ParseACL(XmlReader parser)
+        {
+            return new AtomAcl() { Acl = XmlConverter.convertAcl(parser) };
+        }
+
+        /// <summary>
+        /// Parses an element.
+        /// </summary>
+        private AtomElement ParseElement(XmlReader parser)
+        {
+            string uri = parser.NamespaceURI;
+            string local = parser.LocalName;
+
+            if (uri == XmlConstants.NAMESPACE_RESTATOM)
+            {
+                if (local == XmlConstants.TAG_OBJECT)
+                {
+                    return new AtomElement(uri, local, XmlConverter.convertObject(parser));
+                }
+                else if (local == XmlConstants.TAG_PATH_SEGMENT
+                        || local == XmlConstants.TAG_RELATIVE_PATH_SEGMENT)
+                {
+                    return ParseText(parser);
+                }
+                else if (local == XmlConstants.TAG_TYPE)
+                {
+                    return new AtomElement(uri, local, XmlConverter.convertTypeDefinition(parser));
+                }
+                else if (local == XmlConstants.TAG_CHILDREN)
+                {
+                    return ParseChildren(parser);
+                }
+            }
+            else if (uri == XmlConstants.NAMESPACE_ATOM)
+            {
+                if (local == XmlConstants.TAG_LINK)
+                {
+                    return ParseLink(parser);
+                }
+                else if (local == XmlConstants.TAG_CONTENT)
+                {
+                    return ParseAtomContentSrc(parser);
+                }
+            }
+
+            // we don't know it - skip it
+            XmlUtils.Skip(parser);
+
+            return null;
+        }
+
+        /// <summary>
+        /// Parses a children element.
+        /// </summary>
+        private AtomElement ParseChildren(XmlReader parser)
+        {
+            AtomElement result = null;
+            string uri = parser.NamespaceURI;
+            string local = parser.LocalName;
+
+            XmlUtils.Next(parser);
+
+            // walk through the children tag
+            while (true)
+            {
+                XmlNodeType nodeType = parser.NodeType;
+                if (nodeType == XmlNodeType.Element)
+                {
+                    string tagUri = parser.NamespaceURI;
+                    string tagLocal = parser.LocalName;
+
+                    if (tagUri == XmlConstants.NAMESPACE_ATOM)
+                    {
+                        if (tagLocal == XmlConstants.TAG_FEED)
+                        {
+                            result = new AtomElement(uri, local, ParseFeed(parser));
+                        }
+                        else
+                        {
+                            XmlUtils.Skip(parser);
+                        }
+                    }
+                    else
+                    {
+                        XmlUtils.Skip(parser);
+                    }
+                }
+                else if (nodeType == XmlNodeType.EndElement)
+                {
+                    break;
+                }
+                else
+                {
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+
+            XmlUtils.Next(parser);
+
+            return result;
+        }
+
+        /// <summary>
+        /// Parses a workspace element.
+        /// </summary>
+        private static AtomElement ParseWorkspaceElement(XmlReader parser)
+        {
+            string uri = parser.NamespaceURI;
+            string local = parser.LocalName;
+
+            if (uri == XmlConstants.NAMESPACE_RESTATOM)
+            {
+                if (local == XmlConstants.TAG_REPOSITORY_INFO)
+                {
+                    return new AtomElement(uri, local, XmlConverter.convertRepositoryInfo(parser));
+                }
+                else if (local == XmlConstants.TAG_URI_TEMPLATE)
+                {
+                    return ParseTemplate(parser);
+                }
+            }
+            else if (uri == XmlConstants.NAMESPACE_ATOM)
+            {
+                if (local == XmlConstants.TAG_LINK)
+                {
+                    return ParseLink(parser);
+                }
+            }
+            else if (uri == XmlConstants.NAMESPACE_APP)
+            {
+                if (local == XmlConstants.TAG_COLLECTION)
+                {
+                    return ParseCollection(parser);
+                }
+            }
+
+            // we don't know it - skip it
+            XmlUtils.Skip(parser);
+
+            return null;
+        }
+
+        /// <summary>
+        /// Parses a collection tag.
+        /// </summary>
+        private static AtomElement ParseCollection(XmlReader parser)
+        {
+            string uri = parser.NamespaceURI;
+            string local = parser.LocalName;
+            Dictionary<string, string> result = new Dictionary<string, string>();
+
+            result["href"] = parser.GetAttribute("href");
+
+            XmlUtils.Next(parser);
+
+            while (true)
+            {
+                XmlNodeType nodeType = parser.NodeType;
+                if (nodeType == XmlNodeType.Element)
+                {
+                    string tagUri = parser.NamespaceURI;
+                    string tagLocal = parser.LocalName;
+
+                    if (tagUri == XmlConstants.NAMESPACE_RESTATOM
+                            && tagLocal == XmlConstants.TAG_COLLECTION_TYPE)
+                    {
+                        result["collectionType"] = XmlUtils.ReadText(parser, XmlConstraints.MaxStringLength);
+                    }
+                    else
+                    {
+                        XmlUtils.Skip(parser);
+                    }
+                }
+                else if (nodeType == XmlNodeType.EndElement)
+                {
+                    break;
+                }
+                else
+                {
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+
+            XmlUtils.Next(parser);
+
+            return new AtomElement(uri, local, result);
+        }
+
+        /// <summary>
+        /// Parses a template tag.
+        /// </summary>
+        private static AtomElement ParseTemplate(XmlReader parser)
+        {
+            string uri = parser.NamespaceURI;
+            string local = parser.LocalName;
+            Dictionary<string, string> result = new Dictionary<string, string>();
+
+            XmlUtils.Next(parser);
+
+            while (true)
+            {
+                XmlNodeType nodeType = parser.NodeType;
+                if (nodeType == XmlNodeType.Element)
+                {
+                    string tagUri = parser.NamespaceURI;
+                    string tagLocal = parser.LocalName;
+
+                    if (tagUri == XmlConstants.NAMESPACE_RESTATOM)
+                    {
+                        if (tagLocal == XmlConstants.TAG_TEMPLATE_TEMPLATE)
+                        {
+                            result["template"] = XmlUtils.ReadText(parser, XmlConstraints.MaxStringLength);
+                        }
+                        else if (tagLocal == XmlConstants.TAG_TEMPLATE_TYPE)
+                        {
+                            result["type"] = XmlUtils.ReadText(parser, XmlConstraints.MaxStringLength);
+                        }
+                        else
+                        {
+                            XmlUtils.Skip(parser);
+                        }
+                    }
+                    else
+                    {
+                        XmlUtils.Skip(parser);
+                    }
+                }
+                else if (nodeType == XmlNodeType.EndElement)
+                {
+                    break;
+                }
+                else
+                {
+                    if (!XmlUtils.Next(parser))
+                    {
+                        break;
+                    }
+                }
+            }
+
+            XmlUtils.Next(parser);
+
+            return new AtomElement(uri, local, result);
+        }
+
+        /// <summary>
+        /// Parses a link tag.
+        /// </summary>
+        private static AtomElement ParseLink(XmlReader parser)
+        {
+            string uri = parser.NamespaceURI;
+            string local = parser.LocalName;
+
+            AtomLink result = new AtomLink();
+
+            // save attributes
+            if (parser.HasAttributes)
+            {
+                for (int i = 0; i < parser.AttributeCount; i++)
+                {
+                    parser.MoveToAttribute(i);
+
+                    if (parser.Name == XmlConstants.LINK_REL)
+                    {
+                        result.Rel = parser.Value;
+                    }
+                    else if (parser.Name == XmlConstants.LINK_HREF)
+                    {
+                        result.Href = parser.Value;
+                    }
+                    else if (parser.Name == XmlConstants.LINK_TYPE)
+                    {
+                        result.Type = parser.Value;
+                    }
+                }
+            }
+
+            // skip enclosed tags, if any
+            XmlUtils.Skip(parser);
+
+            return new AtomElement(uri, local, result);
+        }
+
+        /// <summary>
+        /// Parses a link tag.
+        /// </summary>
+        private static AtomElement ParseAtomContentSrc(XmlReader parser)
+        {
+            string uri = parser.NamespaceURI;
+            string local = parser.LocalName;
+
+            AtomLink result = new AtomLink();
+            result.Rel = LinkRelContent;
+
+            // save attributes
+            if (parser.HasAttributes)
+            {
+                for (int i = 0; i < parser.AttributeCount; i++)
+                {
+                    parser.MoveToAttribute(i);
+
+                    if (parser.Name == XmlConstants.CONTENT_SRC)
+                    {
+                        result.Href = parser.Value;
+                    }
+                }
+            }
+
+            // skip enclosed tags, if any
+            XmlUtils.Skip(parser);
+
+            return new AtomElement(uri, local, result);
+        }
+
+        /// <summary>
+        /// Parses a text tag.
+        /// </summary>
+        private static AtomElement ParseText(XmlReader parser)
+        {
+            return new AtomElement(parser.NamespaceURI, parser.LocalName, XmlUtils.ReadText(parser, XmlConstraints.MaxStringLength));
+        }
+
+        /// <summary>
+        /// Parses a text tag and convert it into an integer.
+        /// </summary>
+        private static AtomElement ParseBigInteger(XmlReader parser)
+        {
+            return new AtomElement(parser.NamespaceURI, parser.LocalName,
+                BigInteger.Parse(XmlUtils.ReadText(parser, XmlConstraints.MaxStringLength), NumberStyles.Integer, CultureInfo.InvariantCulture));
+        }
+    }
+
+    internal class AtomElement
+    {
+        public string Namespace { get; private set; }
+        public string LocalName { get; private set; }
+        public object Object { get; private set; }
+
+        public AtomElement(string elementNamespace, string elementLocalName, object elementObject)
+        {
+            Namespace = elementNamespace;
+            LocalName = elementLocalName;
+            Object = elementObject;
+        }
+
+        public override string ToString()
+        {
+            return "{" + Namespace + "}" + LocalName + ": " + Object;
+        }
+    }
+
+    internal abstract class AtomBase
+    {
+        private IList<AtomElement> elements = new List<AtomElement>();
+
+        public abstract string Type { get; }
+
+        public IList<AtomElement> Elements { get { return elements; } }
+
+        public void AddElement(AtomElement element)
+        {
+            if (element != null)
+            {
+                elements.Add(element);
+            }
+        }
+    }
+
+    internal class RepositoryWorkspace : AtomBase
+    {
+        public string Id { get; set; }
+        public override string Type { get { return "Repository Workspace"; } }
+
+        public override string ToString()
+        {
+            return "Workspace \"" + Id + "\": " + Elements;
+        }
+    }
+
+    internal class ServiceDoc : AtomBase
+    {
+        private IList<RepositoryWorkspace> workspaces = new List<RepositoryWorkspace>();
+
+        public override string Type { get { return "Service Document"; } }
+        public IList<RepositoryWorkspace> Workspaces { get { return workspaces; } }
+
+        public void AddWorkspace(RepositoryWorkspace ws)
+        {
+            if (ws != null)
+            {
+                workspaces.Add(ws);
+            }
+        }
+
+        public override string ToString()
+        {
+            return "Service Doc: " + workspaces;
+        }
+    }
+
+    internal class AtomEntry : AtomBase
+    {
+        public string Id { get; set; }
+        public override string Type { get { return "Atom Entry"; } }
+
+        public override string ToString()
+        {
+            return "Entry \"" + Id + "\": " + Elements;
+        }
+    }
+
+    internal class AtomFeed : AtomBase
+    {
+        private IList<AtomEntry> entries = new List<AtomEntry>();
+
+        public override string Type { get { return "Atom Feed"; } }
+        public IList<AtomEntry> Entries { get { return entries; } }
+
+        public void AddEntry(AtomEntry entry)
+        {
+            if (entry != null)
+            {
+                entries.Add(entry);
+            }
+        }
+
+        public override string ToString()
+        {
+            return "Feed: " + Elements;
+        }
+    }
+
+    internal class AtomAllowableActions : AtomBase
+    {
+        public IAllowableActions AllowableActions { get; set; }
+        public override string Type { get { return "Allowable Actions"; } }
+    }
+
+    internal class AtomAcl : AtomBase
+    {
+        public IAcl Acl { get; set; }
+        public override string Type { get { return "ACL"; } }
+    }
+
+    internal class HtmlDoc : AtomBase
+    {
+        public override string Type { get { return "HTML document"; } }
+    }
+
+    internal class AtomLink
+    {
+        public string Rel { get; set; }
+        public string Type { get; set; }
+        public string Href { get; set; }
+    }
+
+    internal class LinkCache
+    {
+        private static readonly HashSet<string> KnownLinks = new HashSet<string>();
+
+        static LinkCache()
+        {
+            KnownLinks.Add(BindingConstants.RelAcl);
+            KnownLinks.Add(BindingConstants.RelDown);
+            KnownLinks.Add(BindingConstants.RelUp);
+            KnownLinks.Add(BindingConstants.RelFolderTree);
+            KnownLinks.Add(BindingConstants.RelRelationships);
+            KnownLinks.Add(BindingConstants.RelSelf);
+            KnownLinks.Add(BindingConstants.RelAllowableActions);
+            KnownLinks.Add(BindingConstants.RelEditMedia);
+            KnownLinks.Add(BindingConstants.RelPolicies);
+            KnownLinks.Add(BindingConstants.RelVersionHistory);
+            KnownLinks.Add(BindingConstants.RelWorkingCopy);
+            KnownLinks.Add(AtomPubParser.LinkRelContent);
+        }
+
+        private IBindingCache linkCache;
+        private IBindingCache typeLinkCache;
+        private IBindingCache collectionLinkCache;
+        private IBindingCache templateCache;
+        private IBindingCache repositoryLinkCache;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        public LinkCache(BindingSession session)
+        {
+            int repCount = session.GetValue(SessionParameter.CacheSizeRepositories,
+                    SessionParameterDefaults.CacheSizeRepositories);
+            if (repCount < 1)
+            {
+                repCount = SessionParameterDefaults.CacheSizeRepositories;
+            }
+
+            int typeCount = session.GetValue(SessionParameter.CacheSizeTypes, SessionParameterDefaults.CacheSizeTypes);
+            if (typeCount < 1)
+            {
+                typeCount = SessionParameterDefaults.CacheSizeTypes;
+            }
+
+            int objCount = session.GetValue(SessionParameter.CacheSizeLinks, SessionParameterDefaults.CacheSizeLinks);
+            if (objCount < 1)
+            {
+                objCount = SessionParameterDefaults.CacheSizeLinks;
+            }
+
+            string dictionaryLevelName = typeof(DictionaryCacheLevel).FullName;
+            string lruLevelName = typeof(LruCacheLevel).FullName;
+            string contentTypeLevelName = typeof(DictionaryCacheLevel).FullName;
+
+            linkCache = new Cache("Link Cache");
+            linkCache.Initialize(new string[] {
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=" + repCount.ToString(), // repository
+                lruLevelName + " " + LruCacheLevel.MaxEntries + "=" + objCount.ToString(), // id
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=16", // rel
+                contentTypeLevelName + " " + DictionaryCacheLevel.Capacity + "=3,"
+                        + DictionaryCacheLevel.SingleValue + "=true" // type
+        });
+
+            typeLinkCache = new Cache("Type Link Cache");
+            typeLinkCache.Initialize(new string[] {
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=" + repCount.ToString(), // repository
+                lruLevelName + " " + LruCacheLevel.MaxEntries + "=" + typeCount.ToString(), // id
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=16", // rel
+                contentTypeLevelName + " " + DictionaryCacheLevel.Capacity + "=3,"
+                        + DictionaryCacheLevel.SingleValue + "=true"// type
+        });
+
+            collectionLinkCache = new Cache("Collection Link Cache");
+            collectionLinkCache.Initialize(new string[] {
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=" + repCount.ToString(), // repository
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=8" // collection
+        });
+
+            templateCache = new Cache("URI Template Cache");
+            templateCache.Initialize(new string[] {
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=" + repCount.ToString(), // repository
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=6" // type
+        });
+
+            repositoryLinkCache = new Cache("Repository Link Cache");
+            repositoryLinkCache.Initialize(new string[] {
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=" + repCount.ToString(), // repository
+                dictionaryLevelName + " " + DictionaryCacheLevel.Capacity + "=6" // rel
+        });
+        }
+
+        /// <summary>
+        /// Adds a link.
+        /// </summary>
+        public void AddLink(string repositoryId, string id, string rel, string type, string link)
+        {
+            if (KnownLinks.Contains(rel))
+            {
+                linkCache.Put(new string[] { repositoryId, id, rel, type }, link);
+            }
+            else if (BindingConstants.RelAlternate == rel)
+            {
+                // use streamId instead of type as discriminating parameter
+                string streamId = extractStreamId(link);
+                if (streamId != null)
+                {
+                    linkCache.Put(new string[] { link, repositoryId, id, rel }, streamId);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Tries to extract a streamId from an alternate link.
+        /// this is not strictly in the spec
+        /// </summary>
+        protected string extractStreamId(string link)
+        {
+            int i = link.LastIndexOf('?');
+            if (i > 0)
+            {
+                string[] parameters = link.Substring(i + 1).Split('&');
+                foreach (string param in parameters)
+                {
+                    string[] parts = param.Split(new char[] { '=' }, 2);
+                    if (parts[0] == BindingConstants.ParamStreamId && parts.Length == 2)
+                    {
+                        return parts[1];
+                    }
+                }
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// Removes all links of an object.
+        /// </summary>
+        public void RemoveLinks(string repositoryId, string id)
+        {
+            linkCache.Remove(new string[] { repositoryId, id });
+        }
+
+        /// <summary>
+        /// Gets a link.
+        /// </summary>
+        public string GetLink(string repositoryId, string id, string rel, string type)
+        {
+            return (string)linkCache.Get(new string[] { repositoryId, id, rel, type });
+        }
+
+        /// <summary>
+        /// Gets a link.
+        /// </summary>
+        public string GetLink(string repositoryId, string id, string rel)
+        {
+            return GetLink(repositoryId, id, rel, null);
+        }
+
+        /// <summary>
+        /// Checks a link.
+        /// </summary>
+        public int CheckLink(string repositoryId, string id, string rel, string type)
+        {
+            return linkCache.Check(new string[] { repositoryId, id, rel, type });
+        }
+
+        /// <summary>
+        /// Locks the link cache.
+        /// </summary>
+        public void LockLinks()
+        {
+            linkCache.Lock();
+        }
+
+        /// <summary>
+        /// Unlocks the link cache.
+        /// </summary>
+        public void UnlockLinks()
+        {
+            linkCache.Unlock();
+        }
+
+        /// <summary>
+        /// Adds a type link.
+        /// </summary>
+        public void AddTypeLink(string repositoryId, string id, string rel, string type, string link)
+        {
+            if (KnownLinks.Contains(rel))
+            {
+                typeLinkCache.Put(new string[] { link, repositoryId, id, rel }, type);
+            }
+        }
+
+        /// <summary>
+        /// Removes all links of a type.
+        /// </summary>
+        public void RemoveTypeLinks(string repositoryId, string id)
+        {
+            typeLinkCache.Remove(new string[] { repositoryId, id });
+        }
+
+        /// <summary>
+        /// Gets a type link.
+        /// </summary>
+        public string GetTypeLink(string repositoryId, string id, string rel, string type)
+        {
+            return (string)typeLinkCache.Get(new string[] { repositoryId, id, rel, type });
+        }
+
+        /// <summary>
+        /// Locks the type link cache.
+        /// </summary>
+        public void LockTypeLinks()
+        {
+            typeLinkCache.Lock();
+        }
+
+        /// <summary>
+        /// Unlocks the type link cache.
+        /// </summary>
+        public void UnlockTypeLinks()
+        {
+            typeLinkCache.Unlock();
+        }
+
+        /// <summary>
+        /// Adds a collection.
+        /// </summary>
+        public void AddCollection(string repositoryId, string collection, string link)
+        {
+            collectionLinkCache.Put(new string[] { repositoryId, collection }, link);
+        }
+
+        /// <summary>
+        /// Gets a collection.
+        /// </summary>
+        public string GetCollection(string repositoryId, string collection)
+        {
+            return (string)collectionLinkCache.Get(new string[] { repositoryId, collection });
+        }
+
+        /// <summary>
+        /// Adds an URI template.
+        /// </summary>
+        public void AddTemplate(string repositoryId, string type, string link)
+        {
+            templateCache.Put(new string[] { repositoryId, type }, link);
+        }
+
+        /// <summary>
+        /// Gets an URI template and replaces place holders with the given
+        /// parameters.
+        /// </summary>
+        public string GetTemplateLink(string repositoryId, string type, IDictionary<string, object> parameters)
+        {
+            string template = (string)templateCache.Get(new string[] { repositoryId, type });
+            if (template == null)
+            {
+                return null;
+            }
+
+            StringBuilder result = new StringBuilder();
+            StringBuilder param = new StringBuilder();
+
+            bool paramMode = false;
+            for (int i = 0; i < template.Length; i++)
+            {
+                char c = template[i];
+
+                if (paramMode)
+                {
+                    if (c == '}')
+                    {
+                        paramMode = false;
+
+                        object paramValue;
+                        if (parameters.TryGetValue(param.ToString(), out paramValue))
+                        {
+                            result.Append(paramValue == null ? "" : Uri.EscapeDataString(UrlBuilder.NormalizeParameter(paramValue)));
+                        }
+
+                        param.Length = 0;
+                    }
+                    else
+                    {
+                        param.Append(c);
+                    }
+                }
+                else
+                {
+                    if (c == '{')
+                    {
+                        paramMode = true;
+                    }
+                    else
+                    {
+                        result.Append(c);
+                    }
+                }
+            }
+
+            return result.ToString();
+        }
+
+        // ---- repository links ----
+
+        /// <summary>
+        /// Adds a collection.
+        /// </summary>
+        public void AddRepositoryLink(string repositoryId, string rel, string link)
+        {
+            repositoryLinkCache.Put(new string[] { repositoryId, rel }, link);
+        }
+
+        /// <summary>
+        /// Gets a collection.
+        /// </summary>
+        public string GetRepositoryLink(string repositoryId, string rel)
+        {
+            return (string)repositoryLinkCache.Get(new string[] { repositoryId, rel });
+        }
+
+        // ---- clear ----
+
+        /// <summary>
+        /// Removes all entries of the given repository from the caches.
+        /// </summary>
+        public void ClearRepository(string repositoryId)
+        {
+            linkCache.Remove(new string[] { repositoryId });
+            typeLinkCache.Remove(new string[] { repositoryId });
+            collectionLinkCache.Remove(new string[] { repositoryId });
+            templateCache.Remove(new string[] { repositoryId });
+            repositoryLinkCache.Remove(new string[] { repositoryId });
+        }
+
+        public override string ToString()
+        {
+            return "Link Cache [link cache=" + linkCache + ", type link cache=" + typeLinkCache
+                    + ", collection link cache=" + collectionLinkCache + ", repository link cache=" + repositoryLinkCache
+                    + ",  template cache=" + templateCache + "]";
+        }
+    }
+
+    /// <summary>
+    /// Writes a CMIS Atom entry to an output stream.
+    /// </summary>
+    internal class AtomEntryWriter
+    {
+        private const int BufferSize = 64 * 1024;
+
+        private CmisVersion cmisVersion;
+        private IObjectData objectData;
+        private IContentStream contentStream;
+        private Stream stream;
+        private ITypeDefinition typeDef;
+        private BulkUpdate bulkUpdate;
+
+        /// <summary>
+        /// Constructor for objects.
+        /// </summary>
+        public AtomEntryWriter(ObjectData objectData, CmisVersion cmisVersion)
+            : this(objectData, cmisVersion, null)
+        {
+        }
+
+        /// <summary>
+        /// Constructor for objects.
+        /// </summary>
+        public AtomEntryWriter(ObjectData objectData, CmisVersion cmisVersion, ContentStream contentStream)
+        {
+            if (objectData == null || objectData.Properties == null)
+            {
+                throw new CmisInvalidArgumentException("Object and properties must not be null!");
+            }
+
+            if (contentStream != null && contentStream.MimeType == null)
+            {
+                throw new CmisInvalidArgumentException("Media type must be set if a stream is present!");
+            }
+
+            this.objectData = objectData;
+            this.cmisVersion = cmisVersion;
+            this.contentStream = contentStream;
+            if (contentStream != null && contentStream.Stream != null)
+            {
+                // do we need buffering here?
+                stream = contentStream.Stream;
+            }
+            else
+            {
+                stream = null;
+            }
+            this.typeDef = null;
+            this.bulkUpdate = null;
+        }
+
+        /// <summary>
+        /// Constructor for types.
+        /// </summary>
+        public AtomEntryWriter(ITypeDefinition type, CmisVersion cmisVersion)
+        {
+            if (type == null)
+            {
+                throw new CmisInvalidArgumentException("Type must not be null!");
+            }
+
+            this.typeDef = type;
+            this.cmisVersion = cmisVersion;
+            this.objectData = null;
+            this.contentStream = null;
+            this.stream = null;
+            this.bulkUpdate = null;
+        }
+
+        /// <summary>
+        /// Constructor for bulk updates.
+        /// </summary>
+        public AtomEntryWriter(BulkUpdate bulkUpdate)
+        {
+            if (bulkUpdate == null)
+            {
+                throw new CmisInvalidArgumentException("Bulk update data must not be null!");
+            }
+
+            this.bulkUpdate = bulkUpdate;
+            this.typeDef = null;
+            this.cmisVersion = CmisVersion.Cmis_1_1;
+            this.objectData = null;
+            this.contentStream = null;
+            this.stream = null;
+        }
+
+        /// <summary>
+        /// Writes the entry to an output stream.
+        /// </summary>
+        public void Write(Stream outStream)
+        {
+            using (XmlWriter writer = XmlUtils.createWriter(outStream))
+            {
+                XmlUtils.StartXmlDocument(writer);
+
+                writer.WriteStartElement(XmlConstants.PREFIX_ATOM, "entry", XmlConstants.NAMESPACE_ATOM);
+                writer.WriteAttributeString("xmlns", XmlConstants.PREFIX_ATOM, null, XmlConstants.NAMESPACE_ATOM);
+                writer.WriteAttributeString("xmlns", XmlConstants.PREFIX_CMIS, null, XmlConstants.NAMESPACE_CMIS);
+                writer.WriteAttributeString("xmlns", XmlConstants.PREFIX_RESTATOM, null, XmlConstants.NAMESPACE_RESTATOM);
+
+                if (contentStream != null && contentStream.FileName != null)
+                {
+                    writer.WriteAttributeString("xmlns", XmlConstants.PREFIX_APACHE_CHEMISTY, null, XmlConstants.NAMESPACE_APACHE_CHEMISTRY);
+                }
+
+                // atom:id
+                XmlUtils.Write(writer, XmlConstants.PREFIX_ATOM, XmlConstants.NAMESPACE_ATOM, XmlConstants.TAG_ATOM_ID,
+                        "urn:uuid:00000000-0000-0000-0000-00000000000");
+
+                // atom:title
+                XmlUtils.Write(writer, XmlConstants.PREFIX_ATOM, XmlConstants.NAMESPACE_ATOM, XmlConstants.TAG_ATOM_TITLE, GetTitle());
+
+                // atom:updated
+                XmlUtils.Write(writer, XmlConstants.PREFIX_ATOM, XmlConstants.NAMESPACE_ATOM, XmlConstants.TAG_ATOM_UPDATED, DateTime.UtcNow);
+
+                // content
+                if (stream != null)
+                {
+                    writer.WriteStartElement(XmlConstants.PREFIX_RESTATOM, XmlConstants.TAG_CONTENT, XmlConstants.NAMESPACE_RESTATOM);
+
+                    XmlUtils.Write(writer, XmlConstants.PREFIX_RESTATOM, XmlConstants.NAMESPACE_RESTATOM,
+                            XmlConstants.TAG_CONTENT_MEDIATYPE, contentStream.MimeType);
+
+                    if (contentStream.FileName != null)
+                    {
+                        XmlUtils.Write(writer, XmlConstants.PREFIX_APACHE_CHEMISTY, XmlConstants.NAMESPACE_APACHE_CHEMISTRY,
+                                XmlConstants.TAG_CONTENT_FILENAME, contentStream.FileName);
+                    }
+
+                    writer.WriteStartElement(XmlConstants.PREFIX_RESTATOM, XmlConstants.TAG_CONTENT_BASE64, XmlConstants.NAMESPACE_RESTATOM);
+                    WriteContent(writer);
+                    writer.WriteEndElement();
+
+                    writer.WriteEndElement();
+                }
+
+                // object
+                if (objectData != null)
+                {
+                    XmlConverter.writeObject(writer, cmisVersion, XmlConstants.NAMESPACE_RESTATOM, objectData);
+                }
+
+                // type
+                if (typeDef != null)
+                {
+                    XmlConverter.writeTypeDefinition(writer, cmisVersion, XmlConstants.NAMESPACE_RESTATOM, typeDef);
+                }
+
+                // bulk update
+                if (bulkUpdate != null)
+                {
+                    XmlConverter.writeBulkUpdate(writer, XmlConstants.NAMESPACE_RESTATOM, bulkUpdate);
+                }
+
+                // end entry
+                writer.WriteEndElement();
+
+                // end document
+                XmlUtils.EndXmlDocument(writer);
+            }
+        }
+
+        // ---- internal ----
+
+        private string GetTitle()
+        {
+            string result = "";
+
+            if (objectData != null)
+            {
+                IPropertyData nameProperty = objectData.Properties[PropertyIds.Name];
+                if (nameProperty != null)
+                {
+                    result = nameProperty.FirstValue as string;
+                }
+            }
+
+            if (typeDef != null)
+            {
+                if (typeDef.DisplayName != null)
+                {
+                    result = typeDef.DisplayName;
+                }
+            }
+
+            if (bulkUpdate != null)
+            {
+                result = "Bulk Update Properties";
+            }
+
+            return result;
+        }
+
+        private void WriteContent(XmlWriter writer)
+        {
+            byte[] buffer = new byte[BufferSize];
+
+            int rb;
+            while ((rb = stream.Read(buffer, 0, buffer.Length)) > 0)
+            {
+                writer.WriteBase64(buffer, 0, rb);
+            }
+        }
+    }
+
+
+
+
+    /// <summary>
+    /// HttpContent class for streaming AtomPub content.
+    /// </summary>
+    internal class AtomPubHttpContent : HttpContent
+    {
+        private readonly Action<Stream> writeAction;
+
+        public AtomPubHttpContent(string contentType, Action<Stream> writeAction)
+            : base()
+        {
+            this.Headers.ContentType = new MediaTypeHeaderValue(contentType) { CharSet = Encoding.UTF8.WebName };
+            this.writeAction = writeAction;
+        }
+
+        protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
+        {
+            await Task.Run(() => writeAction(stream));
+        }
+
+        protected override bool TryComputeLength(out long length)
+        {
+            length = -1;
+            return false;
+        }
+    }
+}

Modified: chemistry/portcmis/trunk/PortCMIS/binding/atompub/XmlConstants.cs
URL: http://svn.apache.org/viewvc/chemistry/portcmis/trunk/PortCMIS/binding/atompub/XmlConstants.cs?rev=1740350&r1=1740349&r2=1740350&view=diff
==============================================================================
--- chemistry/portcmis/trunk/PortCMIS/binding/atompub/XmlConstants.cs (original)
+++ chemistry/portcmis/trunk/PortCMIS/binding/atompub/XmlConstants.cs Thu Apr 21 16:29:04 2016
@@ -43,6 +43,57 @@ namespace PortCMIS.Binding.AtomPub
         public const string PREFIX_RESTATOM = "cmisra";
         public const string PREFIX_APACHE_CHEMISTY = "chemistry";
 
+        // service doc
+        public const string TAG_SERVICE = "service";
+        public const string TAG_WORKSPACE = "workspace";
+        public const string TAG_COLLECTION = "collection";
+        public const string TAG_COLLECTION_TYPE = "collectionType";
+        public const string TAG_URI_TEMPLATE = "uritemplate";
+        public const string TAG_TEMPLATE_TEMPLATE = "template";
+        public const string TAG_TEMPLATE_TYPE = "type";
+        public const string TAG_LINK = "link";
+
+        // atom
+        public const string TAG_ATOM_ID = "id";
+        public const string TAG_ATOM_TITLE = "title";
+        public const string TAG_ATOM_UPDATED = "updated";
+
+        // feed
+        public const string TAG_FEED = "feed";
+
+        // entry
+        public const string TAG_ENTRY = "entry";
+        public const string TAG_NUM_ITEMS = "numItems";
+        public const string TAG_PATH_SEGMENT = "pathSegment";
+        public const string TAG_RELATIVE_PATH_SEGMENT = "relativePathSegment";
+        public const string TAG_CHILDREN = "children";
+        public const string TAG_CONTENT = "content";
+        public const string TAG_CONTENT_MEDIATYPE = "mediatype";
+        public const string TAG_CONTENT_BASE64 = "base64";
+        public const string TAG_CONTENT_FILENAME = "filename";
+
+        public const string ATTR_DOCUMENT_TYPE = "cmisTypeDocumentDefinitionType";
+        public const string ATTR_FOLDER_TYPE = "cmisTypeFolderDefinitionType";
+        public const string ATTR_RELATIONSHIP_TYPE = "cmisTypeRelationshipDefinitionType";
+        public const string ATTR_POLICY_TYPE = "cmisTypePolicyDefinitionType";
+        public const string ATTR_ITEM_TYPE = "cmisTypeItemDefinitionType";
+        public const string ATTR_SECONDARY_TYPE = "cmisTypeSecondaryDefinitionType";
+
+        // allowable actions
+        public const string TAG_ALLOWABLEACTIONS = "allowableActions";
+
+        // ACL
+        public const string TAG_ACL = "acl";
+
+        // HTML
+        public const string TAG_HTML = "html";
+
+        // links
+        public const string LINK_REL = "rel";
+        public const string LINK_HREF = "href";
+        public const string LINK_TYPE = "type";
+        public const string CONTENT_SRC = "src";
+
         // tags
         public const string TAG_REPOSITORY_INFO = "repositoryInfo";
 
@@ -168,13 +219,6 @@ namespace PortCMIS.Binding.AtomPub
 
         public const string TAG_TYPE = "type";
 
-        public const string ATTR_DOCUMENT_TYPE = "cmisTypeDocumentDefinitionType";
-        public const string ATTR_FOLDER_TYPE = "cmisTypeFolderDefinitionType";
-        public const string ATTR_RELATIONSHIP_TYPE = "cmisTypeRelationshipDefinitionType";
-        public const string ATTR_POLICY_TYPE = "cmisTypePolicyDefinitionType";
-        public const string ATTR_ITEM_TYPE = "cmisTypeItemDefinitionType";
-        public const string ATTR_SECONDARY_TYPE = "cmisTypeSecondaryDefinitionType";
-
         public const string TAG_TYPE_ID = "id";
         public const string TAG_TYPE_LOCALNAME = "localName";
         public const string TAG_TYPE_LOCALNAMESPACE = "localNamespace";