001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
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                    @Override
069                    public boolean accept(File file) {
070                            return file.isDirectory() || file.getName().endsWith(".as");
071                    }
072            };
073            
074            public static boolean generateFlexConfig(BuilderConfiguration config, BuilderListener listener, IProject project) throws Exception {
075                    GraniteProperties properties = config.getProperties();
076                    
077                    if (properties.getGas3().getSources() == null || properties.getGas3().getSources().isEmpty())
078                            return false;
079                    if (!ProjectUtil.isFlexBuilderProject(project))
080                            return false;
081                    
082                    List<String> asClasses = new ArrayList<String>();
083                    for (Gas3Source source : properties.getGas3().getSources()) {
084                            File output = new File(ProjectUtil.getProjectFile(project), source.getOutputDir());
085                            asClasses.addAll(listAsFiles(output));
086                    }
087                    Collections.sort(asClasses);
088                    
089                    File flexConfigFile = FileUtil.getLocationFile(project.getFile(FILE_NAME));
090                    
091                    StringBuilder sb = new StringBuilder(1024);
092                    sb.append(PREFIX);
093                    try {
094                            Properties as3Metadata = new Properties();
095                            InputStream is = config.getClassLoader().getResourceAsStream(AS3_METADATA_RES);
096                            //  If null -> granite.jar isn't in the classpath or is outdated...
097                            if (is != null) {
098                                    try {
099                                            as3Metadata.load(is);
100                                    }
101                                    finally {
102                                            is.close();
103                                    }
104                                    String[] names = as3Metadata.keySet().toArray(new String[as3Metadata.size()]);
105                                    Arrays.sort(names);
106                                    for (Object name : names)
107                                            sb.append("        <name>").append(name).append("</name>\n");
108                            }
109                    }
110                    catch (IOException e) {
111                            // ignore...
112                    }
113                    sb.append(INFIX);
114                    for (String asClass : asClasses)
115                            sb.append("      <symbol>").append(asClass).append("</symbol>\n");
116                    sb.append(SUFFIX);
117                    
118                    byte[] bs = sb.toString().getBytes("UTF-8");
119                    
120                    boolean writeFile = true;
121                    
122                    String message = Listener.MSG_FILE_UPTODATE;
123                    if (flexConfigFile.exists()) {
124                            if (flexConfigFile.length() == bs.length) {
125                                    InputStream is = new FileInputStream(flexConfigFile);
126                                    try {
127                                            byte[] fc = new byte[bs.length];
128                                            is.read(fc);
129                                            writeFile = !Arrays.equals(bs, fc);
130                                    }
131                                    finally {
132                                            is.close();
133                                    }
134                            }
135                            if (writeFile)
136                                    message = Listener.MSG_FILE_OUTDATED;
137                    }
138                    else
139                            message = Listener.MSG_FILE_NOT_EXISTS;
140                    
141                    if (writeFile) {
142                            listener.generating(flexConfigFile.toString(), message);
143                            OutputStream os = new FileOutputStream(flexConfigFile);
144                            try {
145                                    os.write(bs);
146                            }
147                            finally {
148                                    os.close();
149                            }
150                    }
151                    else
152                            listener.skipping(flexConfigFile.toString(), message);
153    
154                    return writeFile;
155            }
156            
157            private static List<String> listAsFiles(File root) throws Exception {
158                    List<String> files = new ArrayList<String>();
159                    listAsFiles(root, root, files);
160                    return files;
161            }
162            
163            private static void listAsFiles(File root, File dir, List<String> files) throws Exception {
164                    if (dir.exists() && dir.isDirectory()) {
165                            for (File file : dir.listFiles(AS_FILE_FILTER)) {
166                                    if (file.isDirectory())
167                                            listAsFiles(root, file, files);
168                                    else {
169                                            StringBuilder sb = new StringBuilder();
170                                            sb.append(file.getName().substring(0, file.getName().length() - 3));
171                                            for (File parent = file.getParentFile(); parent != null && !root.equals(parent); parent = parent.getParentFile())
172                                                    sb.insert(0, '.').insert(0, parent.getName());
173                                            files.add(sb.toString());
174                                    }
175                            }
176                    }
177            }
178    }