/* ==================================================================== * * The ObjectStyle Group Software License, Version 1.0 * * Copyright (c) 2002 - 2004 The ObjectStyle Group * and individual authors of the software. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * ObjectStyle Group (http://objectstyle.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "ObjectStyle Group" and "Cayenne" * must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact andrus@objectstyle.org. * * 5. Products derived from this software may not be called "ObjectStyle" * nor may "ObjectStyle" appear in their names without prior written * permission of the ObjectStyle Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the ObjectStyle Group. For more * information on the ObjectStyle Group, please see * <http://objectstyle.org/>. * */ package org.objectstyle.woproject.ant; import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Copy; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.FilterSet; import org.apache.tools.ant.types.FilterSetCollection; import org.apache.tools.ant.types.PatternSet; import org.objectstyle.woenvironment.env.WOVariables; /** * Subclass of ProjectFormat that defines file copying strategy for * WOApplications. * * @author Andrei Adamchik */ public class AppFormat extends ProjectFormat { protected HashMap<String, String> templateMap = new HashMap<String, String>(); protected HashMap<String, FilterSetCollection> filterMap = new HashMap<String, FilterSetCollection>(); protected String appPaths; protected String frameworkPaths; protected String otherClasspaths; /** * Creates new AppFormat and initializes it with the name of the project * being built. */ public AppFormat(WOTask task) { super(task); prepare(); } /** * Builds a list of files for the application, maps them to templates and * filters. */ private void prepare() { log("AppFormat prepare", Project.MSG_VERBOSE); preparePaths(); prepare52(); prepareWindows(); prepareUnix(); prepareMac(); // add Info.plist String infoFile = new File(getApplicatonTask().contentsDir(), "Info.plist").getPath(); createMappings(infoFile, woappPlusVersion() + "/Info.plist", infoFilter(null)); // add web.xml if (((WOApplication) this.task).webXML) { String webXMLFile = new File(getApplicatonTask().contentsDir(), "web.xml").getPath(); createMappings(webXMLFile, woappPlusVersion() + "/web.xml", webXMLFilter()); } } /** * Prepares all path values needed for substitutions. */ private void preparePaths() { appPaths = buildAppPaths(); frameworkPaths = buildFrameworkPaths(); otherClasspaths = buildOtherClassPaths(); } /** * Prepares all path values needed for substitutions. */ private void prepare52() { if (this.getApplicatonTask().getWOEnvironment().wo52()) { Copy cp = new Copy(); // cp.setOwningTarget(getApplicatonTask().getProject().getDefaultTarget()); cp.setProject(getApplicatonTask().getProject()); cp.setTaskName("copy bootstrap"); cp.setFile(this.getApplicatonTask().getWOEnvironment().bootstrap()); cp.setTodir(getApplicatonTask().taskDir()); cp.execute(); } } /** * Returns a String that consists of paths to the application jar. File * separator used is platform dependent and may need to be changed when * creating files for multiple platforms. */ protected String buildAppPaths() { FileSet fs = null; // include zips and jars // http://objectstyle.org/jira/secure/ViewIssue.jspa?key=WOL-47 PatternSet.NameEntry includeJar = null, includeZip = null; DirectoryScanner ds = null; String[] files = null; StringBuffer buf = null; try { fs = new FileSet(); fs.setDir(getApplicatonTask().contentsDir()); includeJar = fs.createInclude(); includeJar.setName("Resources/Java/**/*.jar"); includeZip = fs.createInclude(); includeZip.setName("Resources/Java/**/*.zip"); ds = fs.getDirectoryScanner(task.getProject()); files = ds.getIncludedFiles(); buf = new StringBuffer(); // prepend the path with Resources/Java (for CompilerProxy support) buf.append("APPROOT").append(File.separatorChar).append("Resources").append(File.separatorChar).append("Java").append(File.separatorChar).append(System.getProperty("line.separator")); for (int k = 0; k < 2; k++) { for (int i = 0; i < files.length; i++) { if (k == 0 && files[i].toString().indexOf("webobjects") >= 0) { continue; } if (k == 1 && files[i].toString().indexOf("webobjects") < 0) { continue; } buf.append("APPROOT").append(File.separatorChar).append(files[i]).append(System.getProperty("line.separator")); } } return buf.toString(); } catch (Exception anException) { log(anException.getMessage(), Project.MSG_WARN); } finally { fs = null; includeJar = null; includeZip = null; ds = null; files = null; buf = null; } return ""; } /** * Returns a String that consists of paths of all framework's jar's needed * by the application. File separator used is platform dependent and may * need to be changed when creating files for multiple platforms. */ protected String buildFrameworkPaths() { WOVariables variables = getApplicatonTask().getWOEnvironment().getWOVariables(); String relativeEmbeddedFrameworksDir = getApplicatonTask().relativeEmbeddedFrameworksDir(); String result = FrameworkSet.jarsPathForFrameworkSets(task.getProject(), relativeEmbeddedFrameworksDir, getApplicatonTask().getFrameworkSets(), variables); return result; } /** * Method buildOtherClassPaths. * * @return String */ protected String buildOtherClassPaths() { StringBuffer buf = new StringBuffer(); List<?> classpathSets = getApplicatonTask().getOtherClasspath(); Project project = task.getProject(); // track included paths to avoid double entries HashSet<File> pathSet = new HashSet<File>(); int size = classpathSets.size(); try { for (int i = 0; i < size; i++) { OtherClasspathSet cs = (OtherClasspathSet) classpathSets.get(i); cs.collectClassPaths(project, pathSet); } } catch (BuildException be) { // paths doesn't exist or are not readable log(be.getMessage(), Project.MSG_WARN); } if (pathSet.size() > 0) { File someFiles[] = pathSet.toArray(new File[] {}); size = someFiles.length; for (int i = 0; i < size; i++) { // log(": Framework JAR " + (File) someFiles[i], // Project.MSG_VERBOSE); String fileName = this.getApplicatonTask().getWOEnvironment().getWOVariables().encodePathForFile(someFiles[i]); // If it's not a jar file and it doesn't have a trailing '/'. // add one in. boolean isJar = fileName.endsWith(".jar") || fileName.endsWith(".zip"); if (isJar == false && fileName.endsWith("/") == false) { fileName = fileName + "/"; } buf.append(fileName).append("\r\n"); } } return buf.toString(); } /** * Prepare mappings for Windows subdirectory. */ private void prepareWindows() { File winDir = new File(getApplicatonTask().contentsDir(), "Windows"); String cp = new File(winDir, "CLSSPATH.TXT").getPath(); createMappings(cp, woappPlusVersion() + "/Contents/Windows/CLSSPATH.TXT", classpathFilter('\\')); String subp = new File(winDir, "SUBPATHS.TXT").getPath(); createMappings(subp, woappPlusVersion() + "/Contents/Windows/SUBPATHS.TXT"); // add run script to Win. directory String runScript = new File(winDir, getName() + ".cmd").getPath(); createMappings(runScript, woappPlusVersion() + "/Contents/Windows/appstart.cmd", startupScriptFilter()); // add run script to top-level directory File taskDir = getApplicatonTask().taskDir(); String startupScriptName = this.getApplicatonTask().startupScriptName; if (startupScriptName == null || startupScriptName.length() == 0) { startupScriptName = getName(); } String topRunScript = new File(taskDir, startupScriptName + ".cmd").getPath(); createMappings(topRunScript, woappPlusVersion() + "/Contents/Windows/appstart.cmd", startupScriptFilter()); } /** * Prepare mappings for UNIX subdirectory. */ private void prepareUnix() { File dir = new File(getApplicatonTask().contentsDir(), "UNIX"); String cp = new File(dir, "UNIXClassPath.txt").getPath(); createMappings(cp, woappPlusVersion() + "/Contents/UNIX/UNIXClassPath.txt", classpathFilter('/')); } /** * Prepare mappings for MacOS subdirectory. */ private void prepareMac() { File macDir = new File(getApplicatonTask().contentsDir(), "MacOS"); String cp = new File(macDir, "MacOSClassPath.txt").getPath(); createMappings(cp, woappPlusVersion() + "/Contents/MacOS/MacOSClassPath.txt", classpathFilter('/')); String servercp = new File(macDir, "MacOSXServerClassPath.txt").getPath(); createMappings(servercp, woappPlusVersion() + "/Contents/MacOS/MacOSXServerClassPath.txt", classpathFilter('/')); // add run script to Mac directory String runScript = new File(macDir, getName()).getPath(); createMappings(runScript, woappPlusVersion() + "/Contents/MacOS/appstart", startupScriptFilter()); // add run script to top-level directory File taskDir = getApplicatonTask().taskDir(); String startupScriptName = this.getApplicatonTask().startupScriptName; if (startupScriptName == null || startupScriptName.length() == 0) { startupScriptName = getName(); } String topRunScript = new File(taskDir, startupScriptName).getPath(); createMappings(topRunScript, woappPlusVersion() + "/Contents/MacOS/appstart", startupScriptFilter()); } /** * Creates a filter for Classpath helper files. */ private FilterSet classpathFilter(char pathSeparator) { FilterSet filter = new FilterSet(); if (pathSeparator == File.separatorChar) { filter.addFilter("APP_JAR", appPaths); filter.addFilter("FRAMEWORK_JAR", frameworkPaths); filter.addFilter("OTHER_PATHS", otherClasspaths); } else { filter.addFilter("APP_JAR", appPaths.replace(File.separatorChar, pathSeparator)); filter.addFilter("FRAMEWORK_JAR", frameworkPaths.replace(File.separatorChar, pathSeparator)); filter.addFilter("OTHER_PATHS", otherClasspaths.replace(File.separatorChar, pathSeparator)); } return filter; } /** * Method getAppClass. * * @return String */ private String getAppClass() { return task.getPrincipalClass(); } /** * Returns the WO servlet adaptor for this application. * * @return the WO servlet adaptor for this application */ private String getServletAdaptor() { return task.getServletAdaptor(); } /** * Method createMappings. * * @param fileName * @param template * @param filter */ private void createMappings(String fileName, String template, FilterSet filter) { FilterSetCollection fsCollection = new FilterSetCollection(filter); FilterSet additionalBuildSettingsFilter = additionalBuildSettingsFilter(); filter.addFilter("APP_CLASS", getAppClass()); filter.addFilter("JAR_NAME", getJarName()); if (additionalBuildSettingsFilter != null) { fsCollection.addFilterSet(additionalBuildSettingsFilter); } createMappings(fileName, template, fsCollection); } /** * Method createMappings. * * @param fileName * @param template */ private void createMappings(String fileName, String template) { createMappings(fileName, template, (FilterSetCollection) null); } /** * Method createMappings. * * @param fileName * @param template * @param filter */ private void createMappings(String fileName, String template, FilterSetCollection filter) { templateMap.put(fileName, template); filterMap.put(fileName, filter); } /** * Method getApplicatonTask. * * @return WOApplication */ private WOApplication getApplicatonTask() { return (WOApplication) task; } /** * @see org.objectstyle.woproject.ant.ProjectFormat#fileIterator() */ @Override public Iterator<String> fileIterator() { return templateMap.keySet().iterator(); } /** * @see org.objectstyle.woproject.ant.ProjectFormat#templateForTarget(java.lang.String) */ @Override public String templateForTarget(String targetName) throws BuildException { String template = templateMap.get(targetName); if (template == null) { throw new BuildException("Invalid target, no template found: " + targetName); } return template; } /** * @see org.objectstyle.woproject.ant.ProjectFormat#filtersForTarget(java.lang.String) */ @Override public FilterSetCollection filtersForTarget(String targetName) throws BuildException { if (!filterMap.containsKey(targetName)) { throw new BuildException("Invalid target: " + targetName); } return filterMap.get(targetName); } /** * Method woappPlusVersion returns the template name. * * @return String */ public String woappPlusVersion() { if (this.getApplicatonTask().getWOEnvironment().wo5or51()) return "woapp"; return "woapp_52"; } /** * Launch scripts configuration * @return FilterSet */ private FilterSet additionalBuildSettingsFilter() { String jvmOptions = getApplicatonTask().getJvmOptions(); String jvm = getApplicatonTask().getJVM(); String jdb = getApplicatonTask().getJDB(); String jdbOptions = getApplicatonTask().getJDBOptions(); String javaVersion = getApplicatonTask().getJavaVersion(); if (jvmOptions != null) { FilterSet filter = new FilterSet(); filter.addFilter("JVM_OPTIONS", jvmOptions); filter.addFilter("JVM", jvm); filter.addFilter("JDB", jdb); filter.addFilter("JDB_OPTIONS", jdbOptions); filter.addFilter("JAVA_VERSION", javaVersion); return filter; } return null; } /** * */ @Override public void release() { super.release(); } /** * Returns a FilterSet that can be used to build the startup script file. */ public FilterSetCollection startupScriptFilter() { FilterSet filter = new FilterSet(); String frameworksBaseURL = this.getApplicatonTask().getFrameworksBaseURL(); if (frameworksBaseURL != null && frameworksBaseURL.length() > 0) { frameworksBaseURL = "-WOFrameworksBaseURL " + frameworksBaseURL; } else { frameworksBaseURL = ""; } filter.addFilter("-WOFrameworksBaseURL", frameworksBaseURL); return new FilterSetCollection(filter); } protected String stripPath(String path) { path = path.replace("WOROOT", ""); path = path.replace("APPROOT", ""); path = path.replace("LOCALROOT", ""); return path; } /** * Returns a FilterSet that can be used to build web.xml file. */ public FilterSetCollection webXMLFilter() { //System.out.println("AppFormat.webXMLFilter: appPaths = " + appPaths); //System.out.println("AppFormat.webXMLFilter: frameworkPaths = " + frameworkPaths); //System.out.println("AppFormat.webXMLFilter: otherClasspaths = " + otherClasspaths); FilterSet filter = new FilterSet(); String WEBINFROOT = "WEBINFROOT"; List<String> paths = new LinkedList<String>(); if (appPaths != null && appPaths.length() > 0) { appPaths = appPaths.trim(); for (String appPath : appPaths.split("\n")) { paths.add(WEBINFROOT + stripPath(appPath)); } } if (frameworkPaths != null && frameworkPaths.length() > 0) { frameworkPaths = frameworkPaths.trim(); for (String frameworkPath : frameworkPaths.split("\n")) { paths.add(WEBINFROOT + "/" + getApplicatonTask().getName() + ".woa/Contents" + stripPath(frameworkPath)); } } if (otherClasspaths != null && otherClasspaths.length() > 0) { otherClasspaths = otherClasspaths.trim(); for (String otherPath : otherClasspaths.split("\n")) { paths.add(WEBINFROOT + stripPath(otherPath)); } } StringBuffer pathsBuffer = new StringBuffer(); for (String path : paths) { pathsBuffer.append(path); pathsBuffer.append("\n"); } WOApplication woappTask = (WOApplication) this.task; log(" AppFormat.webXMLFilter().woappTask: " + woappTask, Project.MSG_VERBOSE); filter.addFilter("WOROOT", woappTask.getWebXML_WOROOT()); filter.addFilter("LOCALROOT", woappTask.getWebXML_LOCALROOT()); filter.addFilter("WOAINSTALLROOT", woappTask.getWebXML_WOAINSTALLROOT()); filter.addFilter("WOAppMode", woappTask.getWebXML_WOAppMode()); filter.addFilter("WOClasspath", pathsBuffer.toString()); filter.addFilter("WOApplicationClass", this.getAppClass()); filter.addFilter("WOServletAdaptor", this.getServletAdaptor()); filter.addFilter("WOTagLib", woappTask.getWebXML_WOtaglib()); String customContent = woappTask.getWebXML_CustomContent(); if (customContent == null) { customContent = ""; } filter.addFilter("CustomContent", customContent); return new FilterSetCollection(filter); } }