Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Genesys PGR
Genesys Backend
Commits
eab9249c
Commit
eab9249c
authored
Nov 04, 2014
by
Matija Obreza
Browse files
Use external artifact org.genesys2.transifex-client
parent
bae81f7b
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/genesys2/server/servlet/controller/transifex/TransifexAPIController.java
View file @
eab9249c
/**
* Copyright 2014 Global Crop Diversity Trust
*
* Licensed 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.genesys2.server.servlet.controller.transifex
;
import
java.io.BufferedWriter
;
import
java.io.File
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.util.Locale
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.commons.io.IOUtils
;
import
org.genesys2.server.model.impl.Article
;
import
org.genesys2.server.service.ContentService
;
import
org.genesys2.server.servlet.controller.BaseController
;
import
org.genesys2.transifex.client.TransifexService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.core.io.FileSystemResource
;
import
org.springframework.core.io.Resource
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.ui.Model
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.client.HttpClientErrorException
;
import
org.springframework.web.client.RestTemplate
;
/**
* Transifex web hook listener.
* TODO Move other (non-hook) methods to ArticleController!
*
* @author matijaobreza
*
*/
@Controller
@RequestMapping
(
value
=
"/transifex"
)
public
class
TransifexAPIController
extends
BaseController
{
...
...
@@ -40,17 +48,8 @@ public class TransifexAPIController extends BaseController {
@Autowired
private
ContentService
contentService
;
@Value
(
"${transifex.project}"
)
private
String
projectSlug
;
@Value
(
"${transifex.username}"
)
private
String
trasifexUserName
;
@Value
(
"${transifex.password}"
)
private
String
transifexPassord
;
@Value
(
"${transifex.base.api.url}"
)
private
String
baseApiURL
;
@Autowired
private
TransifexService
transifexService
;
@Value
(
"${transifex.content.template}"
)
private
String
contentTemplate
;
...
...
@@ -58,25 +57,15 @@ public class TransifexAPIController extends BaseController {
@Value
(
"${transifex.min.translated}"
)
private
int
transifexMinTranslated
;
private
RestTemplate
template
=
new
RestTemplate
();
@Value
(
"${transifex.hook.key}"
)
private
Object
transifexHookKey
;
@RequestMapping
(
value
=
"/deleteContent/{slug}"
)
public
String
deleteResource
(
@PathVariable
String
slug
,
Model
model
)
{
// make authentication for Transifex
HttpHeaders
headers
=
basicAuthentication
();
Article
article
=
contentService
.
getGlobalArticle
(
slug
,
getLocale
());
if
(
resourceExists
(
article
))
{
StringBuilder
url
=
new
StringBuilder
();
url
.
append
(
"project/"
);
url
.
append
(
projectSlug
);
url
.
append
(
"/resource/"
);
url
.
append
(
"article-"
);
url
.
append
(
article
.
getSlug
());
HttpEntity
<
String
>
request
=
new
HttpEntity
<>(
headers
);
ResponseEntity
<
String
>
response
=
template
.
exchange
(
baseApiURL
+
url
,
HttpMethod
.
DELETE
,
request
,
String
.
class
);
if
(
response
.
getStatusCode
().
value
()
==
204
)
{
if
(
articleExists
(
article
))
{
if
(
transifexService
.
deleteResource
(
"article-"
.
concat
(
article
.
getSlug
())))
{
model
.
addAttribute
(
"result"
,
"deleted ok"
);
}
}
else
{
...
...
@@ -94,17 +83,20 @@ public class TransifexAPIController extends BaseController {
*
* @see classpath:spring/spring-security.xml
*/
// FIXME make "magic" configurable
@RequestMapping
(
value
=
"/hook/40874cca86ca396169a5f4e6ebf6e4bf7199c4e7"
,
method
=
RequestMethod
.
POST
)
@RequestMapping
(
value
=
"/hook/{hookKey:.+}"
,
method
=
RequestMethod
.
POST
)
public
@ResponseBody
String
webHookHandle
(
@RequestParam
(
value
=
"project"
)
String
projectSlug
,
@RequestParam
(
value
=
"resource"
)
String
resource
,
@RequestParam
(
value
=
"language"
)
String
language
,
@RequestParam
(
value
=
"translated"
)
Integer
translatedPercentage
,
Model
model
)
{
String
webHookHandle
(
@PathVariable
(
"hookKey"
)
String
hookKey
,
@RequestParam
(
value
=
"project"
)
String
projectSlug
,
@RequestParam
(
value
=
"resource"
)
String
resource
,
@RequestParam
(
value
=
"language"
)
String
language
,
@RequestParam
(
value
=
"translated"
)
Integer
translatedPercentage
,
Model
model
)
{
if
(!
transifexHookKey
.
equals
(
hookKey
))
{
_logger
.
error
(
"Invalid key provided for Transifex callback hook: "
+
hookKey
);
throw
new
RuntimeException
(
"I don't know you!"
);
}
//
FIXME
remove once confirmed to work
//
TODO
remove once confirmed to work
_logger
.
warn
(
"project="
+
projectSlug
+
" resource="
+
resource
+
" lang="
+
language
+
" translated="
+
translatedPercentage
);
// TODO may be revisit this
// currently we do this due to nature of Transifex hook
if
(!
resource
.
startsWith
(
"article-"
))
{
_logger
.
warn
(
"Ignoring Transifex'd hook for "
+
resource
);
return
"Ignored"
;
...
...
@@ -141,23 +133,14 @@ public class TransifexAPIController extends BaseController {
private
Article
updateArticle
(
String
slug
,
String
lang
)
{
_logger
.
info
(
"Fetching updated translation for article "
+
slug
+
" lang="
+
lang
);
// make authentication for Transifex
HttpHeaders
headers
=
basicAuthentication
();
StringBuilder
url
=
new
StringBuilder
().
append
(
"project/"
).
append
(
projectSlug
).
append
(
"/resource/"
).
append
(
"article-"
).
append
(
slug
)
.
append
(
"/translation/"
).
append
(
lang
).
append
(
"/?file"
);
HttpEntity
<
String
>
request
=
new
HttpEntity
<>(
headers
);
ResponseEntity
<
String
>
response
=
template
.
exchange
(
baseApiURL
+
url
,
HttpMethod
.
GET
,
request
,
String
.
class
);
Locale
locale
=
new
Locale
(
lang
);
// TODO FIXME Check response status. Proceed only on HTTP OK response.
_logger
.
info
(
"Response code="
+
response
.
getStatusCode
());
String
resourceBody
=
transifexService
.
getTranslatedResource
(
"article-"
.
concat
(
slug
),
locale
);
String
title
=
res
ponse
.
get
Body
()
.
split
(
"<title>"
)[
1
].
split
(
"</title>"
)[
0
];
String
body
=
res
ponse
.
get
Body
()
.
split
(
"<body>"
)[
1
].
split
(
"</body>"
)[
0
];
String
title
=
res
ource
Body
.
split
(
"<title>"
)[
1
].
split
(
"</title>"
)[
0
];
String
body
=
res
ource
Body
.
split
(
"<body>"
)[
1
].
split
(
"</body>"
)[
0
];
Locale
locale
=
new
Locale
(
lang
);
// Extract article from database we need (correct locale + do not use
// default (EN) language)
Article
article
=
contentService
.
getGlobalArticle
(
slug
,
locale
,
false
);
...
...
@@ -175,103 +158,35 @@ public class TransifexAPIController extends BaseController {
@RequestMapping
(
value
=
"/postContent/{slug:.+}"
)
public
String
postResourceToTransifex
(
@PathVariable
String
slug
,
Model
model
)
throws
IOException
{
_logger
.
info
(
"Posting to transifex slug="
+
slug
);
// Make the authentication for Transifex
HttpHeaders
headers
=
basicAuthentication
();
// Extract article from database we need
Article
article
=
contentService
.
getGlobalArticle
(
slug
,
contentService
.
getDefaultLocale
(),
false
);
if
(!
resourceExists
(
article
))
{
// We will request like MULTIPART_FORM_DATA
headers
.
setContentType
(
MediaType
.
MULTIPART_FORM_DATA
);
if
(!
articleExists
(
article
))
{
_logger
.
info
(
"Posting to transifex slug="
+
slug
);
// This is template our xhtml
String
content
=
String
.
format
(
contentTemplate
,
article
.
getTitle
(),
article
.
getBody
());
// Create Multi value map with all necessary information for request
MultiValueMap
<
String
,
Object
>
map
=
new
LinkedMultiValueMap
<>();
map
.
add
(
"slug"
,
"article-"
+
slug
);
map
.
add
(
"name"
,
article
.
getTitle
());
map
.
add
(
"i18n_type"
,
"XHTML"
);
File
tempFile
=
File
.
createTempFile
(
slug
,
".xhtml"
);
//default FileWriter support default encoding only
try
(
BufferedWriter
writer
=
new
BufferedWriter
(
new
FileWriter
(
tempFile
))){
System
.
err
.
println
(
content
);
IOUtils
.
write
(
content
,
writer
);
writer
.
flush
();
Resource
resource
=
new
FileSystemResource
(
tempFile
);
map
.
add
(
"content"
,
resource
);
// Create our request entity
HttpEntity
<
MultiValueMap
<
String
,
Object
>>
request
=
new
HttpEntity
<>(
map
,
headers
);
StringBuilder
url
=
new
StringBuilder
();
url
.
append
(
"project/"
);
url
.
append
(
projectSlug
);
url
.
append
(
"/resources/"
);
// Send our post request(with .xhtml file) to Transifex
template
.
postForLocation
(
baseApiURL
+
url
,
request
);
try
{
transifexService
.
createXhtmlResource
(
"article-"
.
concat
(
article
.
getSlug
()),
article
.
getTitle
(),
content
);
model
.
addAttribute
(
"responseFromTransifex"
,
"Resource added"
);
}
catch
(
HttpClientErrorException
e
)
{
_logger
.
error
(
e
.
getMessage
());
_logger
.
error
(
e
.
getResponseBodyAsString
());
model
.
addAttribute
(
"responseFromTransifex"
,
"fail"
);
}
finally
{
tempFile
.
delete
();
}
}
else
{
// TODO Update contents!
// TODO Update contents
on Transifex
!
model
.
addAttribute
(
"responseFromTransifex"
,
"already exists"
);
}
model
.
addAttribute
(
"title"
,
article
.
getTitle
());
model
.
addAttribute
(
"article"
,
article
);
return
"/content/article-edit"
;
}
// Transifex requires Basic HTTP authentication!
// This method makes authentication for Transifex
public
HttpHeaders
basicAuthentication
()
{
HttpHeaders
headers
=
new
HttpHeaders
();
String
trasifexCreds
=
trasifexUserName
+
":"
+
transifexPassord
;
byte
[]
transifexCredsBytes
=
trasifexCreds
.
getBytes
();
byte
[]
base64CredsBytes
=
Base64
.
encodeBase64
(
transifexCredsBytes
);
String
base64Creds
=
new
String
(
base64CredsBytes
);
headers
.
add
(
"Authorization"
,
"Basic "
+
base64Creds
);
return
headers
;
}
// This method verify if article already exists in Transifex
boolean
resourceExists
(
Article
resource
)
{
// make authentication for Transifex
HttpHeaders
headers
=
basicAuthentication
();
StringBuilder
url
=
new
StringBuilder
();
url
.
append
(
"project/"
);
url
.
append
(
projectSlug
);
url
.
append
(
"/resource/"
);
url
.
append
(
"article-"
);
url
.
append
(
resource
.
getSlug
());
ResponseEntity
<
String
>
response
;
HttpEntity
<
String
>
request
=
new
HttpEntity
<>(
headers
);
try
{
response
=
template
.
exchange
(
baseApiURL
+
url
,
HttpMethod
.
GET
,
request
,
String
.
class
);
}
catch
(
HttpClientErrorException
e
)
{
return
false
;
}
return
response
.
getStatusCode
().
value
()
==
HttpStatus
.
OK
.
value
();
boolean
articleExists
(
Article
article
)
{
return
transifexService
.
resourceExists
(
"article-"
.
concat
(
article
.
getSlug
()));
}
}
src/main/java/org/genesys2/spring/config/ApplicationConfig.java
View file @
eab9249c
...
...
@@ -16,13 +16,22 @@
package
org.genesys2.spring.config
;
import
org.genesys2.transifex.client.TransifexService
;
import
org.genesys2.transifex.client.TransifexServiceImpl
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.context.annotation.ImportResource
;
@Configuration
@Import
({
SpringProperties
.
class
,
SpringCommonConfig
.
class
,
SpringAclConfig
.
class
,
SpringSchedulerConfig
.
class
,
SpringDataBaseConfig
.
class
,
SpringMailConfig
.
class
,
SpringSecurityOauthConfig
.
class
,
SpringCacheConfig
.
class
,
ElasticsearchConfig
.
class
})
@Import
({
SpringProperties
.
class
,
SpringCommonConfig
.
class
,
SpringAclConfig
.
class
,
SpringSchedulerConfig
.
class
,
SpringDataBaseConfig
.
class
,
SpringMailConfig
.
class
,
SpringSecurityOauthConfig
.
class
,
SpringCacheConfig
.
class
,
ElasticsearchConfig
.
class
})
@ImportResource
({
"classpath:/spring/spring-security.xml"
})
public
class
ApplicationConfig
{
@Bean
public
TransifexService
transifexService
()
{
return
new
TransifexServiceImpl
();
}
}
src/main/java/org/genesys2/transifex/client/TransifexService.java
0 → 100644
View file @
eab9249c
/**
* Copyright 2014 Global Crop Diversity Trust
*
* Licensed 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.genesys2.transifex.client
;
import
java.io.IOException
;
import
java.util.Locale
;
/**
* Transifex client
*
* @author matijaobreza
*
*/
public
interface
TransifexService
{
boolean
resourceExists
(
String
slug
);
boolean
deleteResource
(
String
slug
);
String
getTranslatedResource
(
String
slug
,
Locale
locale
);
/**
* Create a new XHTML resource. Fails if resource exists.
*
* @param slug
* @param title
* @param content
* @throws IOException
*/
void
createXhtmlResource
(
String
slug
,
String
title
,
String
content
)
throws
IOException
;
/**
* Create or update XHTML resource
*
* @param resourceSlug
* @param resourceTitle
* @param content
* @throws IOException
*/
void
updateXhtmlResource
(
String
resourceSlug
,
String
resourceTitle
,
String
content
)
throws
IOException
;
}
src/main/java/org/genesys2/transifex/client/TransifexServiceImpl.java
0 → 100644
View file @
eab9249c
/**
* Copyright 2014 Global Crop Diversity Trust
*
* Licensed 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.genesys2.transifex.client
;
import
java.io.BufferedWriter
;
import
java.io.File
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.util.Locale
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.commons.io.IOUtils
;
import
org.apache.log4j.Logger
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.core.io.FileSystemResource
;
import
org.springframework.core.io.Resource
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.client.HttpClientErrorException
;
import
org.springframework.web.client.RestTemplate
;
/**
* Java implementation of Transifex API 2
*
* @author alexandr
* @author matijaobreza
*
*/
@Service
public
class
TransifexServiceImpl
implements
TransifexService
,
InitializingBean
{
private
static
final
Logger
LOG
=
Logger
.
getLogger
(
TransifexServiceImpl
.
class
);
private
static
final
String
TRANSIFEX_API_URL
=
"https://www.transifex.com/api/2"
;
/*** Transifex project slug ***/
@Value
(
"${transifex.project}"
)
private
String
projectSlug
;
@Value
(
"${transifex.username}"
)
private
String
trasifexUserName
;
@Value
(
"${transifex.password}"
)
private
String
transifexPassord
;
private
RestTemplate
template
=
new
RestTemplate
();
// Transifex project url
private
String
transifexProjectUrl
;
@Override
public
void
afterPropertiesSet
()
throws
Exception
{
transifexProjectUrl
=
TRANSIFEX_API_URL
.
concat
(
"/project/"
).
concat
(
projectSlug
);
LOG
.
info
(
"Transifex project URL: "
+
transifexProjectUrl
);
}
// Transifex requires Basic HTTP authentication!
// This method makes authentication for Transifex
protected
HttpHeaders
basicAuthentication
()
{
HttpHeaders
headers
=
new
HttpHeaders
();
String
trasifexCreds
=
trasifexUserName
+
":"
+
transifexPassord
;
byte
[]
transifexCredsBytes
=
trasifexCreds
.
getBytes
();
byte
[]
base64CredsBytes
=
Base64
.
encodeBase64
(
transifexCredsBytes
);
String
base64Creds
=
new
String
(
base64CredsBytes
);
headers
.
add
(
"Authorization"
,
"Basic "
+
base64Creds
);
return
headers
;
}
@Override
public
boolean
resourceExists
(
String
slug
)
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Checking for resource "
+
slug
);
}
ResponseEntity
<
String
>
response
;
HttpHeaders
headers
=
basicAuthentication
();
HttpEntity
<
String
>
request
=
new
HttpEntity
<>(
headers
);
try
{
response
=
template
.
exchange
(
transifexProjectUrl
+
"/resource/{slug}"
,
HttpMethod
.
GET
,
request
,
String
.
class
,
slug
);
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
response
.
getStatusCode
()
+
" "
+
response
.
getBody
());
}
}
catch
(
HttpClientErrorException
e
)
{
return
false
;
}
return
response
.
getStatusCode
().
value
()
==
HttpStatus
.
OK
.
value
();
}
@Override
public
boolean
deleteResource
(
String
slug
)
{
HttpHeaders
headers
=
basicAuthentication
();
HttpEntity
<
String
>
request
=
new
HttpEntity
<>(
headers
);
ResponseEntity
<
String
>
response
=
template
.
exchange
(
transifexProjectUrl
+
"/resource/{slug}"
,
HttpMethod
.
DELETE
,
request
,
String
.
class
,
slug
);
if
(
response
.
getStatusCode
().
value
()
==
204
)
{
return
true
;
}
return
false
;
}
@Override
public
String
getTranslatedResource
(
String
slug
,
Locale
locale
)
{
HttpHeaders
headers
=
basicAuthentication
();
HttpEntity
<
String
>
request
=
new
HttpEntity
<>(
headers
);
ResponseEntity
<
String
>
response
=
template
.
exchange
(
transifexProjectUrl
+
"/resource/{slug}/translation/{language}"
,
HttpMethod
.
GET
,
request
,
String
.
class
,
slug
,
locale
.
getLanguage
());
// FIXME Check response status. Proceed only on HTTP OK response.
LOG
.
info
(
"Response code="
+
response
.
getStatusCode
());
return
response
.
getBody
();
}
@Override
public
void
createXhtmlResource
(
String
slug
,
String
title
,
String
content
)
throws
IOException
{
// Make the authentication for Transifex
HttpHeaders
headers
=
basicAuthentication
();
// We will request like MULTIPART_FORM_DATA
headers
.
setContentType
(
MediaType
.
MULTIPART_FORM_DATA
);
// Create Multi value map with all necessary information for request
MultiValueMap
<
String
,
Object
>
map
=
new
LinkedMultiValueMap
<>();
map
.
add
(
"slug"
,
slug
);
map
.
add
(
"name"
,
title
);
map
.
add
(
"i18n_type"
,
"XHTML"
);
File
tempFile
=
File
.
createTempFile
(
slug
,
".xhtml"
);
// default FileWriter support default encoding only
try
(
BufferedWriter
writer
=
new
BufferedWriter
(
new
FileWriter
(
tempFile
)))
{
LOG
.
debug
(
content
);
IOUtils
.
write
(
content
,
writer
);
writer
.
flush
();
Resource
resource
=
new
FileSystemResource
(
tempFile
);
map
.
add
(
"content"
,
resource
);
// Create our request entity
HttpEntity
<
MultiValueMap
<
String
,
Object
>>
request
=
new
HttpEntity
<>(
map
,
headers
);
// Send our post request(with .xhtml file) to Transifex
ResponseEntity
<
Object
>
response
=
template
.
postForEntity
(
transifexProjectUrl
+
"/resources/"
,
request
,
Object
.
class
);
if
(
LOG
.
isDebugEnabled
())
{
// 201 CREATED is returned by Transifex API 2
LOG
.
debug
(
"Response: "
+
response
.
getStatusCode
());
}
}
catch
(
HttpClientErrorException
e
)
{
LOG
.
error
(
e
.
getMessage
());
LOG
.
error
(
e
.
getResponseBodyAsString
());
throw
e
;
}
finally
{
tempFile
.
delete
();
}
}
@Override
public
void
updateXhtmlResource
(
String
slug
,
String
title
,
String
content
)
throws
IOException
{
if
(!
resourceExists
(
slug
))
{
// POST the resource
createXhtmlResource
(
slug
,
title
,
content
);
return
;
}
LOG
.
info
(
"Updating Transifex resource "
+
slug
);
// Make the authentication for Transifex
HttpHeaders
headers
=
basicAuthentication
();
// We will request like MULTIPART_FORM_DATA
headers
.
setContentType
(
MediaType
.
MULTIPART_FORM_DATA
);
// Create Multi value map with all necessary information for request
MultiValueMap
<
String
,
Object
>
map
=
new
LinkedMultiValueMap
<>();
// map.add("slug", slug);
// map.add("name", title);
// map.add("i18n_type", "XHTML");
File
tempFile
=
File
.
createTempFile
(
slug
,
".xhtml"
);
// default FileWriter support default encoding only
try
(
BufferedWriter
writer
=
new
BufferedWriter
(
new
FileWriter
(
tempFile
)))
{
LOG
.
debug
(
content
);
IOUtils
.
write
(
content
,
writer
);
writer
.
flush
();