
org.tango.pogo.gui.packaging.Packaging Maven / Gradle / Ivy
//+======================================================================
//
// Project: Tango
//
// Description: java source code for utilities
//
// $Author: verdier $
//
// Copyright (C) : 2004,2005,2006,2007,2008,2009,2009,2010,2011,2012,2013,2014
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This file is part of Tango.
//
// Tango is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Tango 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Tango. If not, see .
//
// $Revision: $
// $Date: $
//
// $HeadURL: $
//
//-======================================================================
package org.tango.pogo.gui.packaging;
import org.tango.pogo.pogoDsl.*;
import org.tango.pogo.gui.tools.ParserTool;
import org.tango.pogo.gui.tools.PogoException;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Packaging {
private List packClassList = new ArrayList<>();
private List addedClasses = new ArrayList<>();
private String packageName;
private String packageAuthor;
private String packagePath;
private String packageVersion;
private boolean multipleClasses = false;
private PackFile[] packFiles = {
new PackFile("README", MODIFY, UPDATE),
new PackFile("COPYING", NO_MODIF, NO_UPDATE),
new PackFile("NEWS", NO_MODIF, NO_UPDATE),
new PackFile("INSTALL", NO_MODIF, NO_UPDATE),
new PackFile("AUTHORS", MODIFY, NO_UPDATE),
new PackFile("ChangeLog", NO_MODIF, NO_UPDATE),
new PackFile("autogen.sh", MODIFY, UPDATE),
new PackFile("configure.ac", MODIFY, UPDATE),
new PackFile("Makefile.am", MODIFY, UPDATE),
new PackFile("src/Makefile.am", MODIFY, UPDATE),
new PackFile("m4/gcc_release.m4", NO_MODIF, NO_UPDATE),
};
private static final String[] directories = {
"", "src", "build", "m4"
};
private static final boolean NO_MODIF = false; // No modification from template
private static final boolean MODIFY = true; // Modifications from template
private static final boolean NO_UPDATE = false; // No update if already exists
private static final boolean UPDATE = true; // Updated at each code generation
static final String PackageDir = "/packaging/";
//===============================================================
/**
* Will create the packaging class for code generation
* @param deviceClass Class to create packaging.
* @throws PogoException If template files are not found.
*/
//===============================================================
public Packaging(final PogoDeviceClass deviceClass, String packageVersion, String author) throws PogoException {
this.packageVersion = packageVersion;
String className = deviceClass.getName();
String path = deviceClass.getDescription().getSourcePath();
initialize(className, path, author);
PackClass _class = new PackClass(className, path);
_class.addAdditionalFiles(deviceClass.getAdditionalFiles());
packClassList.add(_class);
manageInheritances(deviceClass.getDescription().getInheritances());
}
//===============================================================
/**
* Will create the packaging class for code generation
* @param deviceClasses Classes to create packaging.
* @throws PogoException If template files are not found.
*/
//===============================================================
public Packaging(final PogoMultiClasses deviceClasses, String packageVersion, String author) throws PogoException {
this.packageVersion = packageVersion;
String className = deviceClasses.getName();
String path = deviceClasses.getSourcePath();
initialize(className, path, author);
List simpleDefList = deviceClasses.getClasses();
for (OneClassSimpleDef _class : simpleDefList) {
PackClass packClass =new PackClass(_class.getClassname(), _class.getSourcePath());
packClass.addAdditionalFiles(_class.getAdditionalFiles());
packClassList.add(packClass);
manageInheritances(_class.getInheritances());
}
multipleClasses = true;
}
//===============================================================
//===============================================================
private void manageInheritances(List inheritances) throws PogoException {
for (Inheritance inheritance : inheritances) {
String name = inheritance.getClassname();
if (!(name.startsWith("Device") && name.endsWith("Impl")))
packClassList.add(new PackClass(name, inheritance.getSourcePath()));
}
}
//===============================================================
//===============================================================
private void initialize(final String name, final String path, final String author) throws PogoException {
packageName = name;
packagePath = path + "/packaging";
packageAuthor = author;
if (!isAvailable())
throw new PogoException("Property \'PACKAGING_HOME\' not set");
// Check if templates exist
for (PackFile packFile : packFiles) {
if (PackUtils.getInstance().fileExistsInPackage(PackageDir + packFile.name))
throw new PogoException("Template file \'" + packFile.name + "\' not found");
}
}
//===============================================================
//===============================================================
private void copyTemplates() throws PogoException {
for (PackFile packFile : packFiles) {
String targetFile = packagePath + "/" + packFile.name;
// Check if already exists
packFile.alreadyExists = new File(targetFile).exists();
if (packFile.update || !packFile.alreadyExists) {
String code = PackUtils.getInstance().readFileFromPackage(PackageDir + packFile.name);
ParserTool.writeFile(targetFile, code);
if (packFile.name.endsWith(".sh")) // must be executable
if (!new File(targetFile).setExecutable(true))
System.err.println("Cannot set executable " + targetFile);
}
}
}
//===============================================================
//===============================================================
private String addSourceReferences(String code) {
String nextLine = PackUtils.buildNextLine(packageName + "_SOURCES = ");
StringBuilder sb = new StringBuilder();
// For each class
for (PackClass packClass : packClassList) {
// Check if already done
if (addedClasses.indexOf(packClass.name)<0) {
// Add headers
for (String file : packClass.headers)
sb.append(file).append(nextLine);
// Get source files (without main and ClassFactory)
List files = packClass.sources;
for (String file : files) {
sb.append(file).append(nextLine);
}
addedClasses.add(packClass.name);
}
else
PackUtils.println(packClass.name + " has already been added!");
}
String factory = ((multipleClasses)? "MultiClassesFactory.cpp" :"ClassFactory.cpp");
sb.append(factory).append(nextLine);
sb.append("main.cpp");
code = code.replaceAll("TEMPLATE_SOURCES", sb.toString());
return code;
}
//===============================================================
//===============================================================
private void updateTemplate(String fileName) throws PogoException {
String code = ParserTool.readFile(fileName);
if (fileName.endsWith("src/Makefile.am"))
code = addSourceReferences(code);
code = code.replaceAll("TEMPLATE_AUTHOR", packageAuthor);
code = code.replaceAll("TEMPLATE_VERSION", packageVersion);
code = code.replaceAll("TEMPLATE_CLASS", packageName);
ParserTool.writeFile(fileName, code);
}
//===============================================================
//===============================================================
private void updateConfig(String fileName, List headers, List functions) throws PogoException {
String code = ParserTool.readFile(fileName);
code = code.replaceAll("TEMPLATE_CHECK_HEADERS", PackUtils.buildConfigureList(headers));
code = code.replaceAll("TEMPLATE_CHECK_FUNCS", PackUtils.buildConfigureList(functions));
ParserTool.writeFile(fileName, code);
}
//===============================================================
/**
* Create links for specified files in specified path
* @param path specified path
* @param fileName specified file
* @param srcPath specified files path
* @throws PogoException if link creation failed
*/
//===============================================================
private void createSourceLinks(final String path,
final String fileName,
final String srcPath) throws PogoException {
List list = new ArrayList<>();
list.add(fileName);
createSourceLinks(path, list, srcPath);
}
//===============================================================
/**
* Create links for specified files in specified path
* @param path specified path
* @param fileNames specified files
* @param srcPath specified files path
* @throws PogoException if link creation failed
*/
//===============================================================
private void createSourceLinks(final String path,
final List fileNames,
final String srcPath) throws PogoException {
// ToDo When 1.7 will be used --> use java.nio.file.Files.createLink()
try {
// Build a script file and execute it to create links
String scriptName = path + "/create_links";
String code = "#!/bin/sh\n\n";
code += "cd " + path + "\n\n";
for (String fileName : fileNames) {
// Delete old link if any, then create new one
code += "rm -f " + fileName + "\n";
code += "ln -s " + srcPath + "/" + fileName + " " + fileName + "\n\n";
}
//PackUtils.println(code);
ParserTool.writeFile(scriptName, code);
File script = new File(scriptName);
if (script.setExecutable(true)) {
PackUtils.println("execute " + scriptName);
try { Thread.sleep(100); } catch (InterruptedException e) { /* */ }
PackUtils.executeShellCommand(scriptName);
}
//noinspection ResultOfMethodCallIgnored
script.delete();
}
catch (Exception e) {
throw new PogoException("Cannot create link: " + e);
}
}
//===============================================================
//===============================================================
//===============================================================
/**
* Star the code generation for packaging
* @throws PogoException if code generation failed.
*/
//===============================================================
public void generate(List headers, List functions) throws PogoException {
PackUtils.buildDirectories(directories, packagePath);
copyTemplates();
for (PackFile packFile : packFiles) {
if (packFile.doUpdates()) {
updateTemplate(packagePath + "/" + packFile.name);
if (packFile.name.endsWith("configure.ac"))
updateConfig(packagePath + "/" + packFile.name, headers, functions);
}
}
if (multipleClasses) {
for (PackClass _class : packClassList) {
createSourceLinks(packagePath + "/src", _class.headers, _class.path);
createSourceLinks(packagePath + "/src", _class.getSources(), _class.path);
// !!!!
_class.manageSerialSpecialCase();
}
createSourceLinks(packagePath + "/src", "MultiClassesFactory.cpp", "../..");
}
else {
int cnt = 0;
for (PackClass _class : packClassList) {
String srcPath = (cnt++==0)? "../.." : _class.path;
createSourceLinks(packagePath + "/src", _class.headers, srcPath);
createSourceLinks(packagePath + "/src", _class.getSources(), srcPath);
// !!!!
_class.manageSerialSpecialCase();
}
createSourceLinks(packagePath + "/src", "ClassFactory.cpp", "../..");
}
createSourceLinks(packagePath + "/src", "main.cpp", "../..");
PackUtils.println("Packaging for " + packageName +
" has been created in:\n" + packagePath);
}
//===============================================================
/**
* Check if PACKAGING_HOME variable to know where template files are.
* @return true if PACKAGING_HOME has been set.
*/
//===============================================================
public static boolean isAvailable() {
return PackUtils.isAvailable();
}
//===============================================================
//===============================================================
public String getPackagePath() {
return packagePath;
}
//===============================================================
//===============================================================
public String getPackageName() {
return packageName;
}
//===============================================================
//===============================================================
//===============================================================
//===============================================================
private class PackFile{
String name;
boolean modify;
boolean update = false;
boolean alreadyExists = false;
//===========================================================
private PackFile(String name, boolean modify, boolean update) {
this.name = name;
this.modify = modify;
this.update = update;
}
//===========================================================
private boolean doUpdates() {
return (modify && !alreadyExists) || update;
}
//===========================================================
}
//===============================================================
//===============================================================
//===============================================================
//===============================================================
private class PackClass {
private String name;
private String path;
private List headers;
private List sources = new ArrayList<>();
//===========================================================
private PackClass(String name, String path) throws PogoException {
this.name = name;
this.path = path;
headers = PackUtils.getFileList(path, ".h");
sources.add(name+".cpp");
sources.add(name+"Class.cpp");
sources.add(name+"StateMachine.cpp");
String dynAttrFile = name+"DynAttrUtils.cpp";
if (new File(path+"/"+dynAttrFile).exists())
sources.add(dynAttrFile);
}
//===========================================================
private void addAdditionalFiles(List additionalFiles) {
if (additionalFiles!=null) {
for (AdditionalFile file : additionalFiles) {
sources.add(file.getName()+".cpp");
}
}
}
//===========================================================
private void manageSerialSpecialCase() {
// For class Serial:
// Due to a bad design, 2 source files are used as include files :-)
if (name.equals("Serial")) {
try {
String code = ParserTool.readFile(packagePath + "/Makefile.am");
String key = "EXTRA_DIST = ";
String badFiles = "";
for (String badFile : badSerialFiles)
badFiles += " src/" + badFile + " ";
int pos = code.indexOf(key);
if (pos>0) {
pos += key.length();
code = code.substring(0, pos) + badFiles + code.substring(pos);
ParserTool.writeFile(packagePath + "/Makefile.am", code);
}
}
catch (PogoException e) {
System.err.println(e.toString());
}
}
}
//===========================================================
private List getSources() {
List list = new ArrayList<>();
for (String file : sources)
if (!file.equals("main.cpp") && !file.equals("ClassFactory.cpp"))
list.add(file);
// For class Serial:
// Due to a bad design, 2 source files are used as include files :-)
if (name.equals("Serial")) {
Collections.addAll(list, badSerialFiles);
}
return list;
}
//===========================================================
private final String[] badSerialFiles = {"SerialLinux.cpp", "SerialWin32.cpp"};
}
//===============================================================
//===============================================================
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy