fix #2229 upload jar file

This commit is contained in:
Shinsuke Sugaya 2019-08-29 07:51:05 +09:00
parent 4a53458a92
commit 0001a8e909
14 changed files with 373 additions and 220 deletions

View file

@ -15,6 +15,10 @@
*/
package org.codelibs.fess.app.web.admin.plugin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -22,9 +26,11 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.codelibs.core.io.CopyUtil;
import org.codelibs.fess.app.web.base.FessAdminAction;
import org.codelibs.fess.helper.PluginHelper;
import org.codelibs.fess.helper.PluginHelper.Artifact;
import org.codelibs.fess.helper.PluginHelper.ArtifactType;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.RenderDataUtil;
import org.lastaflute.web.Execute;
@ -37,6 +43,8 @@ public class AdminPluginAction extends FessAdminAction {
private static final Logger logger = LoggerFactory.getLogger(AdminPluginAction.class);
private static final String UPLOAD = "upload";
@Override
protected void setupHtmlData(final ActionRuntime runtime) {
super.setupHtmlData(runtime);
@ -53,7 +61,7 @@ public class AdminPluginAction extends FessAdminAction {
public HtmlResponse delete(final DeleteForm form) {
validate(form, messages -> {}, () -> asHtml(path_AdminPlugin_AdminPluginJsp));
verifyToken(() -> asHtml(path_AdminPlugin_AdminPluginJsp));
final Artifact artifact = new Artifact(form.name, form.version);
final Artifact artifact = new Artifact(form.name, form.version, null);
deleteArtifact(artifact);
saveInfo(messages -> messages.addSuccessDeletePlugin(GLOBAL, artifact.getFileName()));
return redirect(getClass());
@ -63,12 +71,48 @@ public class AdminPluginAction extends FessAdminAction {
public HtmlResponse install(final InstallForm form) {
validate(form, messages -> {}, () -> asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp));
verifyToken(() -> asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp));
final Artifact artifact = getArtifactFromInstallForm(form);
if (artifact == null) {
throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), () -> asListHtml());
if (UPLOAD.equals(form.id)) {
if (form.jarFile == null) {
throwValidationError(messages -> messages.addErrorsPluginFileIsNotFound(GLOBAL, form.id), () -> asListHtml());
}
if (!form.jarFile.getFileName().endsWith(".jar")) {
throwValidationError(messages -> messages.addErrorsFileIsNotSupported(GLOBAL, form.jarFile.getFileName()),
() -> asListHtml());
}
final String filename = form.jarFile.getFileName();
final File tempFile = ComponentUtil.getSystemHelper().createTempFile("tmp-adminplugin-", ".jar");
try (final InputStream is = form.jarFile.getInputStream(); final OutputStream os = new FileOutputStream(tempFile)) {
CopyUtil.copy(is, os);
} catch (final Exception e) {
if (tempFile.exists() && !tempFile.delete()) {
logger.warn("Failed to delete {}.", tempFile.getAbsolutePath());
}
logger.debug("Failed to copy " + filename, e);
throwValidationError(messages -> messages.addErrorsFailedToInstallPlugin(GLOBAL, filename), () -> asListHtml());
}
new Thread(() -> {
try {
final PluginHelper pluginHelper = ComponentUtil.getPluginHelper();
final Artifact artifact =
pluginHelper.getArtifactFromFileName(ArtifactType.UNKNOWN, filename, tempFile.getAbsolutePath());
pluginHelper.installArtifact(artifact);
} catch (final Exception e) {
logger.warn("Failed to install " + filename, e);
} finally {
if (tempFile.exists() && !tempFile.delete()) {
logger.warn("Failed to delete {}.", tempFile.getAbsolutePath());
}
}
}).start();
saveInfo(messages -> messages.addSuccessInstallPlugin(GLOBAL, form.jarFile.getFileName()));
} else {
final Artifact artifact = getArtifactFromInstallForm(form);
if (artifact == null) {
throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), () -> asListHtml());
}
installArtifact(artifact);
saveInfo(messages -> messages.addSuccessInstallPlugin(GLOBAL, artifact.getFileName()));
}
installArtifact(artifact);
saveInfo(messages -> messages.addSuccessInstallPlugin(GLOBAL, artifact.getFileName()));
return redirect(getClass());
}
@ -88,6 +132,11 @@ public class AdminPluginAction extends FessAdminAction {
public static List<Map<String, String>> getAllAvailableArtifacts() {
final PluginHelper pluginHelper = ComponentUtil.getPluginHelper();
final List<Map<String, String>> result = new ArrayList<>();
final Map<String, String> map = new HashMap<>();
map.put("id", UPLOAD);
map.put("name", "");
map.put("version", "");
result.add(map);
for (final PluginHelper.ArtifactType artifactType : PluginHelper.ArtifactType.values()) {
result.addAll(Arrays.stream(pluginHelper.getAvailableArtifacts(artifactType)).map(AdminPluginAction::beanToMap)
.collect(Collectors.toList()));

View file

@ -17,6 +17,7 @@ package org.codelibs.fess.app.web.admin.plugin;
import javax.validation.constraints.Size;
import org.lastaflute.web.ruts.multipart.MultipartFormFile;
import org.lastaflute.web.validation.Required;
public class InstallForm {
@ -25,4 +26,5 @@ public class InstallForm {
@Size(max = 400)
public String id;
public MultipartFormFile jarFile;
}

View file

@ -19,6 +19,7 @@ import static org.codelibs.core.stream.StreamUtil.split;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@ -65,7 +66,8 @@ public class PluginHelper {
protected LoadingCache<ArtifactType, Artifact[]> availableArtifacts = CacheBuilder.newBuilder().maximumSize(10)
.expireAfterWrite(5, TimeUnit.MINUTES).build(new CacheLoader<ArtifactType, Artifact[]>() {
public Artifact[] load(ArtifactType key) {
@Override
public Artifact[] load(final ArtifactType key) {
final List<Artifact> list = new ArrayList<>();
for (final String url : getRepositories()) {
if (url.endsWith(".yaml")) {
@ -95,16 +97,16 @@ public class PluginHelper {
protected List<Artifact> loadArtifactsFromRepository(final String url) {
final String content = getRepositoryContent(url);
ObjectMapper objectMapper = new YAMLMapper();
final ObjectMapper objectMapper = new YAMLMapper();
try {
@SuppressWarnings("unchecked")
List<Map<?, ?>> result = objectMapper.readValue(content, List.class);
final List<Map<?, ?>> result = objectMapper.readValue(content, List.class);
if (result != null) {
return result.stream().map(o -> new Artifact((String) o.get("name"), (String) o.get("version"), (String) o.get("url")))
.collect(Collectors.toList());
}
return Collections.emptyList();
} catch (Exception e) {
} catch (final Exception e) {
throw new PluginException("Failed to access " + url, e);
}
}
@ -129,7 +131,7 @@ public class PluginHelper {
if (version.endsWith("SNAPSHOT")) {
final String snapshotVersion = getSnapshotActualVersion(builder, pluginUrl, version);
if (StringUtil.isNotBlank(snapshotVersion)) {
String actualVersion = version.replace("SNAPSHOT", snapshotVersion);
final String actualVersion = version.replace("SNAPSHOT", snapshotVersion);
list.add(new Artifact(name, actualVersion, pluginUrl + version + "/" + name + "-" + actualVersion + ".jar"));
} else if (logger.isDebugEnabled()) {
logger.debug("Snapshot name is not found: " + name + "/" + version);
@ -161,7 +163,7 @@ public class PluginHelper {
final Document doc = builder.parse(is);
final NodeList snapshotNodeList = doc.getElementsByTagName("snapshot");
if (snapshotNodeList.getLength() > 0) {
NodeList nodeList = snapshotNodeList.item(0).getChildNodes();
final NodeList nodeList = snapshotNodeList.item(0).getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
final Node node = nodeList.item(i);
if ("timestamp".equalsIgnoreCase(node.getNodeName())) {
@ -192,7 +194,7 @@ public class PluginHelper {
public Artifact[] getInstalledArtifacts(final ArtifactType artifactType) {
if (artifactType == ArtifactType.UNKNOWN) {
final File[] jarFiles = ResourceUtil.getPluginJarFiles((d, n) -> {
for (ArtifactType type : ArtifactType.values()) {
for (final ArtifactType type : ArtifactType.values()) {
if (n.startsWith(type.getId())) {
return false;
}
@ -216,12 +218,16 @@ public class PluginHelper {
return list.toArray(new Artifact[list.size()]);
}
protected Artifact getArtifactFromFileName(final ArtifactType artifactType, final String name) {
String baseName = StringUtils.removeEndIgnoreCase(name, ".jar");
List<String> nameList = new ArrayList<>();
List<String> versionList = new ArrayList<>();
protected Artifact getArtifactFromFileName(final ArtifactType artifactType, final String filename) {
return getArtifactFromFileName(artifactType, filename, null);
}
public Artifact getArtifactFromFileName(final ArtifactType artifactType, final String filename, final String url) {
final String baseName = StringUtils.removeEndIgnoreCase(filename, ".jar");
final List<String> nameList = new ArrayList<>();
final List<String> versionList = new ArrayList<>();
boolean isName = true;
for (String value : baseName.split("-")) {
for (final String value : baseName.split("-")) {
if (isName && value.length() > 0 && value.charAt(0) >= '0' && value.charAt(0) <= '9') {
isName = false;
}
@ -231,21 +237,31 @@ public class PluginHelper {
versionList.add(value);
}
}
return new Artifact(nameList.stream().collect(Collectors.joining("-")), versionList.stream().collect(Collectors.joining("-")));
return new Artifact(nameList.stream().collect(Collectors.joining("-")), versionList.stream().collect(Collectors.joining("-")), url);
}
public void installArtifact(final Artifact artifact) {
final String fileName = artifact.getFileName();
try (final CurlResponse response = Curl.get(artifact.getUrl()).execute()) {
if (response.getHttpStatusCode() != 200) {
throw new PluginException("HTTP Status " + response.getHttpStatusCode() + " : failed to get the artifact from "
+ artifact.getUrl());
final String url = artifact.getUrl();
if (StringUtil.isBlank(url)) {
throw new PluginException("url is blank: " + artifact.getName());
} else if (url.startsWith("http:") || url.startsWith("https:")) {
try (final CurlResponse response = Curl.get(url).execute()) {
if (response.getHttpStatusCode() != 200) {
throw new PluginException("HTTP Status " + response.getHttpStatusCode() + " : failed to get the artifact from " + url);
}
try (final InputStream in = response.getContentAsStream()) {
CopyUtil.copy(in, ResourceUtil.getPluginPath(fileName).toFile());
}
} catch (final Exception e) {
throw new PluginException("Failed to install the artifact " + artifact.getName(), e);
}
try (final InputStream in = response.getContentAsStream()) {
} else {
try (final InputStream in = new FileInputStream(url)) {
CopyUtil.copy(in, ResourceUtil.getPluginPath(fileName).toFile());
} catch (final Exception e) {
throw new PluginException("Failed to install the artifact " + artifact.getName(), e);
}
} catch (final Exception e) {
throw new PluginException("Failed to install the artifact " + artifact.getName(), e);
}
switch (artifact.getType()) {
@ -283,7 +299,7 @@ public class PluginHelper {
}
}
public Artifact getArtifact(String name, String version) {
public Artifact getArtifact(final String name, final String version) {
if (StringUtil.isBlank(name) || StringUtil.isBlank(version)) {
return null;
}

View file

@ -50,6 +50,7 @@ import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import org.codelibs.core.exception.IORuntimeException;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.core.misc.Pair;
import org.codelibs.fess.Constants;
@ -469,6 +470,14 @@ public class SystemHelper {
return System.getProperty(Constants.FESS_LOG_LEVEL, Level.WARN.toString());
}
public File createTempFile(String prefix, String suffix) {
try {
return File.createTempFile(prefix, suffix);
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
public String getVersion() {
return version;
}
@ -484,5 +493,4 @@ public class SystemHelper {
public String getProductVersion() {
return productVersion;
}
}

View file

@ -2976,6 +2976,15 @@ public class FessLabels extends UserMessages {
/** The key of the message: Install Plugin */
public static final String LABELS_plugin_install_title = "{labels.plugin_install_title}";
/** The key of the message: Jar File */
public static final String LABELS_plugin_jar_file = "{labels.plugin_jar_file}";
/** The key of the message: Local */
public static final String LABELS_plugin_local_install = "{labels.plugin_local_install}";
/** The key of the message: Remote */
public static final String LABELS_plugin_remote_install = "{labels.plugin_remote_install}";
/** The key of the message: Install */
public static final String LABELS_crud_button_install = "{labels.crud_button_install}";

View file

@ -347,6 +347,12 @@ public class FessMessages extends FessLabels {
/** The key of the message: {0} is not supported. */
public static final String ERRORS_file_is_not_supported = "{errors.file_is_not_supported}";
/** The key of the message: {0} is not found. */
public static final String ERRORS_plugin_file_is_not_found = "{errors.plugin_file_is_not_found}";
/** The key of the message: Failed to install {0}. */
public static final String ERRORS_failed_to_install_plugin = "{errors.failed_to_install_plugin}";
/** The key of the message: The given query has unknown condition. */
public static final String ERRORS_invalid_query_unknown = "{errors.invalid_query_unknown}";
@ -2034,6 +2040,36 @@ public class FessMessages extends FessLabels {
return this;
}
/**
* Add the created action message for the key 'errors.plugin_file_is_not_found' with parameters.
* <pre>
* message: {0} is not found.
* </pre>
* @param property The property name for the message. (NotNull)
* @param arg0 The parameter arg0 for message. (NotNull)
* @return this. (NotNull)
*/
public FessMessages addErrorsPluginFileIsNotFound(String property, String arg0) {
assertPropertyNotNull(property);
add(property, new UserMessage(ERRORS_plugin_file_is_not_found, arg0));
return this;
}
/**
* Add the created action message for the key 'errors.failed_to_install_plugin' with parameters.
* <pre>
* message: Failed to install {0}.
* </pre>
* @param property The property name for the message. (NotNull)
* @param arg0 The parameter arg0 for message. (NotNull)
* @return this. (NotNull)
*/
public FessMessages addErrorsFailedToInstallPlugin(String property, String arg0) {
assertPropertyNotNull(property);
add(property, new UserMessage(ERRORS_failed_to_install_plugin, arg0));
return this;
}
/**
* Add the created action message for the key 'errors.invalid_query_unknown' with parameters.
* <pre>

View file

@ -983,4 +983,7 @@ labels.plugin_version=Version
labels.plugin_delete=Delete
labels.plugin_install=Install
labels.plugin_install_title=Install Plugin
labels.plugin_jar_file=Jar File
labels.plugin_local_install=Local
labels.plugin_remote_install=Remote
labels.crud_button_install=Install

View file

@ -983,4 +983,7 @@ labels.plugin_version=Version
labels.plugin_delete=Delete
labels.plugin_install=Install
labels.plugin_install_title=Install Plugin
labels.plugin_jar_file=Jar File
labels.plugin_local_install=Local
labels.plugin_remote_install=Remote
labels.crud_button_install=Install

View file

@ -983,4 +983,7 @@ labels.plugin_version=バージョン
labels.plugin_delete=削除
labels.plugin_install=インストール
labels.plugin_install_title=プラグインのインストール
labels.plugin_jar_file=Jarファイル
labels.plugin_local_install=ローカル
labels.plugin_remote_install=リモート
labels.crud_button_install=インストール

View file

@ -137,6 +137,8 @@ errors.could_not_delete_logged_in_user=Could not delete logged in user.
errors.unauthorized_request=Unauthorized request.
errors.failed_to_print_thread_dump=Failed to print thread dump.
errors.file_is_not_supported={0} is not supported.
errors.plugin_file_is_not_found={0} is not found.
errors.failed_to_install_plugin=Failed to install {0}.
errors.invalid_query_unknown=The given query has unknown condition.
errors.invalid_query_parse_error=The given query is invalid.

View file

@ -133,6 +133,8 @@ errors.could_not_delete_logged_in_user=Could not delete logged in user.
errors.unauthorized_request=Unauthorized request.
errors.failed_to_print_thread_dump=Failed to print thread dump.
errors.file_is_not_supported={0} is not supported.
errors.plugin_file_is_not_found={0} is not found.
errors.failed_to_install_plugin=Failed to install {0}.
errors.invalid_query_unknown=The given query has unknown condition.
errors.invalid_query_parse_error=The given query is invalid.

View file

@ -23,7 +23,7 @@ constraints.NotNull.message = {item} は未入力です。
constraints.Null.message = {item} は null でなければなりません。
constraints.Past.message = {item} は過去の値にする必要があります。
constraints.Pattern.message = {item} が 「{regexp}」 に一致しません。
constraints.Size.message = {item}のサイズは {min} から {max} の範囲にしてください。
constraints.Size.message = {item}のサイズは {min} 文字から {max} 文字の範囲にしてください。
# ----------------------------------------------------------
# Hibernate Validator
# -------------------
@ -139,6 +139,8 @@ errors.invalid_header_for_request_file=ヘッダー行が正しくありませ
errors.could_not_delete_logged_in_user=ログインしているユーザーは削除できません。
errors.failed_to_print_thread_dump=スレッドダンプの出力に失敗しました。
errors.file_is_not_supported={0}はサポートされていません。
errors.plugin_file_is_not_found={0}が見つかりません。
errors.failed_to_install_plugin={0}のインストールに失敗しました。
errors.property_required={0}は必須です。
errors.property_type_integer={0}は数値です。

View file

@ -1,131 +1,129 @@
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><la:message key="labels.admin_brand_title" /> | <la:message
key="labels.plugin_title" /></title>
<jsp:include page="/WEB-INF/view/common/admin/head.jsp"></jsp:include>
<meta charset="UTF-8">
<title><la:message key="labels.admin_brand_title" /> | <la:message key="labels.plugin_title" /></title>
<jsp:include page="/WEB-INF/view/common/admin/head.jsp"></jsp:include>
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
<jsp:include page="/WEB-INF/view/common/admin/header.jsp"></jsp:include>
<jsp:include page="/WEB-INF/view/common/admin/sidebar.jsp">
<jsp:param name="menuCategoryType" value="system" />
<jsp:param name="menuType" value="plugin" />
</jsp:include>
<div class="content-wrapper">
<section class="content-header">
<h1>
<la:message key="labels.plugin_title" />
</h1>
<jsp:include page="/WEB-INF/view/common/admin/crud/breadcrumb.jsp"></jsp:include>
</section>
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">
<la:message key="labels.crud_title_list" />
</h3>
<div class="btn-group pull-right">
<la:link href="installplugin" styleClass="btn btn-success btn-xs">
<em class="fa fa-plus"></em>
<la:message key="labels.plugin_install" />
</la:link>
<div class="wrapper">
<jsp:include page="/WEB-INF/view/common/admin/header.jsp"></jsp:include>
<jsp:include page="/WEB-INF/view/common/admin/sidebar.jsp">
<jsp:param name="menuCategoryType" value="system" />
<jsp:param name="menuType" value="plugin" />
</jsp:include>
<div class="content-wrapper">
<section class="content-header">
<h1>
<la:message key="labels.plugin_title" />
</h1>
<jsp:include page="/WEB-INF/view/common/admin/crud/breadcrumb.jsp"></jsp:include>
</section>
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">
<la:message key="labels.crud_title_list" />
</h3>
<div class="btn-group pull-right">
<la:link href="installplugin" styleClass="btn btn-success btn-xs">
<em class="fa fa-plus"></em>
<la:message key="labels.plugin_install" />
</la:link>
</div>
</div>
<!-- /.box-header -->
<div class="box-body">
<%-- Message --%>
<div>
<la:info id="msg" message="true">
<div class="alert alert-info">${msg}</div>
</la:info>
<la:errors />
</div>
<%-- List --%>
<div class="data-wrapper">
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered table-striped dataTable">
<tbody>
<tr>
<th><la:message key="labels.plugin_type" /></th>
<th><la:message key="labels.plugin_name" /></th>
<th><la:message key="labels.plugin_version" /></th>
<th></th>
</tr>
<c:forEach var="artifact" varStatus="s" items="${installedArtifactItems}">
<tr>
<td>${f:h(artifact.type)}</td>
<td>${f:h(artifact.name)}</td>
<td>${f:h(artifact.version)}</td>
<td>
<button type="button" class="btn btn-danger btn-xs" name="delete" data-toggle="modal"
data-target='#confirmToDelete-${f:h(artifact.name)}-${f:h(artifact.version).replace(".", "\\.")}'
value="<la:message key="labels.design_delete_button" />"
>
<em class="fa fa-trash"></em>
<la:message key="labels.design_delete_button" />
</button>
<div class="modal modal-danger fade" id='confirmToDelete-${f:h(artifact.name)}-${f:h(artifact.version)}'
tabindex="-1" role="dialog"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">
<la:message key="labels.crud_title_delete" />
</h4>
</div>
<div class="modal-body">
<p>
<la:message key="labels.crud_delete_confirmation" />
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline pull-left" data-dismiss="modal">
<la:message key="labels.crud_button_cancel" />
</button>
<la:form action="/admin/plugin/" styleClass="form-horizontal">
<input type="hidden" name="name" value="${f:h(artifact.name)}">
<input type="hidden" name="version" value="${f:h(artifact.version)}">
<button type="submit" class="btn btn-outline btn-danger" name="delete"
value="<la:message key="labels.crud_button_delete" />"
>
<em class="fa fa-trash"></em>
<la:message key="labels.crud_button_delete" />
</button>
</la:form>
</div>
</div>
</div>
</div>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
<!-- /.data-wrapper -->
</div>
<!-- /.box-body -->
</div>
<!-- /.box-header -->
<div class="box-body">
<%-- Message --%>
<div>
<la:info id="msg" message="true">
<div class="alert alert-info">${msg}</div>
</la:info>
<la:errors />
</div>
<%-- List --%>
<div class="data-wrapper">
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered table-striped dataTable">
<tbody>
<tr>
<th><la:message key="labels.plugin_type" /></th>
<th><la:message key="labels.plugin_name" /></th>
<th><la:message key="labels.plugin_version" /></th>
<th></th>
</tr>
<c:forEach var="artifact" varStatus="s"
items="${installedArtifactItems}">
<tr>
<td>${f:h(artifact.type)}</td>
<td>${f:h(artifact.name)}</td>
<td>${f:h(artifact.version)}</td>
<td>
<button type="button" class="btn btn-danger btn-xs" name="delete"
data-toggle="modal" data-target='#confirmToDelete-${f:h(artifact.name)}-${f:h(artifact.version).replace(".", "\\.")}'
value="<la:message key="labels.design_delete_button" />">
<em class="fa fa-trash"></em>
<la:message key="labels.design_delete_button" />
</button>
<div class="modal modal-danger fade" id='confirmToDelete-${f:h(artifact.name)}-${f:h(artifact.version)}'
tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">
<la:message key="labels.crud_title_delete" />
</h4>
</div>
<div class="modal-body">
<p>
<la:message key="labels.crud_delete_confirmation" />
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline pull-left"
data-dismiss="modal">
<la:message key="labels.crud_button_cancel" />
</button>
<la:form action="/admin/plugin/" styleClass="form-horizontal">
<input type="hidden" name="name" value="${f:h(artifact.name)}">
<input type="hidden" name="version" value="${f:h(artifact.version)}">
<button type="submit" class="btn btn-outline btn-danger"
name="delete"
value="<la:message key="labels.crud_button_delete" />">
<em class="fa fa-trash"></em>
<la:message key="labels.crud_button_delete" />
</button>
</la:form>
</div>
</div>
</div>
</div>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
<!-- /.data-wrapper -->
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
</div>
</section>
</div>
<jsp:include page="/WEB-INF/view/common/admin/footer.jsp"></jsp:include>
</div>
<jsp:include page="/WEB-INF/view/common/admin/foot.jsp"></jsp:include>
<!-- /.box -->
</div>
</div>
</section>
</div>
<jsp:include page="/WEB-INF/view/common/admin/footer.jsp"></jsp:include>
</div>
<jsp:include page="/WEB-INF/view/common/admin/foot.jsp"></jsp:include>
</body>
</html>

View file

@ -1,77 +1,97 @@
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><la:message key="labels.admin_brand_title" /> | <la:message
key="labels.plugin_install_title" /></title>
<jsp:include page="/WEB-INF/view/common/admin/head.jsp"></jsp:include>
<meta charset="UTF-8">
<title><la:message key="labels.admin_brand_title" /> | <la:message key="labels.plugin_install_title" /></title>
<jsp:include page="/WEB-INF/view/common/admin/head.jsp"></jsp:include>
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
<jsp:include page="/WEB-INF/view/common/admin/header.jsp"></jsp:include>
<jsp:include page="/WEB-INF/view/common/admin/sidebar.jsp">
<jsp:param name="menuCategoryType" value="system" />
<jsp:param name="menuType" value="plugin" />
</jsp:include>
<div class="content-wrapper">
<section class="content-header">
<h1>
<la:message key="labels.plugin_install_title" />
</h1>
</section>
<section class="content">
<div class="row">
<div class="col-md-12">
<la:info id="msg" message="true">
<div class="alert alert-info">${msg}</div>
</la:info>
<la:errors property="_global" />
</div>
<div class="col-md-6">
<div class="box box-primary">
<la:form action="/admin/plugin/">
<div class="box-header with-border">
<h3 class="box-title">
<la:message key="labels.plugin_install" />
</h3>
</div>
<!-- /.box-header -->
<div class="box-body">
<div class="form-group">
<la:errors property="selectedArtifact" />
<la:select styleId="artifacts" property="id" styleClass="form-control">
<c:forEach var="item" varStatus="s"
items="${availableArtifactItems}">
<la:option value="${f:h(item.id)}">${f:h(item.name)}-${f:h(item.version)}</la:option>
</c:forEach>
</la:select>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-default"
name="back"
value="<la:message key="labels.crud_button_back" />">
<em class="fa fa-arrow-circle-left"></em>
<la:message key="labels.crud_button_back" />
</button>
<button type="submit" class="btn btn-warning"
name="install"
value="<la:message key="labels.crud_button_install" />">
<em class="fa fa-plus"></em>
<la:message key="labels.crud_button_install" />
</button>
</div>
<!-- /.box-footer -->
</la:form>
</div>
<!-- /.box -->
</div>
</div>
</section>
</div>
<jsp:include page="/WEB-INF/view/common/admin/footer.jsp"></jsp:include>
</div>
<jsp:include page="/WEB-INF/view/common/admin/foot.jsp"></jsp:include>
<div class="wrapper">
<jsp:include page="/WEB-INF/view/common/admin/header.jsp"></jsp:include>
<jsp:include page="/WEB-INF/view/common/admin/sidebar.jsp">
<jsp:param name="menuCategoryType" value="system" />
<jsp:param name="menuType" value="plugin" />
</jsp:include>
<div class="content-wrapper">
<section class="content-header">
<h1>
<la:message key="labels.plugin_install_title" />
</h1>
</section>
<section class="content">
<div class="row">
<div class="col-md-12">
<la:info id="msg" message="true">
<div class="alert alert-info">${msg}</div>
</la:info>
<la:errors property="_global" />
</div>
<div class="col-md-6">
<div class="box box-primary">
<la:form action="/admin/plugin/install" enctype="multipart/form-data">
<div class="box-header with-border">
<h3 class="box-title">
<la:message key="labels.plugin_install" />
</h3>
</div>
<!-- /.box-header -->
<div class="box-body">
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#remote" aria-controls="remote" role="tab"
data-toggle="tab"
><la:message key="labels.plugin_remote_install" /></a></li>
<li role="presentation"><a href="#local" aria-controls="local" role="tab" data-toggle="tab"><la:message
key="labels.plugin_local_install"
/></a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="remote">
<div class="box-body">
<div class="form-group">
<la:errors property="selectedArtifact" />
<la:select styleId="artifacts" property="id" styleClass="form-control">
<c:forEach var="item" varStatus="s" items="${availableArtifactItems}">
<la:option value="${f:h(item.id)}">${f:h(item.name)}-${f:h(item.version)}</la:option>
</c:forEach>
</la:select>
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="local">
<div class="box-body">
<div class="form-group">
<label for="name" class="col-md-2 control-label"><la:message key="labels.plugin_jar_file" /></label>
<div>
<input type="file" name="jarFile" />
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-default" name="back" value="<la:message key="labels.crud_button_back" />">
<em class="fa fa-arrow-circle-left"></em>
<la:message key="labels.crud_button_back" />
</button>
<button type="submit" class="btn btn-warning" name="install"
value="<la:message key="labels.crud_button_install" />"
>
<em class="fa fa-plus"></em>
<la:message key="labels.crud_button_install" />
</button>
</div>
<!-- /.box-footer -->
</la:form>
</div>
<!-- /.box -->
</div>
</div>
</section>
</div>
<jsp:include page="/WEB-INF/view/common/admin/footer.jsp"></jsp:include>
</div>
<jsp:include page="/WEB-INF/view/common/admin/foot.jsp"></jsp:include>
</body>
</html>