Java tutorial
/** * Genji Scrum Tool and Issue Tracker * Copyright (C) 2015 Steinbeis GmbH & Co. KG Task Management Solutions * <a href="http://www.trackplus.com">Genji Scrum Tool</a> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* $Id:$ */ package com.aurel.track.prop; import java.io.File; import java.io.Serializable; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.List; import java.util.concurrent.ExecutorService; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpSession; import org.apache.commons.codec.binary.Base64; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.aurel.track.admin.user.person.PersonBL; import com.aurel.track.beans.TClusterNodeBean; import com.aurel.track.beans.TLoggedInUsersBean; import com.aurel.track.beans.TPersonBean; import com.aurel.track.beans.TSiteBean; import com.aurel.track.cluster.ClusterBL; import com.aurel.track.dbase.HandleHome; import com.aurel.track.errors.ErrorData; import com.aurel.track.lucene.index.LuceneIndexer; import com.aurel.track.util.DateTimeUtils; import com.aurel.track.util.LabelValueBean; import com.aurel.track.util.SimpleEncryption; import com.trackplus.license.LicenseManager; /* * This class keeps track on the number of users connected to the database. */ public final class ApplicationBean implements Serializable { private int dbVersion = 503; public static String OPSTATE_RUNNING = "Running"; public static String OPSTATE_MAINTENNANCE = "Maintenance"; private static final long serialVersionUID = 500L; public static final int APPTYPE_FULL = 1; public static final int APPTYPE_DESK = 2; public static final int APPTYPE_BUGS = 3; // ----------------------------------------------------- Instance Variables private static final Logger LOGGER = LogManager.getLogger(ApplicationBean.class); private int maxNumberOfFullUsers = 100000; private int maxNumberOfLimitedUsers = 100000; private String licenseHolder = "GPL"; private Date expDate = DateTimeUtils.getInstance().parseISODate("2099-12-31"); private long instDate = 0; private int edition = 3; // 3 = "ent", 2 = "prof", 1 = "std" private String editionString = "Enterprise"; private int appType = APPTYPE_BUGS; // this and the following will be // overwritten by values in // Version.properties private String appTypeString = ""; // during startup private String extendedKey = null; private static ApplicationBean ref = null; private Integer fullInactive = null; private Integer fullActive = null; private Integer limitedActive = null; private Integer limitedInactive = null; private Boolean isCluster = false; private String latexCommand = null; private String phantomJSCommand = null; private String imageMagickCommand = null; private transient LicenseManager licenseManager = null; private boolean backupInProgress = false; private boolean restoreInProgress = false; private transient ServletContext servletContext = null; private TClusterNodeBean clusterNodeBean = null; private TSiteBean siteBean = null; private transient ExecutorService executor = null; /** * Reuse the lucene indexer instance by reindexing (finished should be true) */ private transient LuceneIndexer luceneIndexer; /* * Make the constructor private, this is a singleton */ private ApplicationBean() { } /** * Singleton <code>ApplicationBean</code> instance. Create one if it does * not yet exist. * * @return the one and only <code>ApplicationBean</code> instance */ public static ApplicationBean getInstance() { if (ref == null) synchronized (ApplicationBean.class) {// While we were waiting for the lock, another thread may have instantiated the object. if (ref == null) { ref = new ApplicationBean(); } } return ref; } /** * Make sure we can't create a second instance by cloning. */ @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); // that'll teach 'em } /** * This <code>ApplicationBean belongs to a single <code>TClusterNode</code>. * If there is no cluster, this is the single running server instance. * * @return this server node */ public TClusterNodeBean getClusterNodeBean() { return clusterNodeBean; } /** * Sets the <code>TClusterNode</code> to this node * * @param clusterNode */ public void setClusterNodeBean(TClusterNodeBean clusterNodeBean) { this.clusterNodeBean = clusterNodeBean; } /** * Whether we are in a cluster or not * * @return */ public boolean isCluster() { return isCluster; } /** * Whether we are in a cluster or not * * @return */ public void setCluster(Boolean _isCluster) { isCluster = _isCluster; } /** * Get the Torque configuration * * @return * @throws ServletException */ public PropertiesConfiguration getDbConfig() { PropertiesConfiguration tcfg = null; try { tcfg = HandleHome.getTorqueProperties(servletContext, false); } catch (Exception e) { LOGGER.error(e.getMessage()); } return tcfg; } /** * Set the servlet context * * @param _servletContext */ public void setServletContext(ServletContext pservletContext) { this.servletContext = pservletContext; } /** * Returns the servlet context * * @return */ public ServletContext getServletContext() { return this.servletContext; } public void setLicenseManager(LicenseManager lm) { licenseManager = lm; } public LicenseManager getLicenseManager() { return licenseManager; } // ----------------------- User section ---------------------------- /** * Get fully licensed users that are inactive * * @return */ public Integer getFullInactive() { return fullInactive; } private void setFullInactive(Integer fullInactive) { this.fullInactive = fullInactive; } public Integer getFullActive() { return fullActive; } private void setFullActive(Integer fullActive) { this.fullActive = fullActive; } public Integer getLimitedActive() { return limitedActive; } private void setLimitedActive(Integer limitedActive) { this.limitedActive = limitedActive; } public Integer getLimitedInactive() { return limitedInactive; } private void setLimitedInactive(Integer limitedInactive) { this.limitedInactive = limitedInactive; } /** * Sets the user counts for the actual users. Considers fully licensed, * active and inactive users as well as easy licensed active and inactive * users. */ public void setActualUsers() { setFullActive(PersonBL.countFullActive()); setFullInactive(PersonBL.countFullInactive()); setLimitedActive(PersonBL.countLimitedActive()); setLimitedInactive(PersonBL.countLimitedInactive()); } // ------ public int getMaxNumberOfFullUsers() { if (licenseManager != null && licenseManager.getLicensedFeature("users") != null) { maxNumberOfFullUsers = licenseManager.getLicensedFeature("users").getNumberOfUsers(); } else { return 2; } return maxNumberOfFullUsers; } public String getLicenseHolder() { if (licenseManager != null) { licenseHolder = licenseManager.getLicenseOwner(); } return licenseHolder; } public int getMaxNumberOfLimitedUsers() { if (licenseManager != null && licenseManager.getLicensedFeature("ext") != null) { maxNumberOfLimitedUsers = licenseManager.getLicensedFeature("ext").getNumberOfUsers(); } else { return 0; } return maxNumberOfLimitedUsers; } // ------------------ End of user section ------------------------- public int getDbVersion() { return dbVersion; } public void setInstDate(long theDate) { instDate = theDate; } public long getInstDate() { return instDate; } public synchronized void addUser(TPersonBean user, String sessionId) { TLoggedInUsersBean loggedInUsersBean = new TLoggedInUsersBean(); TClusterNodeBean lclusterNodeBean = getClusterNodeBean(); if (lclusterNodeBean != null) { loggedInUsersBean.setNodeAddress(lclusterNodeBean.getObjectID()); } else { LOGGER.error("clusterNodeBean is null, this should never happen."); } loggedInUsersBean.setSessionId(sessionId); loggedInUsersBean.setLoggedUser(user.getObjectID()); loggedInUsersBean.setUserLevel(user.getUserLevel()); loggedInUsersBean.setLastUpdate(new Date()); ClusterBL.saveLoggedInUser(loggedInUsersBean); LOGGER.debug("Added user >" + user.getFullName() + "< to loggedIn list"); } /** * session gets invalid */ public synchronized void removeUser(String sessionId) { ClusterBL.removeLoggedInUserBySession(sessionId); } public void removeClusterNode() { TClusterNodeBean lclusterNodeBean = getClusterNodeBean(); if (lclusterNodeBean != null) { // remove the cluster node ClusterBL.delete(clusterNodeBean.getObjectID()); } } /** * Initialize the license and check if it is valid. In case it is valid * update all the user counts and limits. * * @param key * - the license key */ public void initLic(String key) { setExtendedKey(key); if (licenseManager != null) { licenseManager.setLicenseKey(key); } } /** * Check if this license is still valid, in case it is a temporary license. * * @return the number of days this license is still valid */ public int getDaysLicenseValid() { if (licenseManager != null) { return licenseManager.getDaysValid(); } return 7300; // 20 years } public Date getExpDate() { if (licenseManager != null) { expDate = licenseManager.getLicenseExpirationDate(); } return expDate; } /** * @return Returns the extendedKey. */ public String getExtendedKey() { return this.extendedKey; } /* * @param extendedKey The extendedKey to set. */ private void setExtendedKey(String pExtendedKey) { this.extendedKey = pExtendedKey; } /** * @return Returns the edition. */ public int getEdition() { return this.edition; } /** * @param _edition * The program edition (Enterprise, Professional, Standard) */ public void setEdition(String pedition) { this.edition = 3; this.editionString = "Enterprise"; } public String getEditionString() { return this.editionString; } public ErrorData getErrors() { if (licenseManager != null) { return licenseManager.getLicenseErrorText(); } return null; } public int getErrorCode(HttpSession session) { if (licenseManager != null) { return licenseManager.getErrorCode(); } return 0; } public TSiteBean setSiteParams(TSiteBean siteBean) { siteBean.setNumberOfUsers(new Integer(getMaxNumberOfFullUsers() + getMaxNumberOfLimitedUsers())); siteBean.setNumberOfFullUsers(getMaxNumberOfFullUsers()); siteBean.setNumberOfLimitedUsers(getMaxNumberOfLimitedUsers()); siteBean.setExpDate(getExpDate()); this.siteBean = siteBean; return siteBean; } public void setSiteBean(TSiteBean psiteBean) { this.siteBean = psiteBean; } public TSiteBean getSiteBean() { return this.siteBean; } public synchronized boolean isBackupInProgress() { return backupInProgress; } public synchronized void setBackupInProgress(boolean backupInProgress) { this.backupInProgress = backupInProgress; } public synchronized boolean isRestoreInProgress() { return restoreInProgress; } public synchronized void setRestoreInProgress(boolean restoreInProgress) { this.restoreInProgress = restoreInProgress; } private boolean newerVersion = false; public boolean getNewerVersion() { if (siteBean != null && siteBean.getIsVersionReminderOn()) { return newerVersion; } else { return false; } } public void setNewerVersion(boolean nv) { newerVersion = nv; } private Integer mostActualVersion = new Integer(0); public Integer getMostActualVersion() { return mostActualVersion; } public void setMostActualVersion(Integer mav) { if (mav.intValue() > getVersionNo().intValue()) { setNewerVersion(true); } else { setNewerVersion(false); } mostActualVersion = mav; } private String mostActualVersionString = ""; public void setMostActualVersionString(String vs) { mostActualVersionString = vs; } public String getMostActualVersionString() { return mostActualVersionString; } // Salt protected int count = 15; private String CRLF = "\r\n"; /** * Get license properties for this server. * * @return */ public String getProperties() { String result = ""; return result; } /** * Get a comma separated <code>String</code> with IP numbers for this * server. * * @return a comma separated <code>String</code> with IP numbers for this * server. */ public static String getIpNumbersString() { String ipNumbers = ""; for (int i = 0; i < ApplicationBean.getInetAddress().length; ++i) { if (i != 0) { ipNumbers = ipNumbers + (", "); } ipNumbers = ipNumbers + ApplicationBean.getInetAddress()[i].getHostAddress(); } return ipNumbers; } private Integer theVersionNo; public void setVersionNo(Integer pversionNo) { theVersionNo = pversionNo; } private String theVersionDate; public String getVersionDate() { return theVersionDate; } public void setVersionDate(String pversionDate) { theVersionDate = pversionDate; } public Integer getVersionNo() { return theVersionNo; } private String theBuild = null; public void setBuild(String pbuild) { theBuild = pbuild; } public String getBuild() { return theBuild; } private String theVersion = null; public void setVersion(String pversion) { theVersion = pversion; } public String getVersion() { return theVersion; } public int getAppType() { return appType; } public void setAppType(int appType) { } public String getAppTypeString() { return "Genji"; } public boolean isGenji() { return ApplicationBean.getInstance().getAppType() == ApplicationBean.APPTYPE_BUGS; } public void setAppTypeString(String appTypeString) { this.appTypeString = appTypeString; } public int getAppTypeDesk() { return APPTYPE_DESK; } public int getAppTypeBugs() { return APPTYPE_BUGS; } public int getAppTypeFull() { return APPTYPE_FULL; } private List<LabelValueBean> backupErrors; /** * Get a list with errors that occurred during backup. * * @return a list of <code>LabelValueBean</code>s with backup errors */ public List<LabelValueBean> getBackupErrors() { return backupErrors; } public void setBackupErrors(List<LabelValueBean> errors) { backupErrors = errors; } private List<LabelValueBean> designs = new ArrayList<LabelValueBean>(); public List<LabelValueBean> getDesigns() { return designs; } public void setDesigns(List<LabelValueBean> pdesigns) { designs = pdesigns; } /** * Retrieve all non-loopback IP addresses from all network interfaces * * @return the array of assigned IP numbers */ public static InetAddress[] getInetAddress() { List<InetAddress> allIPs = new ArrayList<InetAddress>(); InetAddress[] allAds = null; try { InetAddress candidateAddress = null; // Iterate all NICs (network interface cards)... for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces .hasMoreElements();) { NetworkInterface iface = (NetworkInterface) ifaces.nextElement(); // Iterate all IP addresses assigned to each card... for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) { InetAddress inetAddr = (InetAddress) inetAddrs.nextElement(); if (!inetAddr.isLoopbackAddress()) { if (inetAddr.isSiteLocalAddress()) { // Found non-loopback site-local address. Return it // immediately... allIPs.add(inetAddr); continue; } else if (candidateAddress == null) { // Found non-loopback address, but not necessarily // site-local. // Store it as a candidate to be returned if // site-local address is not subsequently found... candidateAddress = inetAddr; // Note that we don't repeatedly assign non-loopback // non-site-local addresses as candidates, // only the first. For subsequent iterations, // candidate will be non-null. } } } } // At this point, we did not find a non-loopback address. // Fall back to returning whatever InetAddress.getLocalHost() // returns... if (allIPs.isEmpty()) { allIPs.add(InetAddress.getLocalHost()); } allAds = new InetAddress[allIPs.size()]; allAds = allIPs.toArray(allAds); } catch (Exception uhn) { LOGGER.error( "An exception occurred trying to get " + "all IP addresses for this host: " + uhn.getMessage()); } return allAds; } public ExecutorService getExecutor() { return executor; } public void setExecutor(ExecutorService executor) { this.executor = executor; } public LuceneIndexer getLuceneIndexer() { return luceneIndexer; } public void setLuceneIndexer(LuceneIndexer luceneIndexer) { this.luceneIndexer = luceneIndexer; } /** * Get the complete path to the xelatex command on WWindows, OS/X, and Linux * operating systems. * @return something like "/usr/texbin/xelatex" */ public String getLatexCommand() { if (this.latexCommand == null || "".equals(this.latexCommand)) { String os = System.getProperty("os.name").toLowerCase(); String cmdPath = HandleHome.getTrackplus_Home() + "/ExportTemplates/latexTemplates/latex.sh"; if (os.indexOf("mac") >= 0) { this.latexCommand = "/usr/texbin/xelatex"; // cmdPath if (!new File(this.latexCommand).exists()) { this.latexCommand = "/Library/TeX/texbin/xelatex"; } } if (os.indexOf("win") >= 0) { this.latexCommand = getLatexCommandPathWin(); } if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) { this.latexCommand = cmdPath; } } if (this.latexCommand == null && System.getProperty(HandleHome.LATEX_HOME) != null) { this.latexCommand = System.getProperty(HandleHome.LATEX_HOME) + File.separator + "xelatex"; } File test = null; if (this.latexCommand != null && !"".equals(this.latexCommand)) { test = new File(this.latexCommand); } if (test != null && !test.exists()) { this.latexCommand = null; } return this.latexCommand; } public void setLatexCommand(String cmd) { this.latexCommand = cmd; } private String getLatexCommandPathWin() { String path = null; for (String ix : System.getenv().keySet()) { String value = System.getenv().get(ix); if (ix.toUpperCase().contains("MIKTEX")) { path = value; break; } if (ix.equals("Path")) { String[] parts = value.split(";"); for (String aPart : parts) { if (aPart.toUpperCase().contains("MIKTEX")) { path = aPart; break; } } } } if (path != null && path.length() > 1) { if (!path.endsWith("\\")) { path += "\\"; } path += "xelatex.exe"; } if (path == null && System.getProperty(HandleHome.LATEX_HOME) != null) { path = System.getProperty(HandleHome.LATEX_HOME); } return path; } /** * Get the complete path to the ImageMagick "convert" command for Windows, * OS/X, and Linux operating systems. * * @return something like "/usr/local/bin/convert" */ public String getImageMagickCommand() { if (this.imageMagickCommand == null || "".equals(this.imageMagickCommand)) { String os = System.getProperty("os.name").toLowerCase(); if (os.indexOf("mac") >= 0) { this.imageMagickCommand = "/usr/local/bin/convert"; } if (os.indexOf("win") >= 0) { this.imageMagickCommand = getImageMagicCommandPathWin(); } if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) { this.imageMagickCommand = "/usr/bin/convert"; } } if (this.imageMagickCommand != null) { this.imageMagickCommand = this.imageMagickCommand.replace("\\", "/"); } File test = new File(this.imageMagickCommand); if (!test.exists()) { this.imageMagickCommand = null; } if (this.imageMagickCommand == null && System.getProperty(HandleHome.IMAGEMAGICK_HOME) != null) { this.imageMagickCommand = System.getProperty(HandleHome.IMAGEMAGICK_HOME); } return this.imageMagickCommand; } /** * Set the complete path to the ImageMagick command "convert" * * @param _imageMagickCommand */ public void setImageMagickCommand(String pimageMagickCommand) { this.imageMagickCommand = pimageMagickCommand; } private String getImageMagicCommandPathWin() { String path = null; for (String ix : System.getenv().keySet()) { String value = System.getenv().get(ix); if (ix.toUpperCase().contains("IMAGEMAGICK")) { path = value; break; } if ("Path".equals(ix)) { String[] parts = value.split(";"); for (String aPart : parts) { if (aPart.toUpperCase().contains("IMAGEMAGICK")) { path = aPart; break; } } } } if (path != null && path.length() > 1) { if (!path.endsWith("\\")) { path += File.separator; } path += "convert.exe"; } if ((path == null) && System.getProperty(HandleHome.IMAGEMAGICK_HOME) != null) { path = System.getProperty(HandleHome.IMAGEMAGICK_HOME); } if (path != null) { path = path.replace("\\", "/"); } return path; } /** * Attempts to obtain the complete path to the phantomJS command on various * operating systems (Windows, OS/X, Linux) * * @return something like "/usr/local/bin/phantomjs" */ public String getPhantomJSCommand() { if (this.phantomJSCommand == null || "".equals(this.phantomJSCommand)) { String os = System.getProperty("os.name").toLowerCase(); if (os.indexOf("mac") >= 0) { this.phantomJSCommand = "/usr/local/bin/phantomjs"; } if (os.indexOf("win") >= 0) { this.phantomJSCommand = getPhantomJSCommandPathWin(); } if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) { this.phantomJSCommand = "/usr/bin/phantomjs"; } } File test = new File(this.phantomJSCommand); if (!test.exists()) { this.phantomJSCommand = null; } if (this.phantomJSCommand == null && System.getProperty(HandleHome.PHANTOMJS_HOME) != null) { this.phantomJSCommand = System.getProperty(HandleHome.PHANTOMJS_HOME); } return this.phantomJSCommand; } public void setPhantomJSCommand(String cmd) { this.phantomJSCommand = cmd; } private String getPhantomJSCommandPathWin() { String path = null; for (String ix : System.getenv().keySet()) { String value = System.getenv().get(ix); if (ix.toUpperCase().contains("PHANTOMJS")) { path = value; break; } if ("Path".equals(ix)) { String[] parts = value.split(";"); for (String aPart : parts) { if (aPart.toUpperCase().contains("PHANTOMJS")) { path = aPart; break; } } } } if (path != null && path.length() > 1) { if (!path.endsWith("\\")) { path += File.separator; } path += "phantomjs.exe"; } if (path == null) { if (System.getProperty(HandleHome.PHANTOMJS_HOME) != null) { path = System.getProperty(HandleHome.PHANTOMJS_HOME); } } if (path != null) { path = path.replace("\\", "/"); } return path; } private boolean inTestMode = false; public boolean isInTestMode() { return inTestMode; } public void setInTestMode(boolean inTestMode) { this.inTestMode = inTestMode; } /** * Whether budget (top down plan) is available * * @return */ public boolean getBudgetActive() { return !getInstance().isGenji() && getInstance().getSiteBean().getBudgetActive(); } private List<String> installProblem; public void setInstallProblem(List<String> list) { installProblem = list; } public List<String> getInstallProblem() { return installProblem; } /* * The maximum length of the description field in an issue. This is database * dependent. */ private int descriptionMaxLength = 4000; public int getDescriptionMaxLength() { return descriptionMaxLength; } public void setDescriptionMaxLength(int length) { descriptionMaxLength = length; } /* * The maximum length of a comment in the trail of an issue. This is * database dependent. */ private int commentMaxLength = 4000; public int getCommentMaxLength() { return commentMaxLength; } public void setCommentMaxLength(int length) { commentMaxLength = length; } }