Merge remote-tracking branch 'origin/master' into develar/is
[idea/community.git] / platform / util / src / com / intellij / util / jdom.kt
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.util
17
18 import com.intellij.openapi.util.JDOMUtil
19 import com.intellij.reference.SoftReference
20 import com.intellij.util.text.CharSequenceReader
21 import org.jdom.Document
22 import org.jdom.Element
23 import org.jdom.input.SAXBuilder
24 import org.xml.sax.EntityResolver
25 import org.xml.sax.InputSource
26 import java.io.CharArrayReader
27 import java.io.InputStream
28 import java.io.Reader
29 import java.nio.file.Files
30 import java.nio.file.Path
31
32 private val cachedSaxBuilder = ThreadLocal<SoftReference<SAXBuilder>>()
33
34 private fun getSaxBuilder(): SAXBuilder {
35   val reference = cachedSaxBuilder.get()
36   var saxBuilder = SoftReference.dereference<SAXBuilder>(reference)
37   if (saxBuilder == null) {
38     saxBuilder = SAXBuilder()
39     saxBuilder.ignoringBoundaryWhitespace = true
40     saxBuilder.ignoringElementContentWhitespace = true
41     saxBuilder.entityResolver = EntityResolver { publicId, systemId -> InputSource(CharArrayReader(ArrayUtil.EMPTY_CHAR_ARRAY)) }
42     cachedSaxBuilder.set(SoftReference<SAXBuilder>(saxBuilder))
43   }
44   return saxBuilder
45 }
46
47 fun loadElement(chars: CharSequence) = loadElement(CharSequenceReader(chars))
48
49 fun loadElement(reader: Reader): Element = loadDocument(reader).detachRootElement()
50
51 fun loadElement(stream: InputStream): Element = loadDocument(stream.reader()).detachRootElement()
52
53 fun loadElement(path: Path): Element = loadDocument(Files.newInputStream(path).bufferedReader()).detachRootElement()
54
55 private fun loadDocument(reader: Reader): Document {
56   try {
57     return getSaxBuilder().build(reader)
58   }
59   finally {
60     reader.close()
61   }
62 }
63
64 fun Element?.isEmpty() = this == null || JDOMUtil.isEmpty(this)