public boolean publish()

in compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyalePublisher.java [209:637]


    public boolean publish(ProblemQuery problems) throws IOException
    {
        // The "intermediate" is the "js-debug" output.
        final File intermediateDir = outputFolder;

        // The source directory is the source path entry containing the Main class.
        List<File> sourcePaths = project.getSourcePath();
        String targetFile = configuration.getTargetFile().toLowerCase();
    	if (googConfiguration.isVerbose())
        {
            System.out.println("find project folder for " + targetFile);
        }
        File imageSrcDir = null;
        for (File sp : sourcePaths)
        {
        	if (googConfiguration.isVerbose())
            {
                System.out.println("checking source path " + sp.getAbsolutePath());
            }
        	String lowercasePath = sp.getAbsolutePath().toLowerCase();
        	if (targetFile.startsWith(lowercasePath))
        		imageSrcDir = sp;
        }
        if (imageSrcDir == null)
        {
        	imageSrcDir = new File(configuration.getTargetFile()).getAbsoluteFile().getParentFile();
        	if (googConfiguration.isVerbose())
            {
                System.out.println("not found on source path, using parent file " + imageSrcDir.getAbsolutePath());
            }
        }
        final String projectName = FilenameUtils.getBaseName(configuration.getTargetFile());
        String qName = null;
        try {
			qName = project.mainCU.getQualifiedNames().get(0);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String mainClassQName = qName;
        DefinitionPromise cpromise = (DefinitionPromise)project.mainCU.getDefinitionPromises().get(0);
        IDefinition actualDef = cpromise.getActualDefinition();
        IClassDefinition baseDef = null;
        if(actualDef instanceof IClassDefinition)
        {
		    IClassDefinition cdef = (IClassDefinition) cpromise.getActualDefinition();
            baseDef = (IClassDefinition) project.resolveQNameToDefinition(cdef.getBaseClassAsDisplayString());
        }
		if (baseDef != null)
		{
			String factoryClassName = null;
            IClassDefinition.IClassIterator classIterator = baseDef.classIterator(project, true);
            while (classIterator.hasNext())
            {
                baseDef = classIterator.next();
                if (baseDef.hasMetaTagByName("Frame")) {
                    factoryClassName = getFactoryClass(baseDef.getMetaTagByName("Frame"));
                    break;
                }
            }
			if (factoryClassName != null)
			{
				mainClassQName = generateFactoryClass(factoryClassName, projectName, mainClassQName, intermediateDir);
			}
		}
        final String outputFileName = projectName + "." + project.getBackend().getOutputExtension();

        // The "release" is the "js-release" directory.
        File releaseDir = new File(outputParentFolder, ROYALE_RELEASE_DIR_NAME);
        if (moduleOutput != null)
        	releaseDir = new File(releaseDir, File.separator + moduleOutput);

        /////////////////////////////////////////////////////////////////////////////////
        // Copy static resources to the intermediate (and release) directory.
        /////////////////////////////////////////////////////////////////////////////////

        IOFileFilter pngSuffixFilter = FileFilterUtils.and(FileFileFilter.INSTANCE,
                FileFilterUtils.suffixFileFilter(".png"));
        IOFileFilter gifSuffixFilter = FileFilterUtils.and(FileFileFilter.INSTANCE,
                FileFilterUtils.suffixFileFilter(".gif"));
        IOFileFilter jpgSuffixFilter = FileFilterUtils.and(FileFileFilter.INSTANCE,
                FileFilterUtils.suffixFileFilter(".jpg"));
        IOFileFilter jpegSuffixFilter = FileFilterUtils.and(FileFileFilter.INSTANCE,
                FileFilterUtils.suffixFileFilter(".jpeg"));
        IOFileFilter svgSuffixFilter = FileFilterUtils.and(FileFileFilter.INSTANCE,
                FileFilterUtils.suffixFileFilter(".svg"));
        IOFileFilter jsonSuffixFilter = FileFilterUtils.and(FileFileFilter.INSTANCE,
                FileFilterUtils.suffixFileFilter(".json"));
        IOFileFilter assetFiles = FileFilterUtils.or(pngSuffixFilter, jpgSuffixFilter, jpegSuffixFilter, svgSuffixFilter, gifSuffixFilter,
                jsonSuffixFilter);
        IOFileFilter resourceFilter = FileFilterUtils.or(DirectoryFileFilter.DIRECTORY, assetFiles);
        // FIXME: All images need to be located relative to the Main class ... for Maven this is a problem.
        FileUtils.copyDirectory(imageSrcDir, intermediateDir, resourceFilter);
        // Iterate over all themes SWCs and add the contents of any included files in
        // an assets folder to an assets folder in the destination folder.
        final ISWCManager swcManager = project.getWorkspace().getSWCManager();
        List<ISWC> themeSWCs = new ArrayList<ISWC>();
        List<IFileSpecification> themes = project.getThemeFiles();
        for (final IFileSpecification themeFile : themes)
        {
            final String extension = FilenameUtils.getExtension(themeFile.getPath());
            if ("swc".equalsIgnoreCase(extension))
            {
                final ISWC swc = swcManager.get(new File(themeFile.getPath()));
                themeSWCs.add(swc);
	            Map<String, ISWCFileEntry> files = swc.getFiles();
	            for (String key : files.keySet())
	            {
	                if (key.startsWith(ROYALE_THEME_ASSETS))
	                {
	                    ISWCFileEntry fileEntry = swc.getFile(key);
	                    if (fileEntry != null)
	                    {
	                        InputStream is = fileEntry.createInputStream();
	                        int n = is.available();
	                        int total = 0;
                        	byte[] data = new byte[n];
	                        while (total < n)
	                        {
	                        	total += is.read(data, total, n - total);
	                        }
	                        FileUtils.writeByteArrayToFile(new File(intermediateDir, key), data);
                            if (configuration.release())
                            {
	                            FileUtils.writeByteArrayToFile(new File(releaseDir, key), data);
                            }
	                    }
	                }
	            }
	        }
        }
        
        // If we are doing a release build, we need to copy them to the release dir too.
        if (configuration.release()) {
            FileUtils.copyDirectory(imageSrcDir, releaseDir, resourceFilter);
            // The copy-directory contains a lot of empty directories ... clean them up.
            clearEmptyDirectoryTrees(releaseDir);
        }

        /////////////////////////////////////////////////////////////////////////////////
        // Copy / Dump the closure files into the intermediate directory.
        /////////////////////////////////////////////////////////////////////////////////

        // List of source files we need to pass into the closure compiler. As we have to
        // read the content in order to dump it to the intermediate, we can just keep it
        // and eventually use it in case of a release build.
        List<SourceFile> closureSourceFiles = null;

        // If the closure lib dir is explicitly set, use that directory. If it
        // is not set, check if its content is available in the classpath. If
        // it is found in the classpath, use that as closure lib dir.
        if (!googConfiguration.isClosureLibSet())
        {
            // Check if the "goog/deps.js" is available in the classpath.
            File closureLibraryJar = getJarThatContainsClasspathResources("goog/deps.js");
            if (closureLibraryJar != null)
            {
                // We don't want to add all files to the classpath, so we only output the
                // resources contained in 'closure-whitelist.properties' to the output.
                Properties whiteList = new Properties();
                whiteList.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(
                        "royale/closure-whitelist.properties"));

                // Add the closure files from classpath.
                closureSourceFiles = getClasspathResources(closureLibraryJar, whiteList);
            }
        }
        if (closureSourceFiles == null)
        {
            File closureLibDir = new File(googConfiguration.getClosureLib());
            if (!closureLibDir.exists() || !closureLibDir.isDirectory())
            {
                //only throw this error if closure-lib is set because it
                //wouldn't make sense with the default fallback path
                if (googConfiguration.isClosureLibSet())
                {
                    throw new RuntimeException("Parameter 'closure-lib' doesn't point to a valid directory.");
                }
            }
            else
            {
                closureSourceFiles = getDirectoryResources(new File(closureLibDir, "closure"));
            }
        }
        if (closureSourceFiles == null || closureSourceFiles.size() == 0)
        {
            throw new RuntimeException(
                    "Parameter 'closure-lib' not specified and closure resources not available in classpath.");
        }
        // Dump a copy of the closure lib files to the intermediate directory. Without this
        // the application will not be able to run.
        for(SourceFile closureSourceFile : closureSourceFiles) {
            FileUtils.write(new File(new File(intermediateDir, "library/closure"),
                    closureSourceFile.getName()), closureSourceFile.getCode(), Charset.forName("utf8"));
        }
        List<String> closureEntryPoints = new ArrayList<String>();
        closureEntryPoints.add("goog.events.EventTarget");
        closureEntryPoints.add("goog.html.sanitizer.HtmlSanitizer");
        closureSourceFiles = closureFilesInOrder(intermediateDir + "/library/closure/", closureSourceFiles, closureEntryPoints);


        /////////////////////////////////////////////////////////////////////////////////
        // Prepare the closure compilation.
        /////////////////////////////////////////////////////////////////////////////////

        JSClosureCompilerWrapper compilerWrapper = null;
        if (configuration.release())
        {
            compilerWrapper = new JSClosureCompilerWrapper(googConfiguration.getJSCompilerOptions());
            compilerWrapper.setPropertyNamesToKeep(closurePropertyNamesToKeep);
            if (closureSymbolNamesToExport == null) {
                closureSymbolNamesToExport = new HashSet<String>();
            }
            //the HTML template always needs this name to be exported, even if
            //other class names are not exported
            closureSymbolNamesToExport.add(mainClassQName);
            compilerWrapper.setExtraSymbolNamesToExport(closureSymbolNamesToExport);
        }

        if (compilerWrapper != null)
        {
            /////////////////////////////////////////////////////////////////////////////////
            // Add all the closure lib files to the compilation unit.
            /////////////////////////////////////////////////////////////////////////////////

            for (SourceFile closureSourceFile : closureSourceFiles) {
                compilerWrapper.addJSSourceFile(closureSourceFile);
            }
        }

        /////////////////////////////////////////////////////////////////////////////////
        // Add all the externs to the compilation
        /////////////////////////////////////////////////////////////////////////////////

        // Iterate over all swc dependencies and add all the externs they contain.
        // (Externs are located in a "externs" directory in the root of the SWC)
        Set<ISWC> swcExterns = project.swcExterns;
        List<ISWC> swcs = project.getLibraries();
        List<ISWC> allswcs = new ArrayList<ISWC>();
        allswcs.addAll(swcs);
        allswcs.addAll(themeSWCs);
        for (ISWC swc : allswcs)
        {
            Map<String, ISWCFileEntry> files = swc.getFiles();
            for (String key : files.keySet())
            {
                if (key.startsWith(ROYALE_EXTERNS))
                {
                    ISWCFileEntry fileEntry = swc.getFile(key);
                    if (fileEntry != null)
                    {
                        InputStream is = fileEntry.createInputStream();
                        String code = IOUtils.toString(is, "UTF-8");
                        is.close();
                        
                        if (compilerWrapper != null)
                        {
                            JarSourceFile externFile = new JarSourceFile(key, code,true);
                            if (googConfiguration.isVerbose())
                            {
                                System.out.println("using extern: " + key);
                            }
                            compilerWrapper.addJSExternsFile(externFile);
                        }

                        if (swcExterns.contains(swc))
                        {
                            List<String> lines = IOUtils.readLines(new StringReader(code));
                            collectAdditionalHTML(lines, swc.getSWCFile().getAbsolutePath() + ":" + key);
                        }
                    }
                }
            }
        }

        /////////////////////////////////////////////////////////////////////////////////
        // Add all files generated by the compiler to the compilation unit.
        /////////////////////////////////////////////////////////////////////////////////

        GoogDepsWriter gdw = getGoogDepsWriter(intermediateDir, mainClassQName, googConfiguration, allswcs);
        // This list contains all files generated by the compiler, this is both the
        // compiled js files created by the sources of the current project plus the
        // js files of used dependencies.
        ArrayList<String> sourceExternFiles = new ArrayList<String>();
        ArrayList<String> fileList = gdw.getListOfFiles(project, sourceExternFiles, problems);
        if (fileList == null)
            return false; // some error occurred
        
        for (String sourceExtern : project.sourceExterns)
        {
            String sourceExternFileName = sourceExtern.replace(".", "/") + ".js";
            File sourceExternFile = new File(intermediateDir, sourceExternFileName);
            if (sourceExternFile.exists())
            {
                String sourceExternPath = sourceExternFile.getAbsolutePath();
                if (!sourceExternFiles.contains(sourceExternPath))
                    sourceExternFiles.add(sourceExternPath);
            }
        }
        if (compilerWrapper != null)
        {
            for (String file : fileList)
            {
                compilerWrapper.addJSSourceFile(file);
                if (googConfiguration.isVerbose())
                {            
                    System.out.println("using source file: " + file);
                }
            }
        }
        for (String file : sourceExternFiles)
        {
            if (compilerWrapper != null)
            {
                compilerWrapper.addJSExternsFile(file);
                if (googConfiguration.isVerbose())
                {
                    System.out.println("using extern file: " + file);
                }
            }
            collectFileAdditionalHTML(file);
        }
        additionalHTML.addAll(gdw.additionalHTML);

        /////////////////////////////////////////////////////////////////////////////////
        // Generate the index.html for loading the application.
        /////////////////////////////////////////////////////////////////////////////////

        // The application needs to import all dependencies the application needs, this
        // is generated here so it can be used for outputting the html templates.
        String depsFileData = gdw.generateDeps(project, problems);

        // FOR MODULES: this generates inject_script lines for js to be added to __deps.js
        String additionalScript = "";

        if (project.isModule(mainClassQName))
        {
            for (String s : additionalHTML)
            {
                additionalScript += s.trim() + System.lineSeparator();
            }
            
        	// need better test someday
        	depsFileData += "\ngoog.require('" + mainClassQName + "');\n";
            writeFile(new File(intermediateDir, projectName + "__deps.js"), depsFileData + additionalScript + "\n", false);
            gdw.needCSS = true;
            if (configuration.release()) {
            	writeFile(new File(releaseDir, projectName + ".js"), additionalScript, false);
            }
        }
        else
        {
            project.needCSS = gdw.needCSS;

	        File template = ((JSGoogConfiguration)configuration).getHtmlTemplate();
			List<String> wrappedScript = new ArrayList<String>();
            if (additionalHTML.size() > 0)
            {
                wrappedScript.add("<script type=\"text/javascript\">");
                wrappedScript.addAll(additionalHTML);
                wrappedScript.add("</script>");
            }
	        // Create the index.html for the debug-js version.
	        if (!((JSGoogConfiguration)configuration).getSkipTranspile()) {
	            if (template != null) {
	                writeTemplate(template, "intermediate", projectName, mainClassQName, intermediateDir, depsFileData, wrappedScript, problems);
	            } else {
	                writeHTML("intermediate", projectName, mainClassQName, intermediateDir, depsFileData, wrappedScript, problems);
	            }
	        }
	        // Create the index.html for the release-js version.
	        if (configuration.release()) {
	            if (template != null) {
	                writeTemplate(template, "release", projectName, mainClassQName, releaseDir, depsFileData, wrappedScript, problems);
	            } else {
	                writeHTML("release", projectName, mainClassQName, releaseDir, null, wrappedScript, problems);
	            }
	        }
        }        

        /////////////////////////////////////////////////////////////////////////////////
        // Generate or copy the main CSS resources.
        /////////////////////////////////////////////////////////////////////////////////

        project.needCSS = gdw.needCSS;
        if (project.needCSS || googConfiguration.getSkipTranspile()) {
            if (!googConfiguration.getSkipTranspile()) {
                writeCSS(projectName, intermediateDir, false);
            }
            if (project.needCSS && configuration.release()) {
                // if release version minify css string
                writeCSS(projectName, releaseDir, true);
            }
        }


        /////////////////////////////////////////////////////////////////////////////////
        // If we are doing a release build, let the closure compiler do it's job.
        /////////////////////////////////////////////////////////////////////////////////

        if (compilerWrapper != null) {
            boolean ok = true;
            final File projectReleaseMainFile = new File(releaseDir, outputFileName);
            compilerWrapper.setOptions(projectReleaseMainFile.getCanonicalPath(), useStrictPublishing, !googConfiguration.getRemoveCirculars(), projectName);
            compilerWrapper.targetFilePath = projectReleaseMainFile.getCanonicalPath();
            compilerWrapper.setSourceMap(googConfiguration.getSourceMap());
            compilerWrapper.setVerbose(googConfiguration.isVerbose());
            compilerWrapper.setPreventRenameMxmlSymbolReferences(googConfiguration.getPreventRenameMxmlSymbolReferences());

            ok = compilerWrapper.compile();

            // FOR MODULES: add additionalScript to main js release file too
            if (project.isModule(mainClassQName))
            {
                StringBuilder appendString = new StringBuilder();
                appendString.append(additionalScript);
                writeFile(projectReleaseMainFile, appendString.toString(), true);
            }

            appendSourceMapLocation(projectReleaseMainFile, projectName);
            
            if (ok)
                System.out.println("The project '" + projectName + "' has been successfully compiled and optimized.");
        }
        else
        	System.out.println("The project '" + projectName + "' has been successfully compiled.");

        return true;
    }