001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2007-2010 ADEQUATE SYSTEMS SARL
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.builder.util;
022    
023    import java.io.File;
024    import java.io.FileFilter;
025    import java.io.FileInputStream;
026    import java.io.FileOutputStream;
027    import java.io.IOException;
028    import java.io.InputStream;
029    import java.io.OutputStream;
030    import java.util.ArrayList;
031    import java.util.Arrays;
032    import java.util.Collections;
033    import java.util.List;
034    import java.util.Properties;
035    
036    import org.eclipse.core.resources.IProject;
037    import org.granite.builder.BuilderConfiguration;
038    import org.granite.builder.BuilderListener;
039    import org.granite.builder.properties.Gas3Source;
040    import org.granite.builder.properties.GraniteProperties;
041    import org.granite.generator.Listener;
042    
043    /**
044     * @author Franck WOLFF
045     */
046    public class FlexConfigGenerator {
047    
048            private static final String AS3_METADATA_RES = "org/granite/tide/as3-metadata.properties";
049            
050            public static final String FILE_NAME="granite-flex-config.xml";
051            
052            private static final String PREFIX =
053                    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
054                    "<flex-config>\n" +
055                    "   <compiler>\n" +
056                    "      <keep-as3-metadata>\n";
057            
058            private static final String INFIX =
059                    "      </keep-as3-metadata>\n" +
060                    "   </compiler>\n" +
061                    "   <includes>\n";
062    
063            private static final String SUFFIX =
064                    "   </includes>\n" +
065                    "</flex-config>";
066            
067            private static final FileFilter AS_FILE_FILTER = new FileFilter() {
068                    public boolean accept(File file) {
069                            return file.isDirectory() || file.getName().endsWith(".as");
070                    }
071            };
072            
073            public static boolean generateFlexConfig(BuilderConfiguration config, BuilderListener listener, IProject project) throws Exception {
074                    GraniteProperties properties = config.getProperties();
075                    
076                    if (properties.getGas3().getSources() == null || properties.getGas3().getSources().isEmpty())
077                            return false;
078                    if (!ProjectUtil.isFlexBuilderProject(project))
079                            return false;
080                    
081                    List<String> asClasses = new ArrayList<String>();
082                    for (Gas3Source source : properties.getGas3().getSources()) {
083                            File output = new File(ProjectUtil.getProjectFile(project), source.getOutputDir());
084                            asClasses.addAll(listAsFiles(output));
085                    }
086                    Collections.sort(asClasses);
087                    
088                    File flexConfigFile = new File(project.getFile(FILE_NAME).getLocationURI());
089                    
090                    StringBuilder sb = new StringBuilder(1024);
091                    sb.append(PREFIX);
092                    try {
093                            Properties as3Metadata = new Properties();
094                            InputStream is = config.getClassLoader().getResourceAsStream(AS3_METADATA_RES);
095                            //  If null -> granite.jar isn't in the classpath or is outdated...
096                            if (is != null) {
097                                    try {
098                                            as3Metadata.load(is);
099                                    }
100                                    finally {
101                                            is.close();
102                                    }
103                                    String[] names = as3Metadata.keySet().toArray(new String[as3Metadata.size()]);
104                                    Arrays.sort(names);
105                                    for (Object name : names)
106                                            sb.append("        <name>").append(name).append("</name>\n");
107                            }
108                    }
109                    catch (IOException e) {
110                            // ignore...
111                    }
112                    sb.append(INFIX);
113                    for (String asClass : asClasses)
114                            sb.append("      <symbol>").append(asClass).append("</symbol>\n");
115                    sb.append(SUFFIX);
116                    
117                    byte[] bs = sb.toString().getBytes("UTF-8");
118                    
119                    boolean writeFile = true;
120                    
121                    String message = Listener.MSG_FILE_UPTODATE;
122                    if (flexConfigFile.exists()) {
123                            if (flexConfigFile.length() == bs.length) {
124                                    InputStream is = new FileInputStream(flexConfigFile);
125                                    try {
126                                            byte[] fc = new byte[bs.length];
127                                            is.read(fc);
128                                            writeFile = !Arrays.equals(bs, fc);
129                                    }
130                                    finally {
131                                            is.close();
132                                    }
133                            }
134                            if (writeFile)
135                                    message = Listener.MSG_FILE_OUTDATED;
136                    }
137                    else
138                            message = Listener.MSG_FILE_NOT_EXISTS;
139                    
140                    if (writeFile) {
141                            listener.generating(flexConfigFile.toString(), message);
142                            OutputStream os = new FileOutputStream(flexConfigFile);
143                            try {
144                                    os.write(bs);
145                            }
146                            finally {
147                                    os.close();
148                            }
149                    }
150                    else
151                            listener.skipping(flexConfigFile.toString(), message);
152    
153                    return writeFile;
154            }
155            
156            private static List<String> listAsFiles(File root) throws Exception {
157                    List<String> files = new ArrayList<String>();
158                    listAsFiles(root, root, files);
159                    return files;
160            }
161            
162            private static void listAsFiles(File root, File dir, List<String> files) throws Exception {
163                    if (dir.exists() && dir.isDirectory()) {
164                            for (File file : dir.listFiles(AS_FILE_FILTER)) {
165                                    if (file.isDirectory())
166                                            listAsFiles(root, file, files);
167                                    else {
168                                            StringBuilder sb = new StringBuilder();
169                                            sb.append(file.getName().substring(0, file.getName().length() - 3));
170                                            for (File parent = file.getParentFile(); parent != null && !root.equals(parent); parent = parent.getParentFile())
171                                                    sb.insert(0, '.').insert(0, parent.getName());
172                                            files.add(sb.toString());
173                                    }
174                            }
175                    }
176            }
177    }