flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject [07/14] git commit: [flex-utilities] [refs/heads/develop] - port DirectoryScanner from Ant code base and hook up FileSet to it
Date Mon, 09 Dec 2013 23:30:09 GMT
port DirectoryScanner from Ant code base and hook up FileSet to it


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/3a58a60e
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/3a58a60e
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/3a58a60e

Branch: refs/heads/develop
Commit: 3a58a60e9ad01f5bdf26806bd17f92c409fb360d
Parents: 2cc92bf
Author: Alex Harui <aharui@apache.org>
Authored: Sat Dec 7 21:46:49 2013 -0800
Committer: Alex Harui <aharui@apache.org>
Committed: Sat Dec 7 21:50:43 2013 -0800

----------------------------------------------------------------------
 .../src/org/apache/flex/ant/tags/FileSet.as     |   86 +
 .../org/apache/flex/ant/tags/FileSetExclude.as  |   40 +
 .../org/apache/flex/ant/tags/FileSetInclude.as  |   40 +
 .../flex/ant/tags/filesetClasses/Character.as   |   34 +
 .../ant/tags/filesetClasses/CollectionUtils.as  |   41 +
 .../flex/ant/tags/filesetClasses/DataType.as    |  330 ++++
 .../ant/tags/filesetClasses/DirectoryScanner.as | 1764 ++++++++++++++++++
 .../ant/tags/filesetClasses/FileProvider.as     |   27 +
 .../ant/tags/filesetClasses/FileResource.as     |  146 ++
 .../ant/tags/filesetClasses/FileSelector.as     |   27 +
 .../flex/ant/tags/filesetClasses/FileUtils.as   |  657 +++++++
 .../ant/tags/filesetClasses/PathTokenizer.as    |  118 ++
 .../flex/ant/tags/filesetClasses/Reference.as   |  106 ++
 .../flex/ant/tags/filesetClasses/Resource.as    |  349 ++++
 .../ant/tags/filesetClasses/SelectorUtils.as    |  638 +++++++
 .../ant/tags/filesetClasses/StringTokenizer.as  |   68 +
 .../ant/tags/filesetClasses/TokenizedPath.as    |  221 +++
 .../ant/tags/filesetClasses/TokenizedPattern.as |  173 ++
 .../filesetClasses/exceptions/BuildException.as |   28 +
 .../filesetClasses/exceptions/IOException.as    |   28 +
 .../exceptions/IllegalStateException.as         |   28 +
 .../exceptions/UnsupportedOperationException.as |   28 +
 22 files changed, 4977 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as b/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
new file mode 100644
index 0000000..4a01395
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
@@ -0,0 +1,86 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.filesetClasses.DirectoryScanner;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    import org.apache.flex.ant.tags.supportClasses.IValueTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.NamedTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.ParentTagHandler;
+    
+    [Mixin]
+    public class FileSet extends ParentTagHandler implements IValueTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["fileset"] = FileSet;
+        }
+
+        public function FileSet()
+        {
+            super();
+        }
+        
+        private var _dir:String;
+        
+        public function get dir():String
+        {
+            return _dir;
+        }
+        
+        private var _value:Vector.<String>;
+        
+        public function get value():Object
+        {
+            if (_value) return _value;
+            
+            var ds:DirectoryScanner = new DirectoryScanner();
+            var n:int = numChildren;
+            var includes:Vector.<String> = new Vector.<String>();
+            var excludes:Vector.<String> = new Vector.<String>();
+            for (var i:int = 0; i < n; i++)
+            {
+                var tag:NamedTagHandler = getChildAt(i) as NamedTagHandler;
+                if (tag is FileSetInclude)
+                    includes.push(tag.name);
+                else if (tag is FileSetExclude)
+                    excludes.push(tag.name);
+                else
+                    throw new BuildException("Unsupported Tag at index " + i);
+            }
+            ds.setIncludes(includes);
+            ds.setExcludes(excludes);
+            if (_dir != null)
+                ds.setBasedir(_dir);
+            ds.scan();
+            _value = ds.getIncludedFiles();
+            return _value;
+        }
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "dir")
+                _dir = value;
+        }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as b/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as
new file mode 100644
index 0000000..e2c0f02
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.NamedTagHandler;
+    
+    [Mixin]
+    public class FileSetExclude extends NamedTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["exclude"] = FileSetExclude;
+        }
+
+        public function FileSetExclude()
+        {
+            super();
+        }
+                
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as b/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as
new file mode 100644
index 0000000..8c6f98f
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.NamedTagHandler;
+    
+    [Mixin]
+    public class FileSetInclude extends NamedTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["include"] = FileSetInclude;
+        }
+
+        public function FileSetInclude()
+        {
+            super();
+        }
+                
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as
new file mode 100644
index 0000000..d2b6b87
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.flex.ant.tags.filesetClasses
+{
+    public class Character
+    {
+        public function Character()
+        {
+            super();
+        }
+        
+        public static function isLetter(c:String):Boolean
+        {
+            return "a" <= c && c <= "z" ||
+                "A" <= c && c <= "Z";
+        }        
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as
new file mode 100644
index 0000000..0717a4e
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.flex.ant.tags.filesetClasses
+{
+    public class CollectionUtils
+    {
+        public function CollectionUtils()
+        {
+            super();
+        }
+        
+        private static var target:String;
+        
+        private static function callback(item:String, index:int, list:Vector.<String>):Boolean
+        {
+            return CollectionUtils.target == item;
+        }
+        
+        public static function frequency(list:Vector.<String>, c:String):int
+        {
+            target = c;
+            return list.filter(callback).length;
+        }        
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as
new file mode 100644
index 0000000..1efa665
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as
@@ -0,0 +1,330 @@
+/*
+*  Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  See the NOTICE file distributed with
+*  this work for additional information regarding copyright ownership.
+*  The ASF licenses this file to You under the Apache License, Version 2.0
+*  (the "License"); you may not use this file except in compliance with
+*  the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*
+*/
+
+package org.apache.flex.ant.tags.filesetClasses
+{
+    import flash.system.ApplicationDomain;
+    import flash.utils.getQualifiedClassName;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.Project;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    
+    /**
+     * Ported from org.apache.tools.ant.types.DataType.java on 12/3/13 
+     * Base class for those classes that can appear inside the build file
+     * as stand alone data types.
+     *
+     * <p>This class handles the common description attribute and provides
+     * a default implementation for reference handling and checking for
+     * circular references that is appropriate for types that can not be
+     * nested inside elements of the same type (i.e. &lt;patternset&gt;
+     * but not &lt;path&gt;).</p>
+     *
+     */
+    public class DataType 
+    {
+        // CheckStyle:VisibilityModifier OFF
+        
+        /**
+         * Value to the refid attribute.
+         *
+         * @deprecated since 1.7.
+         *             The user should not be directly referencing
+         *             variable. Please use {@link #getRefid} instead.
+         */
+        protected var ref:Reference;
+        
+        /**
+         * Are we sure we don't hold circular references?
+         *
+         * <p>Subclasses are responsible for setting this value to false
+         * if we'd need to investigate this condition (usually because a
+         * child element has been added that is a subclass of
+         * DataType).</p>
+         *
+         * @deprecated since 1.7.
+         *             The user should not be directly referencing
+         *             variable. Please use {@link #setChecked} or
+         *             {@link #isChecked} instead.
+         */
+        protected var checked:Boolean = true;
+        // CheckStyle:VisibilityModifier ON
+        
+        /**
+         * Has the refid attribute of this element been set?
+         * @return true if the refid attribute has been set
+         */
+        public function isReference():Boolean  
+        {
+            return ref != null;
+        }
+        
+        /**
+         * Set the value of the refid attribute.
+         *
+         * <p>Subclasses may need to check whether any other attributes
+         * have been set as well or child elements have been created and
+         * thus override this method. if they do the must call
+         * <code>super.setRefid</code>.</p>
+         * @param ref the reference to use
+         */
+        public function setRefid(ref:Reference):void
+        {
+            this.ref = ref;
+            checked = false;
+        }
+        
+        /**
+         * Gets as descriptive as possible a name used for this datatype instance.
+         * @return <code>String</code> name.
+         */
+        protected function getDataTypeName():String
+        {
+            return "DataType";
+        }
+                
+        /**
+         * Check to see whether any DataType we hold references to is
+         * included in the Stack (which holds all DataType instances that
+         * directly or indirectly reference this instance, including this
+         * instance itself).
+         *
+         * <p>If one is included, throw a BuildException created by {@link
+         * #circularReference circularReference}.</p>
+         *
+         * <p>This implementation is appropriate only for a DataType that
+         * cannot hold other DataTypes as children.</p>
+         *
+         * <p>The general contract of this method is that it shouldn't do
+         * anything if {@link #checked <code>checked</code>} is true and
+         * set it to true on exit.</p>
+         * @param stack the stack of references to check.
+         * @param project the project to use to dereference the references.
+         * @throws BuildException on error.
+         */
+        protected function dieOnCircularReference(stack:Vector.<String> = null, project:Project
= null):void
+        {
+            if (!project)
+                project = Ant.project;
+            
+            if (!stack)
+                stack = new Vector.<String>();
+            
+            if (checked || !isReference()) {
+                return;
+            }
+            var o:Object = ref.getReferencedObject(project);
+            
+            if (o is DataType) {                
+                if (stack.indexOf(o) != -1) {
+                    throw circularReference();
+                } else {
+                    stack.push(o);
+                    DataType(o).dieOnCircularReference(Vector.<String>([id]), project);
+                    stack.pop();
+                }
+            }
+            checked = true;
+        }
+        
+        /**
+         * Allow DataTypes outside org.apache.tools.ant.types to indirectly call
+         * dieOnCircularReference on nested DataTypes.
+         * @param dt the DataType to check.
+         * @param stk the stack of references to check.
+         * @param p the project to use to dereference the references.
+         * @throws BuildException on error.
+         * @since Ant 1.7
+         */
+        public static function invokeCircularReferenceCheck(dt:DataType, stk:Vector.<String>,
+             p:Project):void 
+        {
+                dt.dieOnCircularReference(stk, p);
+        }
+        
+        /**
+         * Allow DataTypes outside org.apache.tools.ant.types to indirectly call
+         * dieOnCircularReference on nested DataTypes.
+         *
+         * <p>Pushes dt on the stack, runs dieOnCircularReference and pops
+         * it again.</p>
+         * @param dt the DataType to check.
+         * @param stk the stack of references to check.
+         * @param p the project to use to dereference the references.
+         * @throws BuildException on error.
+         * @since Ant 1.8.0
+         */
+        public static function pushAndInvokeCircularReferenceCheck(dt:DataType,
+            stk:Vector.<String>,
+            p:Project):void 
+        {
+                stk.push(dt);
+                dt.dieOnCircularReference(stk, p);
+                stk.pop();
+        }
+        
+        /**
+         * Performs the check for circular references and returns the
+         * referenced object.
+         * @param p the Ant Project instance against which to resolve references.
+         * @return the dereferenced object.
+         * @throws BuildException if the reference is invalid (circular ref, wrong class,
etc).
+         * @since Ant 1.7
+         */
+        protected function getCheckedRef(p:Project = null):Object 
+        {
+            if (!p)
+                p = Ant.project;
+            return getCheckedRefActual(Class(ApplicationDomain.currentDomain.getDefinition(getQualifiedClassName(this))),

+                    getDataTypeName(), p);
+        }
+
+        /**
+         * Performs the check for circular references and returns the
+         * referenced object.  This version allows the fallback Project instance to be specified.
+         * @param requiredClass the class that this reference should be a subclass of.
+         * @param dataTypeName  the name of the datatype that the reference should be
+         *                      (error message use only).
+         * @param project       the fallback Project instance for dereferencing.
+         * @return the dereferenced object.
+         * @throws BuildException if the reference is invalid (circular ref, wrong class,
etc),
+         *                        or if <code>project</code> is <code>null</code>.
+         * @since Ant 1.7
+         */
+        protected function getCheckedRefActual(requiredClass:Class,
+            dataTypeName:String, project:Project):Object {
+                if (project == null) {
+                    throw new BuildException("No Project specified");
+                }
+                dieOnCircularReference(null, project);
+                var o:Object = ref.getReferencedObject(project);
+                var oClass:Class = ApplicationDomain.currentDomain.getDefinition(getQualifiedClassName(o))
as Class;
+                if (!(requiredClass is oClass)) {
+                    Ant.log("Class " + oClass + " is not a subclass of " + requiredClass,
+                        Project.MSG_VERBOSE);
+                    var msg:String = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
+                    throw new BuildException(msg);
+                }
+                return o;
+            }
+
+        /**
+         * Creates an exception that indicates that refid has to be the
+         * only attribute if it is set.
+         * @return the exception to throw
+         */
+        protected function tooManyAttributes():BuildException 
+        {
+            return new BuildException("You must not specify more than one "
+                + "attribute when using refid");
+        }
+        
+        /**
+         * Creates an exception that indicates that this XML element must
+         * not have child elements if the refid attribute is set.
+         * @return the exception to throw
+         */
+        protected function noChildrenAllowed():BuildException 
+        {
+            return new BuildException("You must not specify nested elements "
+                + "when using refid");
+        }
+        
+        /**
+         * Creates an exception that indicates the user has generated a
+         * loop of data types referencing each other.
+         * @return the exception to throw
+         */
+        protected function circularReference():BuildException
+        {
+            return new BuildException("This data type contains a circular "
+                + "reference.");
+        }
+        
+        /**
+         * The flag that is used to indicate that circular references have been checked.
+         * @return true if circular references have been checked
+         */
+        protected function isChecked():Boolean 
+        {
+            return checked;
+        }
+        
+        /**
+         * Set the flag that is used to indicate that circular references have been checked.
+         * @param checked if true, if circular references have been checked
+         */
+        protected function setChecked(checked:Boolean):void 
+        {
+            this.checked = checked;
+        }
+        
+        /**
+         * get the reference set on this object
+         * @return the reference or null
+         */
+        public function getRefid():Reference 
+        {
+            return ref;
+        }
+        
+        /**
+         * check that it is ok to set attributes, i.e that no reference is defined
+         * @since Ant 1.6
+         * @throws BuildException if not allowed
+         */
+        protected function checkAttributesAllowed():void  
+        {
+            if (isReference()) {
+                throw tooManyAttributes();
+            }
+        }
+        
+        /**
+         * check that it is ok to add children, i.e that no reference is defined
+         * @since Ant 1.6
+         * @throws BuildException if not allowed
+         */
+        protected function checkChildrenAllowed():void 
+        {
+            if (isReference()) {
+                throw noChildrenAllowed();
+            }
+        }
+        
+        /**
+         * Basic DataType toString().
+         * @return this DataType formatted as a String.
+         */
+        public function toString():String {
+            var d:String = getDescription();
+            return d == null ? getDataTypeName() : getDataTypeName() + " " + d;
+        }
+        
+        /**
+         * Basic description
+         */
+        public function getDescription():String
+        {
+            return null;
+        }
+        
+        public var id:String;
+    }
+}   


Mime
View raw message