Java tutorial
/* * ConcourseConnect * Copyright 2009 Concursive Corporation * http://www.concursive.com * * This file is part of ConcourseConnect, an open source social business * software and community platform. * * Concursive ConcourseConnect is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, version 3 of the License. * * Under the terms of the GNU Affero General Public License you must release the * complete source code for any application that uses any part of ConcourseConnect * (system header files and libraries used by the operating system are excluded). * These terms must be included in any work that has ConcourseConnect components. * If you are developing and distributing open source applications under the * GNU Affero General Public License, then you are free to use ConcourseConnect * under the GNU Affero General Public License. * * If you are deploying a web site in which users interact with any portion of * ConcourseConnect over a network, the complete source code changes must be made * available. For example, include a link to the source archive directly from * your web site. * * For OEMs, ISVs, SIs and VARs who distribute ConcourseConnect with their * products, and do not license and distribute their source code under the GNU * Affero General Public License, Concursive provides a flexible commercial * license. * * To anyone in doubt, we recommend the commercial license. Our commercial license * is competitively priced and will eliminate any confusion about how * ConcourseConnect can be used and distributed. * * ConcourseConnect 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 Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with ConcourseConnect. If not, see <http://www.gnu.org/licenses/>. * * Attribution Notice: ConcourseConnect is an Original Work of software created * by Concursive Corporation */ package com.concursive.connect.web.modules.setup.utils; import bsh.Interpreter; import com.concursive.commons.api.APIConnection; import com.concursive.commons.api.APIRestore; import com.concursive.commons.codec.PasswordHash; import com.concursive.commons.db.ConnectionElement; import com.concursive.commons.db.ConnectionPool; import com.concursive.commons.db.DatabaseUtils; import com.concursive.commons.text.StringUtils; import com.concursive.commons.xml.XMLUtils; import com.concursive.connect.Constants; import com.concursive.connect.cache.CacheContext; import com.concursive.connect.cache.Caches; import com.concursive.connect.cache.utils.CacheUtils; import com.concursive.connect.config.ApplicationPrefs; import com.concursive.connect.web.modules.api.beans.PacketContext; import com.concursive.connect.web.modules.api.dao.SyncTableList; import com.concursive.connect.web.modules.api.utils.TransactionUtils; import com.concursive.connect.web.modules.login.dao.User; import com.concursive.connect.web.modules.login.dao.UserList; import com.concursive.connect.web.modules.members.dao.TeamMember; import com.concursive.connect.web.modules.profile.dao.*; import com.concursive.connect.web.modules.upgrade.utils.UpgradeUtils; import com.concursive.connect.web.utils.LookupList; import net.sf.ehcache.CacheManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.servlet.ServletContext; import java.io.*; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; /** * Utilities for setting up and validating a ConcourseConnect installation * * @author matt rajkowski * @version $Id$ * @created Nov 29, 2005 */ public class SetupUtils { private static Log LOG = LogFactory.getLog(SetupUtils.class); public final static String fs = System.getProperty("file.separator"); /** * This method is used by the ant task to install any default data * * @param args database connection settings: driver, url, user, password */ public static void main(String[] args) { // Connection values String driver = args[0]; String url = args[1]; String user = args[2]; String password = args[3]; String fileLibraryPath = args[4]; String title = args[5]; String description = args[6]; String keywords = args[7]; String purpose = args[8]; String userfirst = args[9]; String userlast = args[10]; String useremail = args[11]; String userpass = args[12]; // Insert default data ConnectionPool cp = new ConnectionPool(); Connection db = null; try { ConnectionElement ce = new ConnectionElement(url, user, password); ce.setDriver(driver); db = cp.getConnection(ce, true); // Instantiate the caches CacheManager.create(); CacheContext cacheContext = new CacheContext(); cacheContext.setUpgradeConnection(db); Caches.addCaches(cacheContext); // Load the object map and services int SYSTEM_ID = 1; SyncTableList syncTableList = new SyncTableList(); syncTableList.setSystemId(SYSTEM_ID); // Load the core object map syncTableList.loadObjectMap(SyncTableList.class.getResourceAsStream("/object_map.xml")); // Load plug-in mappings in the services path File[] serviceFiles = new File("src/main/webapp/WEB-INF/services").listFiles(); if (serviceFiles != null && serviceFiles.length > 0) { for (File thisFile : serviceFiles) { if (thisFile.getAbsolutePath().endsWith(".xml")) { try { LOG.info("Adding services from... " + thisFile.getAbsolutePath()); syncTableList.loadObjectMap(new FileInputStream(thisFile)); } catch (Exception e) { LOG.error("getObjectMap exception", e); } } } } // The default category information insertDefaultCategories(db, syncTableList, fileLibraryPath); // Insert admin user if (useremail != null && userpass != null) { User adminUser = new User(); adminUser.setFirstName(userfirst); adminUser.setLastName(userlast); adminUser.setUsername(useremail); adminUser.setEmail(useremail); adminUser.setPassword1(userpass); adminUser.setPassword2(userpass); insertDefaultAdmin(db, adminUser, null, null); } // The default system profile Project project = new Project(); project.setTitle(title); project.setShortDescription(description); project.setKeywords(keywords); insertDefaultSiteConfig(db, fileLibraryPath, project, purpose, new ApplicationPrefs()); // The default profile content insertDefaultContent(db, syncTableList, fileLibraryPath, project); } catch (Exception e) { e.printStackTrace(System.out); LOG.error(e); System.exit(2); } finally { LOG.info("Cleaning up..."); CacheManager.getInstance().shutdown(); cp.free(db); } System.exit(0); } /** * Determines if the application is fully configured * * @param prefs * @return */ public static boolean isConfigured(ApplicationPrefs prefs) { return prefs.isConfigured(); } /** * Determines if the services component of installation is fully configured * * @param prefs * @return */ public static boolean isServicesConfigured(ApplicationPrefs prefs) { return prefs.has(ApplicationPrefs.CONCURSIVE_SERVICES_ID); } /** * Determines if the database schema has been created * * @param db * @return */ public static boolean isDatabaseInstalled(Connection db) { int count = -1; try { Statement st = db.createStatement(); ResultSet rs = st.executeQuery("SELECT count(*) AS recordcount " + "FROM database_version "); rs.next(); count = rs.getInt("recordcount"); rs.close(); st.close(); } catch (Exception e) { } return count > 0; } /** * Determines if there is an administrative user configured in the database * * @param db * @return */ public static boolean isAdminInstalled(Connection db) { int count = -1; try { PreparedStatement pst = db.prepareStatement( "SELECT count(*) AS recordcount " + "FROM users " + "WHERE access_admin = ? "); pst.setBoolean(1, true); ResultSet rs = pst.executeQuery(); rs.next(); count = rs.getInt("recordcount"); rs.close(); pst.close(); } catch (Exception e) { } return count > 0; } /** * Determines if a default project has been installed * * @param db * @return */ public static boolean isDefaultProjectInstalled(Connection db) { int count = -1; try { PreparedStatement pst = db.prepareStatement( "SELECT count(*) AS recordcount " + "FROM projects " + "WHERE system_default = ? "); pst.setBoolean(1, true); ResultSet rs = pst.executeQuery(); rs.next(); count = rs.getInt("recordcount"); rs.close(); pst.close(); } catch (Exception e) { } return count > 0; } /** * Inserts the default database data * * @param db * @param context * @param setupPath * @throws Exception */ public static void insertDefaultData(Connection db, ServletContext context, String setupPath) throws Exception { // Prepare the BSH interpreter Interpreter script = new Interpreter(); script.set("db", db); // Default database inserts InputStream source = context.getResourceAsStream(setupPath + "common" + fs + "install.bsh"); BufferedReader in = new BufferedReader(new InputStreamReader(source)); script.eval(in); in.close(); // Module Defaults String initPath = setupPath + "init" + fs; DatabaseUtils.executeSQL(db, context.getResourceAsStream(initPath + "project.sql"), true); DatabaseUtils.executeSQL(db, context.getResourceAsStream(initPath + "task.sql"), true); DatabaseUtils.executeSQL(db, context.getResourceAsStream(initPath + "ticket.sql"), true); // Bring the version database up-to-date with the upgrade utility ArrayList<String> versionList = UpgradeUtils .retrieveDatabaseVersions(context.getResourceAsStream(setupPath + "database_versions.txt")); for (String version : versionList) { if (version.length() == 10) { UpgradeUtils.addVersion(db, version); } } } public static void insertDefaultAdmin(Connection db, User thisUser, String ip, ApplicationPrefs prefs) throws Exception { if (thisUser.getUsername() == null || thisUser.getPassword1() == null) { throw new Exception("Missing required fields"); } // Insert the user thisUser.setPassword(PasswordHash.encrypt(thisUser.getPassword1())); thisUser.setGroupId(1); thisUser.setDepartmentId(1); thisUser.setAccessAdmin(true); thisUser.setAccessInvite(true); thisUser.setAccessUserSettings(true); thisUser.setAccessGuestProjects(true); thisUser.setAccessAddProjects(true); thisUser.setEnteredBy(0); thisUser.setModifiedBy(0); thisUser.setStartPage(1); thisUser.setEnabled(true); thisUser.setAccountSize("-1"); thisUser.insert(db, ip, prefs); } /** * Inserts additional default data * * @param db * @param syncTableList the mapping of objects and services * @param fileLibraryPath * @throws Exception */ public static void insertDefaultCategories(Connection db, SyncTableList syncTableList, String fileLibraryPath) throws Exception { int SYSTEM_ID = 1; // From the Service action method PacketContext packetContext = new PacketContext(); packetContext.setObjectMap(syncTableList.getObjectMapping(SYSTEM_ID)); packetContext.setBaseFilePath(fileLibraryPath); // Retrieve and stream the records to restore LOG.debug("Loading the configuration xml..."); InputStream inputStream = SetupUtils.class.getResourceAsStream("/configuration_en_US.xml"); // Restore the state of the objects as-supplied, start by deleting the record and dependents ArrayList<String> meta = new ArrayList<String>(); meta.add("mode=copy"); ArrayList exclude = new ArrayList(); HashMap replace = new HashMap(); replace.put("enteredBy", "1"); replace.put("modifiedBy", "1"); replace.put("thumbnailFilename", "null"); replace.put("logoId", "-1"); HashMap options = new HashMap(); options.put("exclude", exclude); options.put("replace", replace); // Use the APIConnection to do the shared work LOG.debug("Parsing the records..."); APIConnection api = new APIConnection(); api.setAutoCommit(false); api.setTransactionMeta(meta); APIRestore.restore(api, inputStream, null, -1, options); // Construct the xml LOG.debug("Generating XML..."); XMLUtils xml = new XMLUtils(api.generateXMLPacket()); // Restore this item TransactionUtils.processTransactions(db, xml, packetContext); LOG.debug("Finished."); } public static void insertDefaultSiteConfig(Connection db, String fileLibraryPath, Project project, String purpose, ApplicationPrefs prefs) throws Exception { LOG.debug("insertDefaultSiteConfig"); // Validate the pre-reqs if (!StringUtils.hasText(project.getTitle()) || !StringUtils.hasText(project.getShortDescription()) || !StringUtils.hasText(project.getKeywords())) { throw new Exception("Title, description, keywords are required"); } // Load the categories ProjectCategoryList categoryList = new ProjectCategoryList(); categoryList.setTopLevelOnly(true); categoryList.buildList(db); // Determine the default's category int categoryId = categoryList.getIdFromValue("Groups"); // Determine the tabs boolean isPrivate = false; ProjectCategoryList validCategoryList = new ProjectCategoryList(); if ("social".equals(purpose)) { validCategoryList.add(categoryList.getFromValue("Groups")); validCategoryList.add(categoryList.getFromValue("People")); validCategoryList.add(categoryList.getFromValue("Events")); validCategoryList.add(categoryList.getFromValue("Ideas")); validCategoryList.add(categoryList.getFromValue("Sponsors")); } else if ("directory".equals(purpose)) { validCategoryList.add(categoryList.getFromValue("Businesses")); validCategoryList.add(categoryList.getFromValue("Organizations")); validCategoryList.add(categoryList.getFromValue("Groups")); validCategoryList.add(categoryList.getFromValue("People")); validCategoryList.add(categoryList.getFromValue("Places")); validCategoryList.add(categoryList.getFromValue("Events")); validCategoryList.add(categoryList.getFromValue("Ideas")); } else if ("community".equals(purpose)) { validCategoryList.add(categoryList.getFromValue("Groups")); validCategoryList.add(categoryList.getFromValue("People")); validCategoryList.add(categoryList.getFromValue("Ideas")); } else if ("intranet".equals(purpose)) { isPrivate = true; prefs.add(ApplicationPrefs.INFORMATION_IS_SENSITIVE, "true"); prefs.add(ApplicationPrefs.USERS_CAN_REGISTER, "false"); prefs.add(ApplicationPrefs.USERS_CAN_INVITE, "false"); prefs.add(ApplicationPrefs.USERS_CAN_START_PROJECTS, "true"); validCategoryList.add(categoryList.getFromValue("Groups")); validCategoryList.add(categoryList.getFromValue("People")); validCategoryList.add(categoryList.getFromValue("Events")); validCategoryList.add(categoryList.getFromValue("Ideas")); validCategoryList.add(categoryList.getFromValue("Projects")); } else if ("projects".equals(purpose)) { isPrivate = true; prefs.add(ApplicationPrefs.INFORMATION_IS_SENSITIVE, "true"); prefs.add(ApplicationPrefs.USERS_CAN_REGISTER, "false"); prefs.add(ApplicationPrefs.USERS_CAN_INVITE, "false"); validCategoryList.add(categoryList.getFromValue("Groups")); validCategoryList.add(categoryList.getFromValue("People")); validCategoryList.add(categoryList.getFromValue("Projects")); } else if ("web".equals(purpose)) { validCategoryList.add(categoryList.getFromValue("Products")); validCategoryList.add(categoryList.getFromValue("Services")); validCategoryList.add(categoryList.getFromValue("Partners")); validCategoryList.add(categoryList.getFromValue("Groups")); validCategoryList.add(categoryList.getFromValue("People")); validCategoryList.add(categoryList.getFromValue("Events")); validCategoryList.add(categoryList.getFromValue("Ideas")); validCategoryList.add(categoryList.getFromValue("Projects")); } // Update the related tabs, or leave all enabled if (validCategoryList.size() > 0) { for (ProjectCategory category : categoryList) { category.setEnabled(validCategoryList.get(category) != null); category.setSensitive(isPrivate); category.update(db); } } // Determine the profile visibility project.setUpdateAllowGuests(true); project.setAllowGuests(isPrivate ? false : true); project.setUpdateAllowParticipants(true); project.setAllowParticipants(true); project.setUpdateMembershipRequired(true); project.setMembershipRequired(false); project.setApproved(true); // Determine the tabs project.setShowProfile(true); project.getFeatures().setLabelProfile("Overview"); project.setShowNews(true); project.getFeatures().setLabelNews("Blog"); project.setShowReviews(true); project.setShowWiki(true); project.setShowCalendar(true); project.setShowDiscussion(true); project.setShowDocuments(true); project.setShowClassifieds(true); project.setShowBadges(true); project.setShowLists(true); project.setShowIssues(true); project.setShowTeam(true); project.getFeatures().setLabelTickets("Issues"); project.getFeatures().setLabelTeam("Participants"); project.setShowMessages(true); // Determine the record details project.setUniqueId("main-profile"); project.setGroupId(1); project.setCategoryId(categoryId); project.setOwner(1); project.setEnteredBy(1); project.setModifiedBy(1); project.insert(db); project.updateFeatures(db); project.setSystemDefault(true); project.updateSystemDefault(db); // Build a list of roles LookupList roleList = CacheUtils.getLookupList("lookup_project_role"); // Build a list of the default permissions PermissionList permissionList = new PermissionList(); permissionList.setProjectId(project.getId()); permissionList.buildList(db); // Modify the permissions for the default profile LinkedHashMap<String, Integer> permissionMap = new LinkedHashMap<String, Integer>(); permissionMap.put("project-tickets-view", TeamMember.MEMBER); permissionMap.put("project-tickets-other", TeamMember.CHAMPION); permissionMap.put("project-tickets-add", TeamMember.MEMBER); permissionMap.put("project-tickets-edit", TeamMember.CHAMPION); permissionMap.put("project-tickets-assign", TeamMember.CHAMPION); permissionMap.put("project-tickets-close", TeamMember.CHAMPION); permissionMap.put("project-tickets-delete", TeamMember.MANAGER); for (String name : permissionMap.keySet()) { Permission permission = permissionList.get(name); permission.setUserLevel(roleList.getIdFromLevel(permissionMap.get(name))); LOG.debug("Updating a permission: " + name); permission.update(db); } // Get the admin role int adminRowLevel = roleList.getIdFromValue("Manager"); // Add the admins as a member UserList userList = new UserList(); userList.setAdmin(Constants.TRUE); userList.buildList(db); for (User thisUser : userList) { TeamMember thisMember = new TeamMember(); thisMember.setProjectId(project.getId()); thisMember.setUserId(thisUser.getId()); thisMember.setUserLevel(adminRowLevel); thisMember.setEnteredBy(1); thisMember.setModifiedBy(1); thisMember.insert(db); } } public static void insertDefaultContent(Connection db, SyncTableList syncTableList, String fileLibraryPath, Project project) throws Exception { LOG.debug("insertDefaultContent"); int SYSTEM_ID = 1; // From the Service action method PacketContext packetContext = new PacketContext(); packetContext.setObjectMap(syncTableList.getObjectMapping(SYSTEM_ID)); packetContext.setBaseFilePath(fileLibraryPath); // Retrieve and stream the records to restore LOG.debug("Loading the configuration xml..."); InputStream inputStream = SetupUtils.class.getResourceAsStream("/content_en_US.xml"); // Restore the state of the objects as-supplied, start by deleting the record and dependents ArrayList<String> meta = new ArrayList<String>(); meta.add("mode=copy"); ArrayList exclude = new ArrayList(); HashMap<String, String> replace = new HashMap<String, String>(); replace.put("enteredBy", String.valueOf(project.getEnteredBy())); replace.put("modifiedBy", String.valueOf(project.getEnteredBy())); replace.put("projectId", String.valueOf(project.getId())); replace.put("linkItemId", String.valueOf(project.getId())); replace.put("thumbnailFilename", "null"); replace.put("logoId", "-1"); HashMap options = new HashMap(); options.put("exclude", exclude); options.put("replace", replace); // Use the APIConnection to do the shared work LOG.debug("Parsing the records..."); APIConnection api = new APIConnection(); api.setAutoCommit(false); api.setTransactionMeta(meta); APIRestore.restore(api, inputStream, null, -1, options); // Construct the xml LOG.debug("Generating XML..."); XMLUtils xml = new XMLUtils(api.generateXMLPacket()); // Restore this item TransactionUtils.processTransactions(db, xml, packetContext); LOG.debug("Finished."); } }