/**
* Copyright (C) 2010-2017 Structr GmbH
*
* This file is part of Structr <http://structr.org>.
*
* Structr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Structr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Structr. If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.web.entity;
import com.google.javascript.jscomp.BasicErrorManager;
import com.google.javascript.jscomp.CheckLevel;
import com.google.javascript.jscomp.CommandLineRunner;
import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.JSError;
import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.jscomp.parsing.parser.util.format.SimpleFormat;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.structr.common.PropertyView;
import org.structr.common.View;
import org.structr.common.error.FrameworkException;
import org.structr.core.graph.ModificationEvent;
import org.structr.core.property.EnumProperty;
import org.structr.core.property.Property;
import org.structr.core.property.PropertyMap;
import org.structr.core.property.StringProperty;
import org.structr.web.common.FileHelper;
import org.structr.web.entity.relation.MinificationSource;
public class MinifiedJavaScriptFile extends AbstractMinifiedFile {
private static final Logger logger = LoggerFactory.getLogger(MinifiedJavaScriptFile.class.getName());
public static final Property<CompilationLevel> optimizationLevel = new EnumProperty<>("optimizationLevel", CompilationLevel.class, CompilationLevel.WHITESPACE_ONLY);
public static final Property<String> warnings = new StringProperty("warnings");
public static final Property<String> errors = new StringProperty("errors");
public static final View defaultView = new View(MinifiedJavaScriptFile.class, PropertyView.Public, minificationSources, optimizationLevel, warnings, errors);
public static final View uiView = new View(MinifiedJavaScriptFile.class, PropertyView.Ui, minificationSources, optimizationLevel, warnings, errors);
@Override
public boolean shouldModificationTriggerMinifcation(ModificationEvent modState) {
return modState.getModifiedProperties().containsKey(MinifiedJavaScriptFile.optimizationLevel);
}
@Override
public void minify() throws FrameworkException, IOException {
logger.info("Running minify: {}", this.getUuid());
final Compiler compiler = new Compiler();
final CompilerOptions options = new CompilerOptions();
final CompilationLevel selectedLevel = getProperty(optimizationLevel);
selectedLevel.setOptionsForCompilationLevel(options);
compiler.setErrorManager(new BasicErrorManager() {
@Override
public void println(CheckLevel level, JSError error) {
// if (level != CheckLevel.OFF) {
// logger.log((level == CheckLevel.ERROR) ? Level.SEVERE : Level.WARNING, error.toString());
// }
}
@Override
protected void printSummary() {
if (getTypedPercent() > 0) {
if (getErrorCount() + getWarningCount() == 0) {
logger.info(SimpleFormat.format("%d error(s), %d warning(s), %.1f%% typed", getErrorCount(), getWarningCount(), getTypedPercent()));
} else {
logger.warn(SimpleFormat.format("%d error(s), %d warning(s), %.1f%% typed", getErrorCount(), getWarningCount(), getTypedPercent()));
}
} else if (getErrorCount() + getWarningCount() > 0) {
logger.warn(SimpleFormat.format("%d error(s), %d warning(s)", getErrorCount(), getWarningCount()));
}
}
});
compiler.compile(CommandLineRunner.getBuiltinExterns(options), getSourceFileList(), options);
FileHelper.setFileData(this, compiler.toSource().getBytes(), getProperty(contentType));
final PropertyMap changedProperties = new PropertyMap();
changedProperties.put(warnings, StringUtils.join(compiler.getWarnings(), System.lineSeparator()));
changedProperties.put(errors, StringUtils.join(compiler.getErrors(), System.lineSeparator()));
setProperties(securityContext, changedProperties);
}
private ArrayList<SourceFile> getSourceFileList() throws FrameworkException, IOException {
ArrayList<SourceFile> sourceList = new ArrayList();
int cnt = 0;
for (MinificationSource rel : getSortedRelationships()) {
final FileBase src = rel.getTargetNode();
sourceList.add(SourceFile.fromCode(src.getProperty(FileBase.name), FileUtils.readFileToString(src.getFileOnDisk())));
// compact the relationships (if necessary)
if (rel.getProperty(MinificationSource.position) != cnt) {
rel.setProperties(securityContext, new PropertyMap(MinificationSource.position, cnt));
}
cnt++;
}
return sourceList;
}
}