Hack date: 13/3/2003
Design: A new tag is added to the application dtd. This tag
(requirements) contains child tags (requires) which describe the applications on which the current application depends.
You can obtain the list of applications using ApplicationReader.java, using a new method getRequirments. The private MMAdmin method
installApplication now checks for this list. I migrated all
application-instantiating code to this method, and maintain a set of
applications that are being 'installed' to catch circular references.
Also added code so Applicationwriter writes the new attribute;
Functionality:
You can list applications required for the current application by adding the <requiremnts> and <requires> tags in the application xml file.
As follows:
<application name="MyApp" maintainer="mmbase.org" version="1" auto-deploy="true">
<requirements>
<requires name="Basic" />
<requires name="Resources" />
</requirements>
...
The listed applications are then installed prior to installation of the current application. If the applications have in turn other required applications, these are installed too. Circular references are not allowed. Auto-deploy settings are only checked on the initial application.
Installation: not applicable Working example: appropriated changes will be made in MyNews.xml Code: MMAdmin.java: changed: private installApplication(String applicationname, applicationResult result,Set installationSet, boolean autoDeploy) changed the calls to this private method
ApplicationReader.java: added: public List getRequirements()
ApplicationWriter.java: changed: writeXMLFile(XMLApplicationReader app, String targetpath, String goal, MMBase mmb) added: static String getRequirements(XMLApplicationReader app)
XMLEntityResolver: changed to add new applications public id and dtd
application_1_1.dtd : based on application_1_0.dtd added: requirements/requires tags
START OF CALL: Thursday 13 march 2003
END OF CALL: Tuesday 18 march 2003
[_] +1 (YEA)
[_] +0 (ABSTAIN )
[_] -1 (NAY), because :
[_] VETO, because:
-- Pierre van Rooden Mediapark, C 107 tel. +31 (0)35 6772815 "Never summon anything bigger than your head."
<!--
application.dtd
- DTD for MMBase builder definitions
-->
<!ELEMENT application (requirements?,neededbuilderlist,neededreldeflist,allowedrelationlist,datasourcelist,relationsourcelist,contextsourcelist,description?,install-notice?)>
<!ATTLIST application name CDATA #REQUIRED>
<!ATTLIST application maintainer CDATA #IMPLIED>
<!ATTLIST application version CDATA #IMPLIED>
<!ATTLIST application auto-deploy CDATA #IMPLIED><!ELEMENT requirements (requires*)> <!ELEMENT requires (#PCDATA)> <!ATTLIST requires name CDATA #REQUIRED> <!ELEMENT neededbuilderlist (builder*)> <!ELEMENT builder (#PCDATA)> <!ATTLIST builder maintainer CDATA #IMPLIED> <!ATTLIST builder version CDATA #IMPLIED> <!ELEMENT neededreldeflist (reldef*)> <!ELEMENT reldef EMPTY> <!ATTLIST reldef source CDATA #REQUIRED> <!ATTLIST reldef target CDATA #REQUIRED> <!ATTLIST reldef direction CDATA #IMPLIED> <!ATTLIST reldef guisourcename CDATA #IMPLIED> <!ATTLIST reldef guitargetname CDATA #IMPLIED> <!ATTLIST reldef builder CDATA #IMPLIED> <!ELEMENT allowedrelationlist (relation*)> <!ELEMENT relation EMPTY> <!ATTLIST relation from CDATA #REQUIRED> <!ATTLIST relation to CDATA #REQUIRED> <!ATTLIST relation type CDATA #REQUIRED> <!ELEMENT datasourcelist (datasource*)> <!ELEMENT datasource EMPTY> <!ATTLIST datasource path CDATA #REQUIRED> <!ATTLIST datasource builder CDATA #REQUIRED> <!ELEMENT relationsourcelist (relationsource*)> <!ELEMENT relationsource EMPTY> <!ATTLIST relationsource path CDATA #REQUIRED> <!ATTLIST relationsource builder CDATA #REQUIRED> <!ELEMENT contextsourcelist (contextsource*)> <!ELEMENT contextsource EMPTY> <!ATTLIST contextsource path CDATA #REQUIRED> <!ATTLIST contextsource type CDATA #REQUIRED> <!ATTLIST contextsource goal CDATA #REQUIRED> <!ELEMENT description (#PCDATA)> <!ELEMENT install-notice (#PCDATA)>
? appdiff.txt
? util/resources/application_1_1.dtd
Index: module/tools/MMAdmin.java
===================================================================
RCS file: /usr/local/cvs/src/org/mmbase/module/tools/MMAdmin.java,v
retrieving revision 1.59
diff -b -r1.59 MMAdmin.java
204d203
< Versions ver=(Versions)mmb.getMMObject("versions");
206,237c205
< String
path=MMBaseContext.getConfigPath()+File.separator+"applications"+File.separator;
< XMLApplicationReader app=new
XMLApplicationReader(path+appname+".xml");
< if (app!=null) {
< String name=app.getApplicationName();
< String maintainer=app.getApplicationMaintainer();
< int version=app.getApplicationVersion();
< int installedversion=ver.getInstalledVersion(name,"application");
< if (installedversion==-1 || version>installedversion) {
< if (installedversion==-1) {
< log.info("Installing application : "+name);
< } else {
< log.info("installing application : "+name+" new version
from "+installedversion+" to "+version);
< }
< if (installApplication(name,result)) {
< result.success("Application loaded oke\n\n"+
< "The application has the following
install notice for you : \n\n"+
< app.getInstallNotice());
< if (installedversion==-1) {
<
ver.setInstalledVersion(name,"application",maintainer,version);
< } else {
<
ver.updateInstalledVersion(name,"application",maintainer,version);
< }
< }
< } else {
< result.success("Application was allready loaded (or a higher
version)\n\n"+
< "To remind you here is the install notice for
you again : \n\n"+
< app.getInstallNotice());
< }
< } else {
< result.error("Install error: can't find xml file:
"+path+appname+".xml");
< }
< if (result.isSuccess()) {
---
> if (installApplication(appname,result,new HashSet(),false)) {
549c517
< lastmsg="Server Reset requested by '"+user+"' Restart in 3
seconds<BR><BR>\n";
---
> lastmsg="Server Reset requested by '"+user+"' Restart in 3 seconds<br /><br
> />\n";
567,568c535,536
< lastmsg="Started a instance of the MMAppTool with path : <BR><BR>\n";
< lastmsg+=path+File.separator+appname+".xml<BR><BR>\n";
---
> lastmsg="Started a instance of the MMAppTool with path : <br /><br />\n";
> lastmsg+=path+File.separator+appname+".xml<br /><br />\n";
573,575c541,556
< * @javadoc
< */
< private boolean installApplication(String applicationname, ApplicationResult
result) {
---
> * Installs the application
> * @param applicationname Name of the application file, without the xml extension
> * This is also assumed to be the name of teh application
> itself
> * (if not, a warning will be issued)
> * @param result the result object, containing error messages when the
> installation fails,
> or the installnotice if succesfull or already installed
> * @param installationSet set of installations that are currently being
> installed.
> * used to check if there are circular dependencies
> * @param autoDeploy if true, the installation is only installed if the
> application is set to autodeploy
> * @return true if succesfull, false otherwise
> */
> private boolean installApplication(String applicationname, ApplicationResult
> result,
> Set installationSet, boolean autoDeploy) {
> if (installationSet.contains(applicationname)) {
> return result.error("Circular reference to application with name
> "+applicationname);
> }
577a559
> Versions ver=(Versions)mmb.getMMObject("versions");
579,584c561,580
< if (installBuilders(app.getNeededBuilders(), path +
applicationname,result)) {
< if (installRelDefs(app.getNeededRelDefs(),result)) {
< if (installAllowedRelations(app.getAllowedRelations(),result)) {
< if (installDataSources(app.getDataSources(),applicationname,
result)) {
< if (!installRelationSources(app.getRelationSources(),
result)) {
< result.error("Application installer stopped : can't
install relationsources");
---
> // test autodeploy
> if (autoDeploy && !app.getApplicationAutoDeploy()) {
> return true;
> }
> // should be installed - add to installation set
> installationSet.add(applicationname);
> List requires=app.getRequirements();
> for (Iterator i=requires.iterator(); i.hasNext();) {
> Map reqapp= (Map)i.next();
> String appname= (String)reqapp.get("name");
> log.service("Application '"+applicationname+"' requires : "+appname);
> if (!installApplication(appname,result,installationSet,false)) {
> return false;
> }
> }
> // note: currently name and application file name should be the same
> String name=app.getApplicationName();
> if(!name.equals(applicationname)) {
> result.warn("Application name "+name+" not the same as the base
> filename "+applicationname+".\n"+
> "This may cause problems when referring to this
> application.");
585a582,589
> String maintainer=app.getApplicationMaintainer();
> int version=app.getApplicationVersion();
> int installedversion=ver.getInstalledVersion(name,"application");
> if (installedversion==-1 || version>installedversion) {
> if (installedversion==-1) {
> log.info("Installing application : "+name);
> } else {
> log.info("installing application : "+name+" new version from
> "+installedversion+" to "+version);
586a591,599
> if (installBuilders(app.getNeededBuilders(), path +
> applicationname,result) &&
> installRelDefs(app.getNeededRelDefs(),result) &&
> installAllowedRelations(app.getAllowedRelations(),result) &&
> installDataSources(app.getDataSources(),applicationname, result)
> &&
> installRelationSources(app.getRelationSources(), result)) {
> if (installedversion==-1) {
>
> ver.setInstalledVersion(name,"application",maintainer,version);
> } else {
>
> ver.updateInstalledVersion(name,"application",maintainer,version);
587a601,614
> log.info("Application '"+name+"' deployed succesfully.");
> result.success("Application loaded oke\n\n"+
> "The application has the following install notice
> for you : \n\n"+
> app.getInstallNotice());
> }
> // installed or failed - remove from installation set
> installationSet.remove(applicationname);
> } else {
> // only return this message if the application is the main (first)
> application
> // and if it was not auto-deployed (as in that case messages would
> not be deemed very useful)
> if (installationSet.size()==1) {
> result.success("Application was allready loaded (or a higher
> version)\n\n"+
> "To remind you here is the install notice for you
> again : \n\n"+
> app.getInstallNotice());
591c618
< result.error("Can't install application : "+path+applicationname+".xml");
---
> result.error("Install error: can't find xml file:
> "+path+applicationname+".xml");
640d666
< log.info(importnode.toString());
1073,1084d1098
< XMLApplicationReader app=new XMLApplicationReader(path+aname);
< if (app!=null && app.getApplicationAutoDeploy()) {
< String name=app.getApplicationName();
< String maintainer=app.getApplicationMaintainer();
< int version=app.getApplicationVersion();
< int
installedversion=ver.getInstalledVersion(name,"application");
< if (installedversion==-1 || version>installedversion) {
< if (installedversion==-1) {
< log.info("Auto deploy application : "+aname+"
started");
< } else {
< log.info("Auto deploy application : "+aname+" new
version from "+installedversion+" to "+version);
< }
1086,1097c1100,1101
< if
(installApplication(aname.substring(0,aname.length()-4),result)) {
< if (installedversion==-1) {
<
ver.setInstalledVersion(name,"application",maintainer,version);
< } else {
<
ver.updateInstalledVersion(name,"application",maintainer,version);
< }
< log.info("Auto deploy application : "+aname+" done");
< } else {
< log.error("Problem installing application : "+name);
< }
< }
<
---
> if
> (!installApplication(aname.substring(0,aname.length()-4),result,new HashSet(),true))
> {
> log.error("Problem installing application : "+aname);
1115,1116c1119,1120
< lastmsg="Application saved oke<BR><BR>\n";
< lastmsg+="Some statistics on the save : <BR><BR>\n";
---
> lastmsg="Application saved oke<br /><br />\n";
> lastmsg+="Some statistics on the save : <br /><br />\n";
1119c1123
< lastmsg+=result+"<BR><BR>\n";
---
> lastmsg+=result+"<br /><br />\n";
1916c1920,1921
< resultMessage += "\n"+message;
---
> if (!resultMessage.equals("")) resultMessage += "\n";
> resultMessage += message;
1923c1928,1929
< resultMessage += "\n"+message;
---
> if (!resultMessage.equals("")) resultMessage += "\n";
> resultMessage += message;
1929c1935,1936
< resultMessage += "\n"+message;
---
> if (!resultMessage.equals("")) resultMessage += "\n";
> resultMessage += message;
Index: util/XMLApplicationReader.java
===================================================================
RCS file: /usr/local/cvs/src/org/mmbase/util/XMLApplicationReader.java,v
retrieving revision 1.16
diff -b -r1.16 XMLApplicationReader.java
72a73,87
> /**
> * Get the applicationlist required by this application
> */
> public List getRequirements() {
> List results=new Vector();
> for(Enumeration ns=getChildElements("application.requirements","requires");
> ns.hasMoreElements(); ) {
> Element n3=(Element)ns.nextElement();
> Map bset=new HashMap();
> bset.put("name",getElementAttributeValue(n3,"name"));
> results.add(bset);
> }
> return results;
> }
>
Index: util/XMLApplicationWriter.java
===================================================================
RCS file: /usr/local/cvs/src/org/mmbase/util/XMLApplicationWriter.java,v
retrieving revision 1.20
diff -b -r1.20 XMLApplicationWriter.java
15,17c15
< import java.util.Enumeration;
< import java.util.Hashtable;
< import java.util.Vector;
---
> import java.util.*;
44,47c42,45
< String name =app.getApplicationName();
< String maintainer =app.getApplicationMaintainer();
< int version =app.getApplicationVersion();
< boolean deploy =app.getApplicationAutoDeploy();
---
> String name = app.getApplicationName();
> String maintainer = app.getApplicationMaintainer();
> int version = app.getApplicationVersion();
> boolean deploy = app.getApplicationAutoDeploy();
52c50,56
< "<application name=\""+name+"\" maintainer=\""+maintainer+"\"
version=\""+version+"\" auto-deploy=\""+deploy+"\">\n";
---
> "<application name=\"" + name +
> "\" maintainer=\"" + maintainer +
> "\" version=\"" + version +
> "\" auto-deploy=\"" + deploy + "\">\n";
>
> // write the needed builders
> body+=getRequirements(app);
94c98,110
< return(resultmsgs);
---
> return resultmsgs;
> }
>
> static String getRequirements(XMLApplicationReader app) {
> String body="\t<requirements>\n";
> List apps=app.getRequirements();
> for (Iterator i=apps.iterator();i.hasNext();) {
> Map bset=(Map)i.next();
> String name=(String)bset.get("name");
> body+="\t\t<requires name=\""+name+"\" />\n";
> }
> body+="\t</requirements>\n\n";
> return body;
110d125
<
Index: util/XMLEntityResolver.java
===================================================================
RCS file: /usr/local/cvs/src/org/mmbase/util/XMLEntityResolver.java,v
retrieving revision 1.24
diff -b -r1.24 XMLEntityResolver.java
76a77
> publicIDtoResource.put("-//MMBase/DTD application config 1.1//EN", new
> Resource(XMLApplicationReader.class, "application_1_1.dtd"));
79,80d79
<
<
