Java tutorial
package org.ff4j.web; /* * #%L AdministrationConsoleServlet.java (ff4j-web) by Cedrick LUNVEN %% Copyright (C) 2013 Ff4J %% 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. #L% */ import static org.ff4j.web.AdministrationConsoleRenderer.DESCRIPTION; import static org.ff4j.web.AdministrationConsoleRenderer.FEATID; import static org.ff4j.web.AdministrationConsoleRenderer.FLIPFILE; import static org.ff4j.web.AdministrationConsoleRenderer.OPERATION; import static org.ff4j.web.AdministrationConsoleRenderer.OP_ADD_FEATURE; import static org.ff4j.web.AdministrationConsoleRenderer.OP_ADD_ROLE; import static org.ff4j.web.AdministrationConsoleRenderer.OP_DISABLE; import static org.ff4j.web.AdministrationConsoleRenderer.OP_EDIT_FEATURE; import static org.ff4j.web.AdministrationConsoleRenderer.OP_ENABLE; import static org.ff4j.web.AdministrationConsoleRenderer.OP_EXPORT; import static org.ff4j.web.AdministrationConsoleRenderer.OP_RMV_FEATURE; import static org.ff4j.web.AdministrationConsoleRenderer.OP_RMV_ROLE; import static org.ff4j.web.AdministrationConsoleRenderer.ROLE; import static org.ff4j.web.AdministrationConsoleRenderer.renderButtonDeleteFeature; import static org.ff4j.web.AdministrationConsoleRenderer.renderButtonEditFeature; import static org.ff4j.web.AdministrationConsoleRenderer.renderButtonUserRole; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.text.MessageFormat; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; import org.ff4j.FF4j; import org.ff4j.core.Feature; import org.ff4j.core.FeatureXmlParser; /** * Unique Servlet to manage FlipPoints and security * * @author <a href="mailto:cedrick.lunven@gmail.com">Cedrick LUNVEN</a> */ public class AdministrationConsoleServlet extends HttpServlet { /** serial number. */ private static final long serialVersionUID = -3982043895954284269L; /** Buffer size. */ private static final int BUFFER_SIZE = 4096; /** {@inheritDoc} */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String message = null; String messagetype = "info"; // Routing on pagename String operation = req.getParameter(OPERATION); // Idependant of page to display (not same ops) try { if (operation != null && !operation.isEmpty()) { if (OP_DISABLE.equalsIgnoreCase(operation)) { opDisableFeature(req); message = buildMessage(req.getParameter(FEATID), "DISABLED"); } else if (OP_ENABLE.equalsIgnoreCase(operation)) { opEnableFeature(req); message = buildMessage(req.getParameter(FEATID), "ENABLED"); } else if (OP_EDIT_FEATURE.equalsIgnoreCase(operation)) { opUpdateFeatureDescription(req); message = buildMessage(req.getParameter(FEATID), "UPDATED"); } else if (OP_ADD_FEATURE.equalsIgnoreCase(operation)) { opAddNewFeature(req); message = buildMessage(req.getParameter(FEATID), "ADDED"); } else if (OP_RMV_FEATURE.equalsIgnoreCase(operation)) { opDeleteFeature(req); message = buildMessage(req.getParameter(FEATID), "DELETED"); } else if (OP_ADD_ROLE.equalsIgnoreCase(operation)) { opAddRoleToFeature(req); message = "Role <b>" + req.getParameter(ROLE) + "</b> has been successfully added to flipPoint <b>" + req.getParameter(FEATID) + " </b>"; } else if (OP_RMV_ROLE.equalsIgnoreCase(operation)) { opRemoveRoleFromFeature(req); message = "Role <b>" + req.getParameter(ROLE) + "</b> has been successfully removed from flipPoint <b>" + req.getParameter(FEATID) + " </b>"; } else if (OP_EXPORT.equalsIgnoreCase(operation)) { buildResponseForExportFeature(res); } } } catch (Exception e) { messagetype = "error"; message = e.getMessage(); } renderPage(req, res, message, messagetype); } /** * Build info messages. * * @param featureName * target feature name * @param operationd * target operationId * @return */ private String buildMessage(String featureName, String operationId) { return String.format("Feature <b>%s</b> has been successfully %s", featureName, operationId); } /** * Build Http response when invoking export features. * * @param res * http response * @throws IOException * error when building response */ private void buildResponseForExportFeature(HttpServletResponse res) throws IOException { InputStream in = new FeatureXmlParser().exportFeatures(getFf4j().getStore().readAll()); ServletOutputStream sos = null; try { sos = res.getOutputStream(); res.setContentType("text/xml"); res.setHeader("Content-Disposition", "attachment; filename=\"ff4j.xml\""); // res.setContentLength() byte[] bbuf = new byte[BUFFER_SIZE]; int length = 0; while ((in != null) && (length != -1)) { length = in.read(bbuf); sos.write(bbuf, 0, length); } } finally { if (in != null) { in.close(); } if (sos != null) { sos.flush(); sos.close(); } } } /** {@inheritDoc} */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String message = null; String messagetype = "error"; try { List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(req); for (FileItem item : items) { if (item.isFormField()) { if (OPERATION.equalsIgnoreCase(item.getFieldName())) { // String operation = item.getString(); // Proceed here action accessing through POST } } else if (FLIPFILE.equalsIgnoreCase(item.getFieldName())) { String filename = FilenameUtils.getName(item.getName()); if (filename.toLowerCase().endsWith("xml")) { opImportFile(item.getInputStream()); } else { messagetype = "error"; message = "Invalid FILE, must be CSV, XML or PROPERTIES files"; } } } } catch (Exception e) { message = e.getMessage(); } renderPage(req, res, message, messagetype); } /** * Render the ff4f console webpage through different block. * * @param req * http request (with parameters) * @param res * http response (with outouput test) * @param message * text in the information box (blue/green/orange/red) * @param messagetype * type of informatice message (info,success,warning,error) * @throws IOException * error during populating http response */ private void renderPage(HttpServletRequest req, HttpServletResponse res, String message, String messagetype) throws IOException { // Render PAGE res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.println(AdministrationConsoleRenderer.HEADER); out.println(AdministrationConsoleRenderer.renderNavBar(req)); out.println("<div class=\"container\">"); out.print(renderSectionFeatures(req, message, messagetype)); out.println(AdministrationConsoleRenderer.renderModalEditFlip(req)); out.println(AdministrationConsoleRenderer.renderModalNewFlipPoint(req)); out.println(AdministrationConsoleRenderer.renderModalImportFlipPoints(req)); out.println("</body>"); out.println("</html>"); } /** * User action to enable a Feature. * * @param req * http request containing operation parameters */ private void opEnableFeature(HttpServletRequest req) { final String featureId = req.getParameter(FEATID); if (featureId != null && !featureId.isEmpty()) { getFf4j().enable(featureId); } } /** * User action to disable a Feature. * * @param req * http request containing operation parameters */ private void opDisableFeature(HttpServletRequest req) { final String featureId = req.getParameter(FEATID); if (featureId != null && !featureId.isEmpty()) { getFf4j().disable(featureId); } } /** * User action to create a new Feature. * * @param req * http request containing operation parameters */ private void opAddNewFeature(HttpServletRequest req) { final String featureId = req.getParameter(FEATID); final String featureDesc = req.getParameter(DESCRIPTION); if (featureId != null && !featureId.isEmpty()) { Feature fp = new Feature(featureId, false, featureDesc); getFf4j().getStore().create(fp); } } /** * User action to delete a new Feature. * * @param req * http request containing operation parameters */ private void opDeleteFeature(HttpServletRequest req) { final String featureId = req.getParameter(FEATID); if (featureId != null && !featureId.isEmpty()) { getFf4j().getStore().delete(featureId); } } /** * User action to update a target feature's description. * * @param req * http request containing operation parameters */ private void opUpdateFeatureDescription(HttpServletRequest req) { final String featureId = req.getParameter(FEATID); final String description = req.getParameter(DESCRIPTION); if (featureId != null && !featureId.isEmpty()) { Feature fp = getFf4j().getStore().read(featureId); fp.setDescription(description); getFf4j().getStore().update(fp); } } /** * User action to add a role to feature. * * @param req * http request containing operation parameters */ private void opAddRoleToFeature(HttpServletRequest req) { final String flipId = req.getParameter(FEATID); final String roleName = req.getParameter(ROLE); getFf4j().getStore().grantRoleOnFeature(flipId, roleName); } /** * User action to remove a role from feature. * * @param req * http request containing operation parameters */ private void opRemoveRoleFromFeature(HttpServletRequest req) { final String flipId = req.getParameter(FEATID); final String roleName = req.getParameter(ROLE); getFf4j().getStore().removeRoleFromFeature(flipId, roleName); } /** * User action to import Features from a properties files. * * @param in * inpustream from configuration file * @throws IOException * Error raised if the configuration cannot be read */ private void opImportFile(InputStream in) throws IOException { Map<String, Feature> mapsOfFeat = new FeatureXmlParser().parseConfigurationFile(in); for (Entry<String, Feature> feature : mapsOfFeat.entrySet()) { if (getFf4j().getStore().exist(feature.getKey())) { getFf4j().getStore().update(feature.getValue()); } else { getFf4j().getStore().create(feature.getValue()); } } } /** * Produce HTML output to display the feature table. * * @param req * http request containing parameters * @return HTML text output */ private String renderSectionFeatures(HttpServletRequest req, String message, String type) { Map<String, Feature> mapOfFlipPoints = new LinkedHashMap<String, Feature>(); if (getFf4j().getFeatures() != null && !getFf4j().getFeatures().isEmpty()) { mapOfFlipPoints.putAll(getFf4j().getFeatures()); } StringBuilder strB = new StringBuilder(AdministrationConsoleRenderer.renderButtonsMainGroup(req)); if (message != null && !message.isEmpty()) { strB.append(AdministrationConsoleRenderer.renderMessageBox(message, type)); } strB.append(AdministrationConsoleRenderer.TABLE_HEADER); for (Feature fp : mapOfFlipPoints.values()) { strB.append("<tr>"); strB.append("<td style=\"width:150px;font-weight:bold\">" + fp.getUid() + "</td>"); if (fp.getGroup() != null) { strB.append("<td style=\"width:100px;\">" + fp.getGroup() + "</td>"); } else { strB.append("<td style=\"width:100px;\"></td>"); } if (fp.getDescription() != null) { strB.append("<td style=\"width:200px;\">" + fp.getDescription() + "</td>"); } else { strB.append("<td style=\"width:200px;\"></td>"); } strB.append("<td>"); Map<String, String> mapP = new LinkedHashMap<String, String>(); mapP.put("uid", fp.getUid()); if (fp.isEnable()) { strB.append(AdministrationConsoleRenderer.renderElementButton(req, "Enabled", "success", "disable", mapP, null)); } else { strB.append(AdministrationConsoleRenderer.renderElementButton(req, "Disabled", "danger", "enable", mapP, null)); } strB.append("</td>"); strB.append( "<td style=\"width:20px;\">" + renderButtonEditFeature(getFf4j(), req, fp.getUid()) + "</td>"); strB.append("<td style=\"width:20px;\">" + renderButtonDeleteFeature(req, fp.getUid()) + "</td>"); strB.append("<td style=\"width:85px;\">"); if (getFf4j().getAuthorizationsManager() != null) { strB.append(renderButtonUserRole(getFf4j(), req, fp)); } else { strB.append("<center><span style=\"color:#AAAAAA\">N/A</span></center>"); } strB.append("</td>"); strB.append("</tr>"); } strB.append(MessageFormat.format(AdministrationConsoleRenderer.TABLE_FEATURES_FOOTER, req.getContextPath() + req.getServletPath())); return strB.toString(); } /** * Getter accessor for attribute 'ff4j'. * * @return current value of 'ff4j' */ public FF4j getFf4j() { return FF4jWebContextHolder.getFf4j(); } }