/* * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package flex2.tools.oem; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.lang.annotation.Annotation; import java.net.URI; import org.apache.flex.compiler.clients.COMPC; import org.apache.flex.compiler.clients.problems.ProblemFormatter; import org.apache.flex.compiler.clients.problems.ProblemQuery; import org.apache.flex.compiler.problems.CompilerProblemSeverity; import org.apache.flex.compiler.problems.ICompilerProblem; import org.apache.flex.compiler.problems.annotations.DefaultSeverity; import flex2.compiler.common.CompilerConfiguration; import flex2.compiler.config.ConfigurationException; import flex2.compiler.io.FileUtil; import flex2.compiler.io.LocalFile; import flex2.compiler.io.VirtualFile; import flex2.compiler.util.Benchmark; import flex2.compiler.util.CompilerControl; import flex2.compiler.util.CompilerMessage; import flex2.compiler.util.MimeMappings; import flex2.compiler.util.PerformanceData; import flex2.compiler.util.ThreadLocalToolkit; import flex2.tools.oem.internal.OEMConfiguration; import flex2.tools.oem.internal.OEMReport; import flex2.tools.oem.internal.OEMUtil; /** * The <code>Library</code> class represents a SWC archive or a RSL. It implements the <code>Builder</code> interface * which allows for building the library incrementally. The following example defines a SWC archive or RSL: * * <pre> * Library lib = new Library(); * </pre> * * You can add components to the <code>Library</code> object in the following ways: * * <pre> * 1. String - Specify a fully-qualified name. * 2. File - Specify a source file. * 3. VirtualLocalFile - Specify an in-memory source object. * 4. URI - Specify a namespace URI. * </pre> * * <p> * To add resource bundles to the <code>Library</code>, you can use the <code>addResourceBundle()</code> method, * as the following example shows: * * <pre> * lib.addResourceBundle("mx.controls")); * </pre> * * <p> * To add archive files to the <code>Library</code>, you can use the <code>addArchiveFile()</code> method, as the following * example shows: * * <pre> * lib.addArchiveFile("defaults.css", new File("path1/myStyle.css")); * </pre> * * Before you can compile with a <code>Library</code> object, you must configure it. The following * four methods are the most common methods you use to configure the <code>Library</code> object: * * <pre> * 1. setLogger() - Use this to set a Logger so that the client can be notified of events that occurred during the compilation. * 2. setConfiguration() - Optional. Use this to specify compiler options. * 3. setOutput() - Optional. Use this to specify an output file name. * 4. setDirectory() - Optional. Use this to specify an RSL output directory. * </pre> * * You must implement the <code>flex2.tools.oem.Logger</code> interface and use the implementation as the <code>Logger</code> * for the compilation. The following is an example <code>Logger</code> implementation: * * <pre> * lib.setLogger(new flex2.tools.oem.Logger() * { * public void log(Message message, int errorCode, String source) * { * System.out.println(message); * } * }); * </pre> * * To specify compiler options for the <code>Library</code> object, you * must get a <code>Configuration</code> object that is populated with default values. Then, you set * compiler options programmatically using methods of the <code>Configuration</code> class. * * <p> * The <code>setOutput()</code> method lets you specify where the <code>Library</code> object writes * the output to. If you call the <code>setOutput()</code> method, the <code>build(boolean)</code> method * writes directly to the specified location; for example: * * <pre> * lib.setOutput(new File("MyLib.swc")); * lib.build(true); * </pre> * * If you do not call the <code>setOutput()</code> method, you can use the <code>build(OutputStream, boolean)</code> * method. This requires that you provide a buffered output stream; for example: * * <pre> * lib.build(new BufferedOutputStream(new FileOutputStream("MyLib.swc")), true); * </pre> * * The <code>setDirectory()</code> method lets you output RSLs to the specified directory; for example: * * <pre> * lib.setDirectory(new File("dir1")); * lib.build(true); * </pre> * * You can save the <code>Library</code> object compilation * data for reuse. You do this using the <code>save(OutputStream)</code> method. Subsequent compilations can use * the <code>load(OutputStream)</code> method to get the old data into the <code>Library</code> object; for example: * * <pre> * lib.save(new BufferedOutputStream(new FileOutputStream("MyLib.incr"))); * </pre> * * When a cache file (for example, <code>MyLib.incr</code>) from a previous compilation is available before the * compilation, you can call the <code>load(OutputStream)</code> method before you call the <code>build()</code> method; for example: * * <pre> * lib.load(new BufferedInputStream(FileInputStream("MyLib.incr"))); * lib.build(true); * </pre> * * The <code>build(false)</code> and <code>build(OutputStream, false)</code> methods always rebuild the library. * The first time you build the <code>Library</code> * object, the <code>build(true)/build(OutputStream, true)</code> methods do a complete build, which * is equivalent to the <code>build(false)/build(OutputStream, false)</code> methods, respectively. After you call the * <code>clean()</code> method, the <code>Library</code> object always does a full build. * * <p> * The <code>clean()</code> method cleans up compilation data in the <code>Library</code> object the output * file, if the <code>setOutput()</code> method was called. * * <p> * You can use the <code>Library</code> class to build a library from a combination of source * files in the file system and in-memory, dynamically-generated source objects. You * must use the <code>addComponent(VirtualLocalFile)</code>, <code>addResourceBundle(VirtualLocalFile)</code>, and * <code>addArchiveFile(String, VirtualLocalFile)</code> methods to use in-memory objects. * * <p> * The <code>Library</code> class can be part of a <code>Project</code>. * * @see flex2.tools.oem.Configuration * @see flex2.tools.oem.Project * @version 2.0.1 * @author Clement Wong */ public class Library implements Builder, Cloneable { static { // This "should" trigger the static initialization of Application which locates // flex-compiler-oem.jar and set application.home correctly. try { // in Java 1.4, simply saying Application.class would load the class // Java 1.5 is much smarter, and you have to coax the JVM to actually load it Class.forName("flex2.tools.oem.Application"); } catch (ClassNotFoundException e) { // I guess it didn't work *shrug* e.printStackTrace(); assert false; } } /** * Constructor. */ public Library() { sources = new TreeSet<VirtualFile>(new Comparator<VirtualFile>() { public int compare(VirtualFile f0, VirtualFile f1) { return f0.getName().compareTo(f1.getName()); } }); classes = new TreeSet<String>(); namespaces = new TreeSet<URI>(); resourceBundles = new TreeSet<String>(); files = new TreeMap<String, VirtualFile>(); stylesheets = new TreeMap<String, VirtualFile>(); oemConfiguration = null; logger = null; output = null; directory = null; mimeMappings = new MimeMappings(); meter = null; resolver = null; cc = new CompilerControl(); //data = null; cacheName = null; configurationReport = null; messages = new ArrayList<Message>(); } private Set<VirtualFile> sources; private Set<String> classes, resourceBundles; private Set<URI> namespaces; private Map<String, VirtualFile> files, stylesheets; private OEMConfiguration oemConfiguration; private Logger logger; private File output, directory; private MimeMappings mimeMappings; private ProgressMeter meter; protected PathResolver resolver; private CompilerControl cc; private ApplicationCache applicationCache; private LibraryCache libraryCache; // clean() would null out the following variables //LibraryData data; private String cacheName, configurationReport; private List<Message> messages; private HashMap<String, PerformanceData[]> compilerBenchmarks; private Benchmark benchmark; /** * Adds a class, function, variable, or namespace to this <code>Library</code> object. * * This is the equilvalent of the <code>include-classes</code> option of the compc compiler. * * @param includeClass A fully-qualified name. */ public void addComponent(String includeClass) { classes.add(includeClass); } /** * Adds a component to this <code>Library</code> object. * This is the equilvalent of the <code>include-sources</code> option of the compc compiler. * * @param includeSource A source file. */ public void addComponent(File includeSource) { sources.add(new LocalFile(includeSource)); } /** * Adds a component to this <code>Library</code> object. * * This is equilvalent to the <code>include-sources</code> option of the compc compiler. * * @param includeSource An in-memory source object. */ public void addComponent(VirtualLocalFile includeSource) { sources.add(includeSource); } /** * Adds a list of components to this <code>Library</code> object. * * This is equilvalent to the <code>include-namespaces</code> option of the compc compiler. * * @param includeNamespace A namespace URI. */ public void addComponent(URI includeNamespace) { namespaces.add(includeNamespace); } /** * Removes the specified component from this <code>Library</code> object. * The name can be a class, a function, a variable, or a namespace. * * @param includeClass A fully-qualified name. */ public void removeComponent(String includeClass) { classes.remove(includeClass); } /** * Removes the specified component from this <code>Library</code> object. * * @param includeSource A source file. */ public void removeComponent(File includeSource) { sources.remove(new LocalFile(includeSource)); } /** * Removes the specified component from this <code>Library</code> object. * * @param includeSource An in-memory source object. */ public void removeComponent(VirtualLocalFile includeSource) { sources.remove(includeSource); } /** * Removes the specified list of components from this <code>Library</code> object. The input argument is a namespace URI. * * @param includeNamespace A namespace URI. */ public void removeComponent(URI includeNamespace) { namespaces.remove(includeNamespace); } /** * Removes all the components from this <code>Library</code> object. */ public void removeAllComponents() { sources.clear(); classes.clear(); namespaces.clear(); } /** * Adds a resource bundle to this <code>Library</code> object. * * This is equilvalent to the <code>include-resource-bundles</code> option of the compc compiler. * * @param resourceBundle A resource bundle name. */ public void addResourceBundle(String resourceBundle) { resourceBundles.add(resourceBundle); } /** * Removes the specified resource bundle name from this <code>Library</code> object. * * @param resourceBundle A resource bundle name. */ public void removeResourceBundle(String resourceBundle) { resourceBundles.remove(resourceBundle); } /** * Removes all the resource bundles from this <code>Library</code> object. * */ public void removeAllResourceBundles() { resourceBundles.clear(); } /** * Adds a file to this <code>Library</code> object. This is equilvalent to the <code>include-file</code> option of the compc compiler. * * @param name The name in the archive. * @param file The file to be added. */ public void addArchiveFile(String name, File file) { files.put(name, new LocalFile(file)); } /** * Adds an in-memory source object to this <code>Library</code> object. This is equilvalent to the <code> * include-file</code> option of the compc compiler. * * @param name The name in the archive. * @param file The in-memory source object to be added. */ public void addArchiveFile(String name, VirtualLocalFile file) { files.put(name, file); } /** * Removes the specified file from this <code>Library</code> object. * * @param name The name in the archive. */ public void removeArchiveFile(String name) { files.remove(name); } /** * Removes all the archive files from this <code>Library</code> object. */ public void removeAllArchiveFiles() { files.clear(); } /** * Adds a CSS stylesheet to this <code>Library</code> object. This is equilvalent to the <code>include-stylesheet</code> option of the compc compiler. * * @param name The name in the archive. * @param file The file to be added. * @since 3.0 */ public void addStyleSheet(String name, File file) { stylesheets.put(name, new LocalFile(file)); } /** * Adds an in-memory CSS stylesheet object to this <code>Library</code> object. This is equilvalent to the <code> * include-stylesheet</code> option of the compc compiler. * * @param name The name in the archive. * @param file The in-memory source object to be added. * @since 3.0 */ public void addStyleSheet(String name, VirtualLocalFile file) { stylesheets.put(name, file); } /** * Removes the specified CSS stylesheet from this <code>Library</code> object. * * @param name The name in the archive. * @since 3.0 */ public void removeStyleSheet(String name) { stylesheets.remove(name); } /** * Removes all the CSS stylesheets from this <code>Library</code> object. * @since 3.0 */ public void removeAllStyleSheets() { stylesheets.clear(); } /** * @inheritDoc */ public void setConfiguration(Configuration configuration) { oemConfiguration = (OEMConfiguration) configuration; } /** * @inheritDoc */ public Configuration getDefaultConfiguration() { return getDefaultConfiguration(false); } /** * * @param processDefaults * @return */ private Configuration getDefaultConfiguration(boolean processDefaults) { return OEMUtil.getLibraryConfiguration(constructCommandLine(null), false, false, OEMUtil.getLogger(logger, messages), resolver, mimeMappings, processDefaults); } /** * @inheritDoc */ public HashMap<String, PerformanceData[]> getCompilerBenchmarks() { return compilerBenchmarks; } /** * @inheritDoc */ public Benchmark getBenchmark() { return benchmark; } /** * @inheritDoc */ public Configuration getConfiguration() { return oemConfiguration; } /** * @inheritDoc */ public void setLogger(Logger logger) { this.logger = logger; } /** * @inheritDoc */ public Logger getLogger() { return logger; } /** * @inheritDoc */ public void setSupportedFileExtensions(String mimeType, String[] extensions) { mimeMappings.set(mimeType, extensions); } /** * Sets the output destination. This method is necessary if you use the <code>build(boolean)</code> method. * If you use the <code>build(OutputStream, boolean)</code> method, there is no need to use this method. * * @param output An instance of the <code>java.io.File</code> class. */ public void setOutput(File output) { this.output = output; } /** * Gets the output destination. This method returns <code>null</code> if you did not call the * <code>setOutput()</code> method. * * @return An instance of the <code>java.io.File</code> class, or <code>null</code> if you did not * call the <code>setOutput()</code> method. */ public File getOutput() { return output; } /** * Sets the RSL output directory. * * @param directory An RSL directory. */ public void setDirectory(File directory) { this.directory = directory; } /** * Gets the RSL output directory. * * @return A <code>java.io.File</code>, or <code>null</code> if you did not call the <code>setDirectory()</code> method. */ public File getDirectory() { return directory; } /** * @inheritDoc */ public void setProgressMeter(ProgressMeter meter) { this.meter = meter; } /** * @inheritDoc */ public void setPathResolver(PathResolver resolver) { this.resolver = resolver; } /** * @inheritDoc */ // IMPORTANT: If you make changes here, you probably want to mirror them in Application.build() public long build(boolean incremental) throws IOException { // I know that directory is not referenced anywhere in here... // if you setDirectory but do not setOutput, then output==null but dirctory!=null // so this silly looking IF needs to be like this... if (output != null || directory != null) { long size = 0; //TODO PERFORMANCE: A lot of unnecessary recopying and buffering here try { @SuppressWarnings("unused") int result = compile(incremental); return size; } finally { //runExtensions(); clean(false /* cleanData */, false /* cleanCache */, false /* cleanOutput */, true /* cleanConfig */, false /* cleanMessages */, true /* cleanThreadLocals */); } } else { return 0; } } /* private void runExtensions() { if (oemConfiguration != null) { Set<ILibraryExtension> extensions = ExtensionManager.getLibraryExtensions( oemConfiguration.getExtensions() ); for ( ILibraryExtension extension : extensions ) { if (ThreadLocalToolkit.errorCount() == 0) { extension.run( this.clone(), oemConfiguration.clone() ); } } } } */ /** * @inheritDoc * * Note: If the OutputStream is written to a File, * refreshLastModified() should be called to update the timestamp * in the SwcCache. Otherwise, subsequent builds in this Project * will think the Library has been externally updated and will * force a reload. */ public long build(OutputStream out, boolean incremental) throws IOException { try { @SuppressWarnings("unused") int result = compile(incremental); /* if (result == SKIP || result == LINK || result == OK) { return link(out); } else { */ return 0; //} } finally { //runExtensions(); clean(false /* cleanData */, false /* cleanCache */, false /* cleanOutput */, true /* cleanConfig */, false /* cleanMessages */, true /* cleanThreadLocals */); } } /** * @inheritDoc */ public void stop() { cc.stop(); } /** * @inheritDoc */ public void clean() { clean(true /* cleanData */, true /* cleanCache */, true /* cleanOutput */, true /* cleanConfig */, true /* cleanMessages */, true /* cleanThreadLocals */); } /** * @inheritDoc */ public void load(InputStream in) throws IOException { } /** * @inheritDoc */ public long save(OutputStream out) throws IOException { return 1; } /** * @inheritDoc */ public Report getReport() { //OEMUtil.setupLocalizationManager(); return new OEMReport(null, null, null, null, configurationReport, messages, files); } /** * * @param c * @return */ private String[] constructCommandLine(OEMConfiguration localOEMConfiguration) { String[] commandLine = (localOEMConfiguration != null) ? localOEMConfiguration.getCompilerOptions() : new String[0]; if (output != null) { // add output parameter String[] outputCommandLine = new String[commandLine.length + 1]; System.arraycopy(commandLine, 0, outputCommandLine, 0, commandLine.length); outputCommandLine[commandLine.length] = "-output=" + output.getAbsolutePath(); commandLine = outputCommandLine; } // Translate "classes" into "-include-classes" so the CompcConfiguration can // properly validate the configuration. if (classes.size() > 0) { StringBuilder buffer = new StringBuilder("-include-classes="); for (Iterator<String> iter = classes.iterator(); iter.hasNext();) { String className = iter.next(); buffer.append(className); if (iter.hasNext()) { buffer.append(","); } } String[] newCommandLine = new String[commandLine.length + 1]; System.arraycopy(commandLine, 0, newCommandLine, 0, commandLine.length); newCommandLine[commandLine.length] = buffer.toString(); return newCommandLine; } // Translate "sources" into "-include-sources" so the CompcConfiguration can // properly validate the configuration. if (sources.size() > 0) { StringBuilder buffer = new StringBuilder("-include-sources="); for (Iterator<VirtualFile> iter = sources.iterator(); iter.hasNext();) { String className = iter.next().getName(); buffer.append(className); if (iter.hasNext()) { buffer.append(","); } } String[] newCommandLine = new String[commandLine.length + 1]; System.arraycopy(commandLine, 0, newCommandLine, 0, commandLine.length); newCommandLine[commandLine.length] = buffer.toString(); return newCommandLine; } return commandLine; } /** * Compiles the <code>Library</code>. This method does not link the <code>Library</code>. * * @param incremental If <code>true</code>, build incrementally; if <code>false</code>, rebuild. * @return {@link Builder#OK} if this method call resulted in compilation of some/all parts of the application; * {@link Builder#LINK} if this method call did not compile anything in the application but advise the caller to link again; * {@link Builder#SKIP} if this method call did not compile anything in the application; * {@link Builder#FAIL} if this method call encountered errors during compilation. */ protected int compile(boolean incremental) { try { messages.clear(); // if there is no configuration, use the default... but don't populate this.configuration. OEMConfiguration tempOEMConfiguration; if (oemConfiguration == null) { tempOEMConfiguration = (OEMConfiguration) getDefaultConfiguration(true); } else { tempOEMConfiguration = OEMUtil.getLibraryConfiguration(constructCommandLine(oemConfiguration), oemConfiguration.keepLinkReport(), oemConfiguration.keepSizeReport(), OEMUtil.getLogger(logger, messages), resolver, mimeMappings); } // if c is null, which indicates problems, this method will return. if (tempOEMConfiguration == null) { clean(false /* cleanData */, false /* cleanCache */, false /* cleanOutput */); return FAIL; } else if (oemConfiguration != null && oemConfiguration.keepConfigurationReport()) { configurationReport = OEMUtil.formatConfigurationBuffer(tempOEMConfiguration.cfgbuf); } if (oemConfiguration != null) { oemConfiguration.cfgbuf = tempOEMConfiguration.cfgbuf; } // add archive files to the link checksum for (Map.Entry<String, VirtualFile>entry : files.entrySet()) { tempOEMConfiguration.cfgbuf.calculateLinkChecksum(entry.getKey(), entry.getValue().getLastModified()); } // initialize some ThreadLocal variables... cc.run(); OEMUtil.init(OEMUtil.getLogger(logger, messages), mimeMappings, meter, resolver, cc); // if there is any problem getting the licenses, this method will return. //Map licenseMap = OEMUtil.getLicenseMap(tempOEMConfiguration.configuration); // if there are no SWC inputs, output an error and return -1 VirtualFile[] includeLibs = (tempOEMConfiguration.configuration == null) ? null : tempOEMConfiguration.configuration.getCompilerConfiguration().getIncludeLibraries(); if (sources.size() == 0 && classes.size() == 0 && namespaces.size() == 0 && resourceBundles.size() == 0 && files.size() == 0 && stylesheets.size() == 0 && (includeLibs == null || includeLibs.length == 0)) { ThreadLocalToolkit.log(new ConfigurationException.NoSwcInputs( null, null, -1 )); clean(false /* cleanData */, false /* cleanCache */, false /* cleanOutput */); return FAIL; } CompilerConfiguration compilerConfig = tempOEMConfiguration.configuration.getCompilerConfiguration(); compilerConfig.setMetadataExport(true); clean(true /* cleanData */, false /* cleanCache */, false /* cleanOutput */, true /* cleanConfig */, false /* cleanMessages */, false /* cleanThreadLocals */); COMPC compc = new COMPC(); int returnValue = compc.mainNoExit(constructCommandLine(oemConfiguration)); if (returnValue == 0) returnValue = OK; else returnValue = FAIL; convertMessages(compc.getProblems()); clean(returnValue != OK, false, false); return returnValue; } finally { // clean thread locals OEMUtil.clean(); } } public long link(OutputStream output) { try { FileInputStream inStream = new FileInputStream(this.output); byte[] b = new byte[(int) this.output.length()]; inStream.read(b); output.write(b); inStream.close(); return this.output.length(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return -1; } /** * * @param cleanData * @param cleanCache * @param cleanOutput */ private void clean(boolean cleanData, boolean cleanCache, boolean cleanOutput) { clean(cleanData, cleanCache, cleanOutput, true /* cleanConfig */, false /* cleanMessages */, false /* cleanThreadLocals */); } /** * * @param cleanData * @param cleanCache * @param cleanOutput * @param cleanConfig * @param cleanMessages * @param cleanThreadLocals */ private void clean(boolean cleanData, boolean cleanCache, boolean cleanOutput, boolean cleanConfig, boolean cleanMessages, boolean cleanThreadLocals) { if (cleanThreadLocals) { OEMUtil.clean(); } if (oemConfiguration != null && cleanConfig) { oemConfiguration.reset(); } if (cleanData) { //data = null; configurationReport = null; } if (cleanCache) { if (cacheName != null) { File dead = FileUtil.openFile(cacheName); if (dead != null && dead.exists()) { dead.delete(); } cacheName = null; } } if (cleanOutput) { if (output != null && output.exists()) { output.delete(); } } if (cleanMessages) { messages.clear(); } } /** * * @param s1 * @param s2 * @return private <T> boolean isDifferent(Collection<T> s1, Collection<T> s2) { for (Iterator<T> i = s2.iterator(); i.hasNext(); ) { if (!s1.contains(i.next())) { return true; } } return s1.size() > s2.size(); } */ /** * Returns the cache of sources in the source list and source * path. After building this Application object, the cache may be * used to compile another Application object with common sources. * * @return The active cache. May be null. * * @since 4.5 */ public ApplicationCache getApplicationCache() { return applicationCache; } /** * Sets the cache for sources in the source list and source path. * After compiling an Application object, the cache may be reused * to build another Application object with common sources. * * @param applicationCache A reference to the application cache. * * @since 4.5 */ public void setApplicationCache(ApplicationCache applicationCache) { this.applicationCache = applicationCache; } // TODO: deprecate getSwcCache() and setSwcCache(), then add // getLibraryCache() and setLibraryCache(). /** * Get the cache of swcs in the library path. After building this Application * object the cache may be saved and used to compile another Application object * that uses the same library path. * * @return The active cache. May be null. * * @since 3.0 */ public LibraryCache getSwcCache() { return libraryCache; } /** * Set the cache for swcs in the library path. After compiling an * Application object the cache may be reused to build another Application * object that uses the same library path. * * @param swcCache A reference to an allocated swc cache. * * @since 3.0 */ public void setSwcCache(LibraryCache libraryCache) { this.libraryCache = libraryCache; } @Override public Library clone() { Library clone; try { clone = (Library) super.clone(); } catch ( CloneNotSupportedException e ) { throw new RuntimeException( e ); //wont happen } clone.oemConfiguration = oemConfiguration.clone(); return clone; } public void refreshLastModified() { } public void convertMessages(ProblemQuery pq) { List<ICompilerProblem> probs = pq.getProblems(); for (ICompilerProblem prob : probs) { Class aClass = prob.getClass(); Annotation[] annotations = aClass.getAnnotations(); for(Annotation annotation : annotations){ if(annotation instanceof DefaultSeverity){ DefaultSeverity myAnnotation = (DefaultSeverity) annotation; CompilerProblemSeverity cps = myAnnotation.value(); String level; if (cps.equals(CompilerProblemSeverity.ERROR)) level = Message.ERROR; else if (cps.equals(CompilerProblemSeverity.WARNING)) level = Message.WARNING; else break; // skip if IGNORE? CompilerMessage msg = new CompilerMessage(level, prob.getSourcePath(), prob.getLine() + 1, prob.getColumn()); try { String errText = ProblemFormatter.DEFAULT_FORMATTER.format(prob); msg.setMessage(errText); } catch (IllegalArgumentException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (SecurityException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } messages.add(msg); try { logger.log(msg, aClass.getField("errorCode").getInt(null), prob.getSourcePath()); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { try { logger.log(msg, aClass.getField("warningCode").getInt(null), prob.getSourcePath()); } catch (IllegalArgumentException e1) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e1) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e1) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e1) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } }