All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.codename1.maven.InstallCn1libsMojo Maven / Gradle / Ivy
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.codename1.maven;
import com.codename1.ant.SortedProperties;
import static com.codename1.maven.ProjectUtil.wrap;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Delete;
import org.apache.tools.ant.taskdefs.Expand;
/**
*
* @author shannah
*/
@Mojo(name = "installcn1libs", requiresDependencyResolution = ResolutionScope.TEST)
public class InstallCn1libsMojo extends AbstractCN1Mojo {
/**
* Extracts cn1lib artifact so that its contents can be accessed directly. Extracted to {@link #getLibDirFor(org.apache.maven.artifact.Artifact) }
* @param artifact
* @return
* @throws IOException
*/
private boolean extractArtifact(Artifact artifact) throws IOException {
File cn1libFile = findArtifactFile(artifact);
File destDir = getLibDirFor(artifact);
getLog().info("Extracting cn1lib "+artifact+" to "+destDir);
boolean requiresUpdate = !destDir.isDirectory() || destDir.lastModified() < cn1libFile.lastModified();
if ("true".equals(System.getProperty("cn1.updateLibs", null))) {
requiresUpdate = true;
}
if (!requiresUpdate) {
getLog().info("no update required for "+artifact);
return false;
}
if (destDir.exists()) {
Delete del = (Delete)antProject.createTask("delete");
del.setDir(destDir);
del.execute();
}
Expand unzip = (Expand)antProject.createTask("unzip");
destDir.mkdirs();
unzip.setDest(destDir);
unzip.setSrc(cn1libFile);
unzip.execute();
// Extract the nativese stuff now
File nativeSeZip = Cn1libUtil.getNativeSEJar(artifact);
if (nativeSeZip != null && nativeSeZip.exists()) {
unzip = (Expand)antProject.createTask("unzip");
unzip.setDest(new File(nativeSeZip.getParentFile(), nativeSeZip.getName()+"-extracted"));
unzip.setSrc(nativeSeZip);
unzip.execute();
}
return true;
}
private long getLastModifiedCn1libDependencies() {
long lastModified = 0;
for (Artifact artifact : project.getDependencyArtifacts()) {
lastModified = Math.max(getLastModified(artifact), lastModified);
}
return lastModified;
}
private boolean isProjectUpdateRequired() throws IOException {
return getLastModifiedCn1libDependencies() > getLastProjectUpdate();
}
private long getLastProjectUpdate() throws IOException {
String lastUpdated = getMavenProperties().getProperty("lastUpdated");
if (lastUpdated == null) {
return 0L;
}
try {
return Long.parseLong(lastUpdated);
} catch (Exception ex) {
return 0L;
}
}
@Override
public void executeImpl() throws MojoExecutionException, MojoFailureException {
setupCef();
Exception[] err = new Exception[1];
List cn1libArtifacts = new ArrayList<>();
project.getArtifacts().forEach(artifact -> {
File jarFile = findArtifactFile(artifact);
if (jarFile != null && Cn1libUtil.isCN1Lib(jarFile)) {
cn1libArtifacts.add(artifact);
try {
if(extractArtifact(artifact)) {
}
} catch (IOException ex) {
err[0] = ex;
}
}
});
boolean forceUpdate = false;
if ("true".equals(System.getProperty("cn1.updateLibs", null))) {
forceUpdate = true;
}
try {
if (forceUpdate || isProjectUpdateRequired()) {
File classesDir = new File(project.getBuild().getOutputDirectory());
delTree(classesDir);
classesDir.mkdirs();
getLog().info("Dependencies have changed. Updating project properties and CSS");
// The dependencies have changed
boolean changed = false;
for (Artifact artifact : project.getArtifacts()) {
if (mergeProjectProperties(artifact)) {
getLog().info("Merged properties for "+artifact+" into project properties");
changed = true;
}
getLog().info("UPdating project css for "+artifact);
updateProjectCSS(artifact);
}
if (changed) {
getLog().info("Project properties where updated. Saving changes");
saveProjectProperties();
}
saveProjectDependencies();
}
} catch (IOException ioe) {
getLog().error("Failed to update project properties and CSS files with new dependencies from pom.xml file.");
throw new MojoExecutionException("Failed to update project properties and CSS with new dependencies.", ioe);
}
if (err[0] != null) {
throw new MojoExecutionException("Failed to extract cn1lib dependencies.", err[0]);
}
}
/**
* Merges artifact's codenameone_library_appended.properties and codenameone_library_required.properties with the
* projects's codenameone_settings.properties file.
*
* Does not persist to disk.
*
* @param artifact
* @return True if any changes were made to the codenameone_settings properties.
* @throws IOException
*/
private boolean mergeProjectProperties(Artifact artifact) throws IOException {
boolean changed = false;
if (mergeProjectRequiredProperties(artifact)) {
changed = true;
}
if (mergeProjectAppendedProperties(artifact)) {
changed = true;
}
return changed;
}
/**
* Merges the lib's appended properties with the project properties. Does not persist to file system.
* @param artifact
* @return True if changes were made to the project properties.s
* @throws IOException
*/
private boolean mergeProjectAppendedProperties(Artifact artifact) throws IOException {
Properties projectProps = getProjectProperties();
Properties libProps = getLibraryAppendedProperties(artifact);
Properties merged = projectProps;
//merged.putAll(projectProps);
Enumeration keys = libProps.propertyNames();
boolean changed = false;
while(keys.hasMoreElements()){
String key = (String) keys.nextElement();
if(!merged.containsKey(key)){
merged.put(key, libProps.getProperty(key));
changed = true;
}else{
String val = merged.getProperty(key);
String libval = libProps.getProperty(key);
if(!val.contains(libval)){
//append libval to the property
merged.put(key, val + libval);
changed = true;
}
}
}
return changed;
}
/**
* Merges the lib's required properties with the project properties. Does not persist.
* @param artifact
* @return True if project properties were changed.
* @throws IOException
*/
private boolean mergeProjectRequiredProperties(Artifact artifact) throws IOException {
SortedProperties projectProps = getProjectProperties();
SortedProperties libProps = getLibraryRequiredProperties(artifact);
String javaVersion = (String)projectProps.getProperty("codename1.arg.java.version", "8");
String javaVersionLib = (String)libProps.get("codename1.arg.java.version");
if(javaVersionLib != null){
int v1 = 5;
if(javaVersion != null){
v1 = Integer.parseInt(javaVersion);
}
int v2 = Integer.parseInt(javaVersionLib);
//if the lib java version is bigger, this library cannot be used
if(v1 < v2){
throw new BuildException("Cannot use a cn1lib with java version "
+ "greater then the project java version");
}
}
//merge and save
SortedProperties merged = projectProps;
// merged.putAll(projectProps);
Enumeration keys = libProps.propertyNames();
boolean changed = false;
while(keys.hasMoreElements()){
String key = (String) keys.nextElement();
if(!merged.containsKey(key)){
merged.put(key, libProps.getProperty(key));
changed = true;
}else{
//if this property already exists with a different value the
//install will fail
if(!merged.get(key).equals(libProps.getProperty(key))){
throw new BuildException("Property " + key + " has a conflict");
}
}
}
return changed;
}
/**
* Project's theme.css file
* @return
*/
private File getProjectCSSFile() {
return new File(getProjectCSSDir(), "theme.css");
}
/**
* Project's theme.css file contents.
*
* @return
* @throws IOException
*/
private String getProjectCSSFileContents()throws IOException {
File cssFile = getProjectCSSFile();
byte[] buf = new byte[(int)cssFile.length()];
int len;
try (FileInputStream fis = new FileInputStream(cssFile)) {
len = fis.read(buf);
}
return new String(buf, "UTF-8");
}
/**
* Lib's theme.css file contents.
* @param artifact
* @return
* @throws IOException
*/
private String getLibCSSFileContents(Artifact artifact)throws IOException {
File cssFile = getLibCSSFile(artifact);
byte[] buf = new byte[(int)cssFile.length()];
int len;
try (FileInputStream fis = new FileInputStream(cssFile)) {
len = fis.read(buf);
}
return new String(buf, "UTF-8");
}
/**
* CSS zip for library.
* @param artifact
* @return
* @throws IOException
*/
private File getLibCSSZip(Artifact artifact) throws IOException {
return new File(getLibDirFor(artifact), "META-INF" + File.separator + "cn1lib" + File.separator + "css.zip");
}
/**
* Lib CSS directory (extracted from CSSZip). This location is likely inside the local repository.
* @param artifact
* @return
* @throws IOException
*/
private File getLibCSSDir(Artifact artifact) throws IOException {
return new File(getLibCSSZip(artifact).getParentFile(), "css");
}
/**
* Gets lib theme.css file from local repository.
* @param artifact
* @return
* @throws IOException
*/
private File getLibCSSFile(Artifact artifact) throws IOException {
return new File(getLibCSSDir(artifact), "theme.css");
}
/**
* Extacts lib's CSS directory inside the local repository.
* @param artifact
* @throws IOException
*/
private void extractLibCSSDir(Artifact artifact) throws IOException {
Expand unzip = (Expand)antProject.createTask("unzip");
unzip.setSrc(getLibCSSZip(artifact));
unzip.setDest(getLibCSSDir(artifact));
unzip.execute();
}
/*
// Originally we were attempting to programmatically add to the classpath by generating system scope dependencies
// but this doesn't work... keeping this here for posterity as this may still be useful for something.
private Dependency createSystemScopeDependency(String artifactId, String groupId, String version, File location) {
Dependency dependency = new Dependency();
dependency.setGroupId(groupId);
dependency.setArtifactId(artifactId+"-jar");
dependency.setVersion(version);
dependency.setScope(Artifact.SCOPE_SYSTEM);
dependency.setSystemPath(location.getAbsolutePath());
dependency.setType("jar");
dependency.setClassifier("jar");
return dependency;
}
*/
/**
* String with existing cn1lib dependencies in the project. This helps us determine if any dependencies have changed
* since we last updated the project.
* @return
* @throws IOException
*/
private String getExistingDependencies() throws IOException {
return getMavenProperties().getProperty("dependencies", "");
}
/**
* Gets the dependencies string from the current pom.xml file which can be compared with {@link #getExistingDependencies() } to
* determine if the project files need to be updated (i.e. dependencies have changed since last update).
* @return
* @throws IOException
*/
private String getPomDependencies() throws IOException {
List deps = new ArrayList<>();
project.getDependencyArtifacts().forEach(artifact -> {
File jarFile = findArtifactFile(artifact);
if (Cn1libUtil.isCN1Lib(jarFile)) {
deps.add(artifact.getGroupId()+":"+artifact.getArtifactId()+":"+artifact.getVersion());
}
});
Collections.sort(deps);
StringBuilder sb = new StringBuilder();
deps.forEach(dep -> {
sb.append(" ").append(dep);
});
return sb.toString().trim();
}
/**
* Saves the current pom dependencies into the {@link #getMavenProperties() } and saves to disk.
* @throws IOException
*/
private void saveProjectDependencies() throws IOException {
getMavenProperties().put("dependencies", getPomDependencies());
getMavenProperties().put("lastUpdated", ""+System.currentTimeMillis());
saveMavenProperties();
}
/**
* Checks if dependencies have changed in the pom file since the last time the project files
* were updated.
* @return
* @throws IOException
*/
public boolean checkDependenciesChanged() throws IOException {
return !getPomDependencies().equals(getExistingDependencies());
}
/**
* Appended properties file for library.
* @param artifact
* @return
*/
private File getLibraryAppendedPropertiesFile(Artifact artifact) {
File dir = getLibDirFor(artifact);
return new File(dir, "META-INF" + File.separator + "codenameone_library_appended.properties");
}
/**
* Appended properties for library.
* @param artifact
* @return
* @throws IOException
*/
private SortedProperties getLibraryAppendedProperties(Artifact artifact) throws IOException {
SortedProperties out = new SortedProperties();
File file = getLibraryAppendedPropertiesFile(artifact);
if (file.exists()) {
try (FileInputStream fis = new FileInputStream(file)) {
out.load(fis);
}
}
return out;
}
/**
* Required properties file for library.
* @param artifact
* @return
*/
private File getLibraryRequiredPropertiesFile(Artifact artifact) {
File dir = getLibDirFor(artifact);
return new File(dir, "META-INF" + File.separator + "codenameone_library_required.properties");
}
/**
* Required properties for library.
* @param artifact
* @return
* @throws IOException
*/
private SortedProperties getLibraryRequiredProperties(Artifact artifact) throws IOException {
SortedProperties out = new SortedProperties();
File file = getLibraryRequiredPropertiesFile(artifact);
if (file.exists()) {
try (FileInputStream fis = new FileInputStream(file)) {
out.load(fis);
}
}
return out;
}
/**
* Throws IOException indicating that CSS activation in project is required.
* @param cn1lib
* @throws IOException
*/
private void failActivateCSS(Artifact cn1lib) throws IOException {
throw new IOException("The library "+cn1lib+" cannot be added to this project because it requires CSS. Please activate CSS in your project before trying to add this library. \nSee https://www.codenameone.com/manual/css.html for instructions on activating CSS");
}
/**
* Updates project CSS with the lib's CSS.
* @param artifact
* @throws IOException
*/
private void updateProjectCSS(Artifact artifact) throws IOException {
File cssZip = getLibCSSZip(artifact);
if (!cssZip.exists()) {
getLog().info(cssZip+" does not exist");
getLog().info("Checking if is cn1lib "+artifact.getFile());
if (!getLibDirFor(artifact).exists() && Cn1libUtil.isCN1Lib(artifact.getFile())) {
getLog().info("Extracting artifact");
extractArtifact(artifact);
}
if (!cssZip.exists()) {
getLog().info(cssZip+" still doesn't exist");
return;
}
}
File libCssDir = getLibCSSDir(artifact);
if (!libCssDir.exists()) {
System.out.println("css dir "+libCssDir+" does not exist yet. Extracting zip");
extractLibCSSDir(artifact);
}
File libCSSFile = getLibCSSFile(artifact);
if (!libCSSFile.exists()) {
System.out.println("No theme.css "+libCSSFile+" found");
return;
}
if (!"true".equals(getProjectProperties().getProperty("codename1.cssTheme"))) {
failActivateCSS(artifact);
}
if (!getProjectCSSDir().exists()) {
failActivateCSS(artifact);
}
File cssFile = getProjectCSSFile();
if (!cssFile.exists()) {
failActivateCSS(artifact);
}
File cssImpl = new File(project.getBuild().getDirectory() + File.separator + "css");
String baseName = artifact.getGroupId()+"__"+artifact.getArtifactId();
if (!cssImpl.exists()) {
cssImpl.mkdirs();
}
File libCssImpl = new File(cssImpl, baseName);
if (libCssImpl.exists()) {
delTree(libCssImpl);
}
libCssImpl.mkdirs();
Expand unzip = (Expand)antProject.createTask("unzip");
unzip.setSrc(cssZip);
unzip.setDest(libCssImpl);
unzip.execute();
}
}