Source Code Cross Referenced for ApplicationInstaller.java in  » Database-ORM » MMBase » org » mmbase » module » tools » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » MMBase » org.mmbase.module.tools 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:        This software is OSI Certified Open Source Software.
0004:        OSI Certified is a certification mark of the Open Source Initiative.
0005:
0006:        The license (Mozilla version 1.0) can be read at the MMBase site.
0007:        See http://www.MMBase.org/license
0008:
0009:         */
0010:        package org.mmbase.module.tools;
0011:
0012:        import java.util.*;
0013:        import java.util.Map.Entry;
0014:
0015:        import org.mmbase.bridge.Field;
0016:        import org.mmbase.cache.NodeCache;
0017:        import org.mmbase.core.CoreField;
0018:        import org.mmbase.module.builders.Versions;
0019:        import org.mmbase.module.core.*;
0020:        import org.mmbase.module.corebuilders.*;
0021:        import org.mmbase.storage.search.*;
0022:        import org.mmbase.storage.search.implementation.*;
0023:        import org.mmbase.util.*;
0024:        import org.mmbase.util.logging.Logger;
0025:        import org.mmbase.util.logging.Logging;
0026:        import org.mmbase.util.xml.ApplicationReader;
0027:        import org.xml.sax.InputSource;
0028:
0029:        /**
0030:         * Application installations functionality of MMAdmin.
0031:         *
0032:         * @author Nico Klasens
0033:         * @since MMBase-1.8
0034:         * @version $Id: ApplicationInstaller.java,v 1.14 2007/10/02 12:15:14 michiel Exp $
0035:         */
0036:        class ApplicationInstaller {
0037:
0038:            private static final Logger log = Logging
0039:                    .getLoggerInstance(ApplicationInstaller.class);
0040:
0041:            private final MMBase mmb;
0042:            private final MMAdmin admin;
0043:
0044:            public ApplicationInstaller(MMBase mmb, MMAdmin admin) {
0045:                this .mmb = mmb;
0046:                this .admin = admin;
0047:            }
0048:
0049:            public void installApplications() throws SearchQueryException {
0050:                ResourceLoader applicationLoader = ResourceLoader
0051:                        .getConfigurationRoot().getChildResourceLoader(
0052:                                "applications");
0053:                for (String appResource : applicationLoader.getResourcePaths(
0054:                        ResourceLoader.XML_PATTERN, false)) {
0055:                    ApplicationResult result = new ApplicationResult();
0056:                    if (!installApplication(appResource.substring(0,
0057:                            appResource.length() - 4), -1, null, result,
0058:                            new HashSet<String>(), true)) {
0059:                        log.error("Problem installing application : "
0060:                                + appResource + ", cause: "
0061:                                + result.getMessage());
0062:                    }
0063:                }
0064:            }
0065:
0066:            /**
0067:             * Installs the application
0068:             * @param applicationName Name of the application file, without the xml extension
0069:             *                        This is also assumed to be the name of teh application itself
0070:             *                        (if not, a warning will be issued)
0071:             * @param result the result object, containing error messages when the installation fails,
0072:             * or the installnotice if succesfull or already installed
0073:             * @param installationSet set of installations that are currently being installed.
0074:             *                        used to check if there are circular dependencies
0075:             * @param autoDeploy if true, the installation is only installed if the application is set to autodeploy
0076:             * @return true if succesfull, false otherwise
0077:             */
0078:            public boolean installApplication(String applicationName,
0079:                    int requiredVersion, String requiredMaintainer,
0080:                    ApplicationResult result, Set<String> installationSet,
0081:                    boolean autoDeploy) throws SearchQueryException {
0082:
0083:                if (installationSet.contains(applicationName)) {
0084:                    return result
0085:                            .error("Circular reference to application with name "
0086:                                    + applicationName);
0087:                }
0088:
0089:                ApplicationReader reader = getApplicationReader(applicationName);
0090:                Versions ver = (Versions) mmb.getBuilder("versions");
0091:                if (reader != null) {
0092:                    // test autodeploy
0093:                    if (autoDeploy) {
0094:                        if (!reader.hasAutoDeploy()) {
0095:                            return true;
0096:                        } else {
0097:                            if (admin.getIgnoredAutodeployApplications()
0098:                                    .contains(applicationName)) {
0099:                                log
0100:                                        .info("Ignoring auto-deploy '"
0101:                                                + applicationName
0102:                                                + "' because specified as ignore-auto-deploy parameter of mmadmin");
0103:                                return true;
0104:                            }
0105:                        }
0106:                    }
0107:                    String name = reader.getName();
0108:                    String maintainer = reader.getMaintainer();
0109:                    if (requiredMaintainer != null
0110:                            && !maintainer.equals(requiredMaintainer)) {
0111:                        return result
0112:                                .error("Install error: " + name
0113:                                        + " requires maintainer '"
0114:                                        + requiredMaintainer
0115:                                        + "' but found maintainer '"
0116:                                        + maintainer + "'");
0117:                    }
0118:                    int version = reader.getVersion();
0119:                    if (requiredVersion != -1 && version != requiredVersion) {
0120:                        return result.error("Install error: " + name
0121:                                + " requires version '" + requiredVersion
0122:                                + "' but found version '" + version + "'");
0123:                    }
0124:                    int installedVersion = ver.getInstalledVersion(name,
0125:                            "application");
0126:                    if (installedVersion == -1 || version > installedVersion) {
0127:                        if (!name.equals(applicationName)) {
0128:                            result
0129:                                    .warn("Application name "
0130:                                            + name
0131:                                            + " not the same as the base filename "
0132:                                            + applicationName
0133:                                            + ".\n"
0134:                                            + "This may cause problems when referring to this application.");
0135:                        }
0136:                        // We should possibly check whether the maintainer is valid here (see sample code below).
0137:                        // There is currently no way to do this, though, unless we use awful queries.
0138:                        // what we need is a getInstalledMaintainer() method on the Versions builder
0139:                        /* sample code
0140:                        String installedMaintainer=ver.getInstalledMaintainer(name,"application");
0141:                        if (!maintainer.equals(installedAppMaintainer)) {
0142:                            return result.error("Install error: "+name+" is of maintainer '"+maintainer+"' but installed application is of maintainer '"+installedMaintainer+"'");
0143:                        }
0144:                         */
0145:                        // should be installed - add to installation set
0146:                        installationSet.add(applicationName);
0147:                        List<Map<String, String>> requires = reader
0148:                                .getRequirements();
0149:                        for (Map<String, String> reqapp : requires) {
0150:                            String reqType = reqapp.get("type");
0151:                            if (reqType == null
0152:                                    || reqType.equals("application")) {
0153:                                String appName = reqapp.get("name");
0154:                                int installedAppVersion = ver
0155:                                        .getInstalledVersion(appName,
0156:                                                "application");
0157:                                String appMaintainer = reqapp.get("maintainer");
0158:                                int appVersion = -1;
0159:                                try {
0160:                                    String appVersionAttr = reqapp
0161:                                            .get("version");
0162:                                    if (appVersionAttr != null)
0163:                                        appVersion = Integer
0164:                                                .parseInt(appVersionAttr);
0165:                                } catch (Exception e) {
0166:                                }
0167:                                if (installedAppVersion == -1
0168:                                        || appVersion > installedAppVersion) {
0169:                                    log.service("Application '"
0170:                                            + applicationName + "' requires : "
0171:                                            + appName);
0172:                                    if (!installApplication(appName,
0173:                                            appVersion, appMaintainer, result,
0174:                                            installationSet, false)) {
0175:                                        return false;
0176:                                    }
0177:                                } else if (appMaintainer != null) {
0178:                                    // we should possibly check whether the maintainer is valid here (see sample code below).
0179:                                    // There is currently no way to do this, though, unless we use awful queries.
0180:                                    // what we need is a getInstalledMaintainer() method on the Versions builder
0181:                                    /* sample code
0182:                                    String installedAppMaintainer=ver.getInstalledMaintainer(name,"application");
0183:                                    if (!appMaintainer.equals(installedAppMaintainer)) {
0184:                                        return result.error("Install error: "+name+" requires maintainer '"+appMaintainer+"' but found maintainer '"+installedAppMaintainer+"'");
0185:                                    }
0186:                                     */
0187:                                }
0188:                            }
0189:                        }
0190:                        // note: currently name and application file name should be the same
0191:                        if (installedVersion == -1) {
0192:                            log.info("Installing application : " + name);
0193:                        } else {
0194:                            log.info("installing application : " + name
0195:                                    + " new version from " + installedVersion
0196:                                    + " to " + version);
0197:                        }
0198:                        if (installBuilders(reader.getNeededBuilders(),
0199:                                "applications/" + applicationName, result)
0200:                                && installRelDefs(reader.getNeededRelDefs(),
0201:                                        result)
0202:                                && installAllowedRelations(reader
0203:                                        .getAllowedRelations(), result)
0204:                                && installDataSources(reader.getDataSources(),
0205:                                        applicationName, result)
0206:                                && installRelationSources(reader
0207:                                        .getRelationSources(), applicationName,
0208:                                        result)) {
0209:
0210:                            if (installedVersion == -1) {
0211:                                ver.setInstalledVersion(name, "application",
0212:                                        maintainer, version);
0213:                            } else {
0214:                                ver.updateInstalledVersion(name, "application",
0215:                                        maintainer, version);
0216:                            }
0217:                            log.info("Application '" + name
0218:                                    + "' deployed succesfully.");
0219:                            result
0220:                                    .success("Application loaded oke\n\n"
0221:                                            + "The application has the following install notice for you : \n\n"
0222:                                            + reader.getInstallNotice());
0223:                        }
0224:                        // installed or failed - remove from installation set
0225:                        installationSet.remove(applicationName);
0226:                    } else {
0227:                        // only return this message if the application is the main (first) application
0228:                        // and if it was not auto-deployed (as in that case messages would not be deemed very useful)
0229:                        if (installationSet.size() == 1) {
0230:                            result
0231:                                    .success("Application was allready loaded (or a higher version)\n\n"
0232:                                            + "To remind you here is the install notice for you again : \n\n"
0233:                                            + reader.getInstallNotice());
0234:                        }
0235:                    }
0236:                } else {
0237:                    result
0238:                            .error("Install error: can't find xml file: applications/"
0239:                                    + applicationName + ".xml");
0240:                }
0241:                return result.isSuccess();
0242:            }
0243:
0244:            /**
0245:             * @javadoc
0246:             * @since MMBase-1.7
0247:             */
0248:            protected boolean installDataSources(
0249:                    List<Map<String, String>> dataSources, String appName,
0250:                    ApplicationResult result) {
0251:                MMObjectBuilder syncbul = mmb.getBuilder("syncnodes");
0252:
0253:                List<MMObjectNode> nodeFieldNodes = new ArrayList<MMObjectNode>(); // a temporary list with all nodes that have NODE fields, which should be synced, later.
0254:                if (syncbul != null) {
0255:                    for (Map<String, String> bh : dataSources) {
0256:                        XMLNodeReader nodeReader = getNodeReader(bh, appName);
0257:                        if (nodeReader == null) {
0258:                            continue;
0259:                        } else {
0260:                            installDatasource(syncbul, nodeReader,
0261:                                    nodeFieldNodes, result);
0262:                        }
0263:                    }
0264:
0265:                    treatNodeFields(nodeFieldNodes, syncbul);
0266:
0267:                    return result.isSuccess();
0268:                } else {
0269:                    return result
0270:                            .error("Application installer : can't reach syncnodes builder"); //
0271:                }
0272:            }
0273:
0274:            private void installDatasource(MMObjectBuilder syncbul,
0275:                    XMLNodeReader nodeReader,
0276:                    List<MMObjectNode> nodeFieldNodes, ApplicationResult result) {
0277:                String exportsource = nodeReader.getExportSource();
0278:                int timestamp = nodeReader.getTimeStamp();
0279:
0280:                nodeReader.setLoadBinaries(false);
0281:
0282:                // loop all nodes , and add to syncnodes.
0283:                for (Iterator<MMObjectNode> n = nodeReader.getNodes(mmb)
0284:                        .iterator(); n.hasNext();) {
0285:                    try {
0286:                        MMObjectNode newNode = n.next();
0287:                        nodeReader.loadBinairyFields(newNode);
0288:
0289:                        int exportnumber = newNode.getIntValue("number");
0290:                        if (existsSyncnode(syncbul, exportsource, exportnumber)) {
0291:                            // XXX To do : we may want to load the node and check/change the fields
0292:                            log.debug("node allready installed : "
0293:                                    + exportnumber);
0294:                        } else {
0295:                            newNode.setValue("number", -1);
0296:                            int localnumber = doKeyMergeNode(syncbul, newNode,
0297:                                    exportsource, result);
0298:                            if (localnumber != -1) { // this node was not yet imported earlier
0299:                                createSyncnode(syncbul, exportsource,
0300:                                        timestamp, exportnumber, localnumber);
0301:                                if (localnumber == newNode.getNumber()) {
0302:                                    findFieldsOfTypeNode(nodeFieldNodes,
0303:                                            exportsource, newNode);
0304:                                }
0305:                            }
0306:                            NodeCache.getCache().remove(localnumber);
0307:                        }
0308:                        n.remove();
0309:                    } catch (SearchQueryException sqe) {
0310:                        log.error(sqe);
0311:                    }
0312:                }
0313:            }
0314:
0315:            private void findFieldsOfTypeNode(
0316:                    List<MMObjectNode> nodeFieldNodes, String exportsource,
0317:                    MMObjectNode newNode) {
0318:                // determine if there were NODE fields, which need special treatment later.
0319:                Collection<CoreField> fields = newNode.getBuilder().getFields();
0320:                Iterator<CoreField> i = fields.iterator();
0321:                while (i.hasNext()) {
0322:                    CoreField field = i.next();
0323:
0324:                    // Fields with type NODE and notnull=true will be handled
0325:                    // by the doKeyMergeNode() method.
0326:                    if (field.getType() == Field.TYPE_NODE
0327:                            && !field.getName().equals("number")
0328:                            && !field.isRequired()) {
0329:
0330:                        newNode.storeValue("__exportsource", exportsource);
0331:                        nodeFieldNodes.add(newNode);
0332:                        break;
0333:                    }
0334:                }
0335:            }
0336:
0337:            private void treatNodeFields(List<MMObjectNode> nodeFieldNodes,
0338:                    MMObjectBuilder syncbul) {
0339:                Iterator<MMObjectNode> i = nodeFieldNodes.iterator();
0340:                while (i.hasNext()) {
0341:                    MMObjectNode importedNode = i.next();
0342:                    String exportsource = (String) importedNode.getValues()
0343:                            .get("__exportsource");
0344:                    // clean it up
0345:                    importedNode.storeValue("__exportsource", null); // hack to remove it.
0346:
0347:                    Collection<CoreField> fields = importedNode.getBuilder()
0348:                            .getFields();
0349:                    Iterator<CoreField> j = fields.iterator();
0350:                    while (j.hasNext()) {
0351:                        CoreField def = j.next();
0352:                        String fieldName = def.getName();
0353:                        if (def.getType() == Field.TYPE_NODE
0354:                                && !fieldName.equals("number")
0355:                                && !fieldName.equals("snumber")
0356:                                && !fieldName.equals("dnumber")
0357:                                && !fieldName.equals("rnumber")) {
0358:
0359:                            updateFieldWithTypeNode(syncbul, importedNode,
0360:                                    exportsource, fieldName);
0361:                        }
0362:                    }
0363:                    if (importedNode.isChanged()) {
0364:                        importedNode.commit();
0365:                    }
0366:                }
0367:            }
0368:
0369:            /**
0370:             * @javadoc !!!
0371:             */
0372:            private int doKeyMergeNode(MMObjectBuilder syncbul,
0373:                    MMObjectNode newNode, String exportsource,
0374:                    ApplicationResult result) {
0375:                MMObjectBuilder bul = newNode.getBuilder();
0376:                if (bul != null) {
0377:                    Collection<CoreField> vec = bul.getFields();
0378:                    Constraint constraint = null;
0379:                    NodeSearchQuery query = null;
0380:                    for (CoreField def : vec) {
0381:                        // check for notnull fields with type NODE.
0382:                        if (def.getType() == Field.TYPE_NODE
0383:                                && !def.getName().equals("number")
0384:                                && !def.getName().equals("otype")
0385:                                && def.isRequired()) {
0386:
0387:                            // Dangerous territory here.
0388:                            // The node contains a reference to another node.
0389:                            // The referenced node has to exist when this node is inserted.
0390:                            // trying to update the node.
0391:                            updateFieldWithTypeNode(syncbul, newNode,
0392:                                    exportsource, def.getName());
0393:                            if (newNode.getIntValue(def.getName()) == -1) {
0394:                                // guess that failed
0395:                                result
0396:                                        .error("Insert of node "
0397:                                                + newNode
0398:                                                + " failed. Field '"
0399:                                                + def.getName()
0400:                                                + "' with type NODE is not allowed to have a null value. "
0401:                                                + "The referenced node is not found. Try to reorder the nodes so the referenced node is imported before this one.");
0402:                                return -1;
0403:                            }
0404:                        }
0405:
0406:                        // generation of key constraint to check if there is a node already present.
0407:                        // if a node is present then we can't insert this one.
0408:                        if (def.isUnique()) {
0409:                            int type = def.getType();
0410:                            String name = def.getName();
0411:                            if (type == Field.TYPE_STRING) {
0412:                                String value = newNode.getStringValue(name);
0413:                                if (query == null) {
0414:                                    query = new NodeSearchQuery(bul);
0415:                                }
0416:                                StepField field = query.getField(def);
0417:                                Constraint newConstraint = new BasicFieldValueConstraint(
0418:                                        field, value);
0419:                                if (constraint == null) {
0420:                                    constraint = newConstraint;
0421:                                } else {
0422:                                    BasicCompositeConstraint compConstraint = new BasicCompositeConstraint(
0423:                                            CompositeConstraint.LOGICAL_AND);
0424:                                    compConstraint.addChild(constraint);
0425:                                    compConstraint.addChild(newConstraint);
0426:                                    constraint = compConstraint;
0427:                                }
0428:                            }
0429:                        }
0430:                    }
0431:                    if (query != null && constraint != null) {
0432:                        query.setConstraint(constraint);
0433:                        try {
0434:                            List<MMObjectNode> nodes = bul.getNodes(query);
0435:                            if (nodes.size() > 0) {
0436:                                MMObjectNode oldNode = nodes.get(0);
0437:                                return oldNode.getIntValue("number");
0438:                            }
0439:                        } catch (SearchQueryException sqe) {
0440:                            result
0441:                                    .error("Application installer can't search builder storage ("
0442:                                            + sqe.getMessage() + ")");
0443:                            return -1;
0444:                        }
0445:                    }
0446:
0447:                    int localnumber = newNode.insert("import");
0448:                    if (localnumber == -1) {
0449:                        result.error("Insert of node " + newNode + " failed.");
0450:                    }
0451:                    return localnumber;
0452:
0453:                } else {
0454:                    result
0455:                            .error("Application installer can't find builder for : "
0456:                                    + newNode);
0457:                    return -1;
0458:                }
0459:            }
0460:
0461:            /** update the field with the real node number of the referenced node
0462:             *
0463:             * @param syncbul syncnode builder
0464:             * @param importedNode Node to update
0465:             * @param exportsource export source of the node to update
0466:             * @param fieldname name of the field
0467:             */
0468:            private void updateFieldWithTypeNode(MMObjectBuilder syncbul,
0469:                    MMObjectNode importedNode, String exportsource,
0470:                    String fieldname) {
0471:
0472:                int exportnumber;
0473:                try {
0474:                    exportnumber = Integer.parseInt((String) importedNode
0475:                            .getValues().get("__" + fieldname));
0476:                } catch (Exception e) {
0477:                    exportnumber = -1;
0478:                }
0479:
0480:                // clean it up (don't know if this is necessary, but don't risk anything!)
0481:                importedNode.storeValue("__" + fieldname, null);
0482:
0483:                int localNumber = -1;
0484:
0485:                List<MMObjectNode> syncnodes = null;
0486:                try {
0487:                    syncnodes = getSyncnodes(syncbul, exportsource,
0488:                            exportnumber);
0489:                } catch (SearchQueryException e) {
0490:                    log.warn("Search for exportnumber " + exportnumber
0491:                            + " exportsource " + exportsource + "failed", e);
0492:                }
0493:                if (syncnodes != null && !syncnodes.isEmpty()) {
0494:                    MMObjectNode n2 = syncnodes.get(0);
0495:                    localNumber = n2.getIntValue("localnumber");
0496:                }
0497:                if (localNumber != -1) { // leave it unset in that case, because foreign keys whine otherwise (so, if you have foreign keys (e.g. hsql), the field _must not_ be required).
0498:                    importedNode.setValue(fieldname, localNumber);
0499:                }
0500:            }
0501:
0502:            /**
0503:             * @javadoc
0504:             */
0505:            boolean installRelationSources(List<Map<String, String>> ds,
0506:                    String appname, ApplicationResult result) {
0507:                MMObjectBuilder syncbul = mmb.getBuilder("syncnodes");
0508:                InsRel insRel = mmb.getInsRel();
0509:                if (syncbul != null) {
0510:                    List<MMObjectNode> nodeFieldNodes = new ArrayList<MMObjectNode>(); // a temporary list with all nodes that have NODE fields, which should be synced, later.
0511:                    for (Map<String, String> bh : ds) {
0512:                        XMLRelationNodeReader nodereader = getRelationNodeReader(
0513:                                appname, bh);
0514:                        if (nodereader == null) {
0515:                            continue;
0516:                        } else {
0517:                            installRelationSource(syncbul, insRel, nodereader,
0518:                                    nodeFieldNodes, result);
0519:                        }
0520:                    }
0521:                    treatNodeFields(nodeFieldNodes, syncbul);
0522:                } else {
0523:                    result
0524:                            .error("Application installer : can't reach syncnodes builder");
0525:                }
0526:                return result.isSuccess();
0527:            }
0528:
0529:            private void installRelationSource(MMObjectBuilder syncbul,
0530:                    InsRel insRel, XMLRelationNodeReader nodereader,
0531:                    List<MMObjectNode> nodeFieldNodes, ApplicationResult result) {
0532:                String exportsource = nodereader.getExportSource();
0533:                int timestamp = nodereader.getTimeStamp();
0534:
0535:                for (Iterator<MMObjectNode> n = (nodereader.getNodes(mmb))
0536:                        .iterator(); n.hasNext();) {
0537:                    try {
0538:                        MMObjectNode newNode = n.next();
0539:                        int exportnumber = newNode.getIntValue("number");
0540:
0541:                        if (existsSyncnode(syncbul, exportsource, exportnumber)) {
0542:                            // XXX To do : we may want to load the relation node and check/change the fields
0543:                            log.debug("node allready installed : "
0544:                                    + exportnumber);
0545:                        } else {
0546:                            newNode.setValue("number", -1);
0547:                            // The following code determines the 'actual' (synced) numbers for the destination and source nodes
0548:                            // This will normally work well, however:
0549:                            // It is _theoretically_ possible that one or both nodes are _themselves_ relation nodes.
0550:                            // (since relations are nodes).
0551:                            // Due to the order in which syncing takles place, it is possible that such structures will fail
0552:                            // to get imported.
0553:                            // ye be warned.
0554:
0555:                            // find snumber
0556:                            int snumber = newNode.getIntValue("snumber");
0557:                            List<MMObjectNode> snumberNodes = getSyncnodes(
0558:                                    syncbul, exportsource, snumber);
0559:                            if (!snumberNodes.isEmpty()) {
0560:                                MMObjectNode n2 = snumberNodes.get(0);
0561:                                snumber = n2.getIntValue("localnumber");
0562:                            } else {
0563:                                snumber = -1;
0564:                            }
0565:                            newNode.setValue("snumber", snumber);
0566:
0567:                            // find dnumber
0568:                            int dnumber = newNode.getIntValue("dnumber");
0569:                            List<MMObjectNode> dnumberNodes = getSyncnodes(
0570:                                    syncbul, exportsource, dnumber);
0571:                            if (!dnumberNodes.isEmpty()) {
0572:                                MMObjectNode n2 = dnumberNodes.get(0);
0573:                                dnumber = n2.getIntValue("localnumber");
0574:                            } else {
0575:                                dnumber = -1;
0576:                            }
0577:                            newNode.setValue("dnumber", dnumber);
0578:
0579:                            int localnumber = -1;
0580:                            if (snumber != -1 && dnumber != -1) {
0581:                                // test whether a relation with the proposed snumber/dnumber/rnumber already exists
0582:                                // if so, skip this relation when the same
0583:                                if (relationAlreadyExists(insRel, newNode,
0584:                                        snumber, dnumber)) {
0585:                                    log
0586:                                            .warn("Application tries to add relation which already exists. "
0587:                                                    + "Skipping relation with exportnumber "
0588:                                                    + exportnumber);
0589:                                } else {
0590:                                    localnumber = newNode.insert("import");
0591:                                    if (localnumber != -1) {
0592:                                        createSyncnode(syncbul, exportsource,
0593:                                                timestamp, exportnumber,
0594:                                                localnumber);
0595:                                        if (localnumber == newNode.getNumber()) {
0596:                                            findFieldsOfTypeNode(
0597:                                                    nodeFieldNodes,
0598:                                                    exportsource, newNode);
0599:                                        }
0600:                                    }
0601:                                }
0602:                            } else {
0603:                                result
0604:                                        .error("Cannot sync relation (exportnumber=="
0605:                                                + exportnumber
0606:                                                + ", snumber:"
0607:                                                + snumber
0608:                                                + ", dnumber:"
0609:                                                + dnumber + ")");
0610:                            }
0611:                        }
0612:                    } catch (SearchQueryException sqe) {
0613:                        log.error(sqe);
0614:                    }
0615:                }
0616:            }
0617:
0618:            private boolean existsSyncnode(MMObjectBuilder syncbul,
0619:                    String exportsource, int exportnumber)
0620:                    throws SearchQueryException {
0621:                List<MMObjectNode> nodes = getSyncnodes(syncbul, exportsource,
0622:                        exportnumber);
0623:                return !nodes.isEmpty();
0624:            }
0625:
0626:            private List<MMObjectNode> getSyncnodes(MMObjectBuilder syncbul,
0627:                    String exportsource, int exportnumber)
0628:                    throws SearchQueryException {
0629:                NodeSearchQuery existQuery = new NodeSearchQuery(syncbul);
0630:                BasicFieldValueConstraint constraint1 = new BasicFieldValueConstraint(
0631:                        existQuery.getField(syncbul.getField("exportnumber")),
0632:                        exportnumber);
0633:                BasicFieldValueConstraint constraint2 = new BasicFieldValueConstraint(
0634:                        existQuery.getField(syncbul.getField("exportsource")),
0635:                        exportsource);
0636:                BasicCompositeConstraint constraint = new BasicCompositeConstraint(
0637:                        CompositeConstraint.LOGICAL_AND);
0638:                constraint.addChild(constraint1);
0639:                constraint.addChild(constraint2);
0640:                existQuery.setConstraint(constraint);
0641:                List<MMObjectNode> nodes = syncbul.getNodes(existQuery);
0642:                if (nodes == null) {
0643:                    // could this happen?
0644:                    nodes = new ArrayList<MMObjectNode>();
0645:                }
0646:                return nodes;
0647:            }
0648:
0649:            private void createSyncnode(MMObjectBuilder syncbul,
0650:                    String exportsource, int timestamp, int exportnumber,
0651:                    int localnumber) {
0652:                MMObjectNode syncnode = syncbul.getNewNode("import");
0653:                syncnode.setValue("exportsource", exportsource);
0654:                syncnode.setValue("exportnumber", exportnumber);
0655:                syncnode.setValue("timestamp", timestamp);
0656:                syncnode.setValue("localnumber", localnumber);
0657:                syncnode.insert("import");
0658:            }
0659:
0660:            /**
0661:             * This method uses the {@link ResourceLoader} to fetch an application by name. for this purpose
0662:             * it requests the resource by adding <code>applications/</code> to the start of the appName and appends <code>.xml</core> to the end
0663:             * @param appName the name of the application to be read.
0664:             * @return the ApplicationReader for the application, or null is the application wat not found or an exception occured. In the later a message is logged
0665:             */
0666:            private ApplicationReader getApplicationReader(String appName) {
0667:                String resourceName = appName + ".xml";
0668:                try {
0669:                    ResourceLoader applicationLoader = ResourceLoader
0670:                            .getConfigurationRoot().getChildResourceLoader(
0671:                                    "applications");
0672:                    InputSource is = applicationLoader
0673:                            .getInputSource(resourceName);
0674:                    if (is == null) {
0675:                        return null;
0676:                    }
0677:                    return new ApplicationReader(is);
0678:                } catch (Exception e) {
0679:                    log.error("error while reading application from resource "
0680:                            + resourceName + " : " + e.getMessage(), e);
0681:                    return null;
0682:                }
0683:            }
0684:
0685:            private XMLNodeReader getNodeReader(Map<String, String> bh,
0686:                    String appName) {
0687:                XMLNodeReader nodeReader = null;
0688:
0689:                String path = bh.get("path");
0690:                ResourceLoader applicationLoader = ResourceLoader
0691:                        .getConfigurationRoot().getChildResourceLoader(
0692:                                "applications");
0693:                InputSource is = null;
0694:                try {
0695:                    is = applicationLoader.getInputSource(path);
0696:                } catch (Exception e) {
0697:                    log.info("No datasource resource " + path);
0698:                }
0699:                if (is != null) {
0700:                    nodeReader = new XMLNodeReader(is, applicationLoader
0701:                            .getChildResourceLoader(appName));
0702:                }
0703:                return nodeReader;
0704:            }
0705:
0706:            private XMLRelationNodeReader getRelationNodeReader(String appname,
0707:                    Map<String, String> bh) {
0708:                XMLRelationNodeReader nodereader = null;
0709:
0710:                String path = bh.get("path");
0711:                ResourceLoader applicationLoader = ResourceLoader
0712:                        .getConfigurationRoot().getChildResourceLoader(
0713:                                "applications");
0714:                InputSource is = null;
0715:                try {
0716:                    is = applicationLoader.getInputSource(path);
0717:                } catch (Exception e) {
0718:                    log.info("No relationsource resource " + path);
0719:                }
0720:                if (is != null) {
0721:                    nodereader = new XMLRelationNodeReader(is,
0722:                            applicationLoader.getChildResourceLoader(appname));
0723:                }
0724:                return nodereader;
0725:            }
0726:
0727:            private boolean relationAlreadyExists(InsRel insRel,
0728:                    MMObjectNode newNode, int snumber, int dnumber) {
0729:                boolean relationAlreadyExists = false;
0730:                MMObjectNode testNode = insRel.getRelation(snumber, dnumber,
0731:                        newNode.getIntValue("rnumber"));
0732:                if (testNode != null) {
0733:                    relationAlreadyExists = true;
0734:                    Map<String, Object> values = newNode.getValues();
0735:                    for (Entry<String, Object> entry : values.entrySet()) {
0736:                        String newFieldName = entry.getKey();
0737:                        if (!insRel.hasField(newFieldName)) {
0738:                            Object newValue = entry.getValue();
0739:                            Object testValue = testNode.getValue(newFieldName);
0740:                            if (!newValue.equals(testValue)) {
0741:                                relationAlreadyExists = false;
0742:                            }
0743:                        }
0744:                    }
0745:                }
0746:                return relationAlreadyExists;
0747:            }
0748:
0749:            /**
0750:             * Checks and if required installs needed relation definitions.
0751:             * Retrieves, for each reldef entry, the attributes, and passes these on to {@link #installRelDef}
0752:             * @param reldefs a list of hashtables. Each hashtable represents a reldef entry, and contains a list of name-value
0753:             *      pairs (the reldef attributes).
0754:             * @return Always <code>true</code> (?)
0755:             */
0756:            private boolean installRelDefs(List<Map<String, String>> reldefs,
0757:                    ApplicationResult result) {
0758:                for (Map<String, String> bh : reldefs) {
0759:                    String source = bh.get("source");
0760:                    String target = bh.get("target");
0761:                    String direction = bh.get("direction");
0762:                    String guisourcename = bh.get("guisourcename");
0763:                    String guitargetname = bh.get("guitargetname");
0764:                    // retrieve builder info
0765:                    int builder = -1;
0766:                    if (RelDef.usesbuilder) {
0767:                        String buildername = bh.get("builder");
0768:                        // if no 'builder' attribute is present (old format), use source name as builder name
0769:                        if (buildername == null) {
0770:                            buildername = bh.get("source");
0771:                        }
0772:                        builder = mmb.getTypeDef().getIntValue(buildername);
0773:                    }
0774:                    // is not explicitly set to unidirectional, direction is assumed to be bidirectional
0775:                    if ("unidirectional".equals(direction)) {
0776:                        if (!installRelDef(source, target, 1, guisourcename,
0777:                                guitargetname, builder, result))
0778:                            return false;
0779:                    } else {
0780:                        if (!installRelDef(source, target, 2, guisourcename,
0781:                                guitargetname, builder, result))
0782:                            return false;
0783:                    }
0784:                }
0785:                return true;
0786:            }
0787:
0788:            /**
0789:             * Checks and if required installs needed allowed type relations.
0790:             * Retrieves, for each allowed relation entry, the attributes, and passes these on to {@link #installTypeRel}
0791:             * @param relations a list of hashtables. Each hashtable represents a allowedrelation entry, and contains a list of name-value
0792:             *      pairs (the allowed relation attributes).
0793:             * @return <code>true</code> if succesfull, <code>false</code> if an error occurred
0794:             */
0795:            private boolean installAllowedRelations(
0796:                    List<Map<String, String>> relations,
0797:                    ApplicationResult result) {
0798:                for (Map<String, String> bh : relations) {
0799:                    String from = bh.get("from");
0800:                    String to = bh.get("to");
0801:                    String type = bh.get("type");
0802:                    if (!installTypeRel(from, to, type, -1, result)) {
0803:                        return false;
0804:                    }
0805:                }
0806:                return true;
0807:            }
0808:
0809:            /**
0810:             * Lists the required builders for this application, and makes attempts to install any builders that are
0811:             * not present.
0812:             * If there is a failure, the function returns false.
0813:             * Failure messages are stored in the lastmsg member.
0814:             * @param neededbuilders a list with builder data that need be installed on teh system for this application to work
0815:             *                       each element in teh list is a Map containing builder properties (in particular, 'name').
0816:             * @param applicationRoot the rootpath where the application's configuration files are located
0817:             * @return true if the builders were succesfully installed, false if the installation failed
0818:             */
0819:            private boolean installBuilders(
0820:                    List<Map<String, String>> neededbuilders,
0821:                    String applicationRoot, ApplicationResult result) {
0822:                for (Map<String, String> builderdata : neededbuilders) {
0823:                    String name = builderdata.get("name");
0824:                    MMObjectBuilder bul = mmb.getBuilder(name);
0825:                    // if builder not loaded
0826:                    if (bul == null) {
0827:                        // if 'inactive' in the config/builder path, fail
0828:                        String path = mmb.getBuilderPath(name, "");
0829:                        if (path != null) {
0830:                            result
0831:                                    .error("The builder '"
0832:                                            + name
0833:                                            + "' was already on our system, but inactive."
0834:                                            + "To install this application, make the builder '"
0835:                                            + path + name + ".xml ' active");
0836:                            continue;
0837:                        }
0838:                        ResourceLoader appLoader = ResourceLoader
0839:                                .getConfigurationRoot().getChildResourceLoader(
0840:                                        ResourceLoader
0841:                                                .getDirectory(applicationRoot));
0842:                        ResourceLoader this AppLoader = appLoader
0843:                                .getChildResourceLoader(ResourceLoader
0844:                                        .getName(applicationRoot));
0845:                        ResourceLoader builderLoader = this AppLoader
0846:                                .getChildResourceLoader("builders");
0847:
0848:                        // attempt to open the builder file.
0849:                        org.w3c.dom.Document config;
0850:                        try {
0851:                            config = builderLoader.getDocument(name + ".xml");
0852:                        } catch (org.xml.sax.SAXException se) {
0853:                            String msg = "builder '" + name + "':\n"
0854:                                    + se.toString();
0855:                            log.error(msg, se);
0856:                            result.error("A XML parsing error occurred ("
0857:                                    + se.toString()
0858:                                    + "). Check the log for details.");
0859:                            continue;
0860:                        } catch (java.io.IOException ioe) {
0861:                            String msg = "builder '" + name + "':\n"
0862:                                    + ioe.toString();
0863:                            log.error(msg, ioe);
0864:                            result.error("A file I/O error occurred ("
0865:                                    + ioe.toString()
0866:                                    + "). Check the log for details.");
0867:                            continue;
0868:                        } catch (Throwable t) {
0869:                            String msg = "builder '" + name + "': "
0870:                                    + t.getMessage();
0871:                            log.error(msg, t);
0872:                            result.error("An error occured " + t.getClass()
0873:                                    + " " + msg);
0874:                            continue;
0875:                        }
0876:
0877:                        if (config == null) {
0878:                            result.error("Could not find the builderfile :  '"
0879:                                    + builderLoader.getResource(name + ".xml")
0880:                                    + "' (builder '" + name + "')");
0881:                            continue;
0882:                        }
0883:
0884:                        // check the presence of typedef (if not present, fail)
0885:                        MMObjectBuilder typeDef = mmb.getTypeDef();
0886:                        if (typeDef == null) {
0887:                            return result
0888:                                    .error("Could not find the typedef builder.");
0889:                        }
0890:                        try {
0891:                            // try to add a node to typedef, same as adding a builder...
0892:                            MMObjectNode typeNode = typeDef
0893:                                    .getNewNode("system");
0894:                            // fill the name....
0895:                            typeNode.setValue("name", name);
0896:                            typeNode.setValue("config", config);
0897:                            // insert into mmbase
0898:                            typeNode.insert("system");
0899:                        } catch (Exception e) {
0900:                            result.error(e.getMessage());
0901:                            continue;
0902:                        }
0903:                        // we now made the builder active.. look for other builders...
0904:                    }
0905:                }
0906:                return result.isSuccess();
0907:            }
0908:
0909:            /**
0910:             * Checks whether a given relation definition exists, and if not, creates that definition.
0911:             * @param sname source name of the relation definition
0912:             * @param dname destination name of the relation definition
0913:             * @param dir directionality (uni or bi)
0914:             * @param sguiname source GUI name of the relation definition
0915:             * @param dguiname destination GUI name of the relation definition
0916:             * @param builder references the builder to use (only in new format)
0917:             * @return <code>true</code> if succesfull, <code>false</code> if an error occurred
0918:             */
0919:            private boolean installRelDef(String sname, String dname, int dir,
0920:                    String sguiname, String dguiname, int builder,
0921:                    ApplicationResult result) {
0922:
0923:                RelDef reldef = mmb.getRelDef();
0924:                if (reldef != null) {
0925:                    if (reldef.getNumberByName(sname + "/" + dname) == -1) {
0926:                        MMObjectNode node = reldef.getNewNode("system");
0927:                        node.setValue("sname", sname);
0928:                        node.setValue("dname", dname);
0929:                        node.setValue("dir", dir);
0930:                        node.setValue("sguiname", sguiname);
0931:                        node.setValue("dguiname", dguiname);
0932:                        if (RelDef.usesbuilder) {
0933:                            // if builder is unknown (falsely specified), use the InsRel builder
0934:                            if (builder <= 0) {
0935:                                builder = mmb.getInsRel().getNumber();
0936:                            }
0937:                            node.setValue("builder", builder);
0938:                        }
0939:                        int id = reldef.insert("system", node);
0940:                        if (id != -1) {
0941:                            log.debug("RefDef (" + sname + "," + dname
0942:                                    + ") installed");
0943:                        } else {
0944:                            return result.error("RelDef (" + sname + ","
0945:                                    + dname + ") could not be installed");
0946:                        }
0947:                    }
0948:                } else {
0949:                    return result.error("Can't get reldef builder");
0950:                }
0951:                return true;
0952:            }
0953:
0954:            /**
0955:             * Checks and if required installs an allowed type relation (typerel object).
0956:             * @param sname source type name of the type relation
0957:             * @param dname destination type name of the type relation
0958:             * @param rname role name of the type relation
0959:             * @param count cardinality of the type relation
0960:             * @return <code>true</code> if succesfull, <code>false</code> if an error occurred
0961:             */
0962:            private boolean installTypeRel(String sname, String dname,
0963:                    String rname, int count, ApplicationResult result) {
0964:                TypeRel typerel = mmb.getTypeRel();
0965:                if (typerel != null) {
0966:                    TypeDef typedef = mmb.getTypeDef();
0967:                    if (typedef == null) {
0968:                        return result.error("Can't get typedef builder");
0969:                    }
0970:                    RelDef reldef = mmb.getRelDef();
0971:                    if (reldef == null) {
0972:                        return result.error("Can't get reldef builder");
0973:                    }
0974:
0975:                    // figure out rnumber
0976:                    int rnumber = reldef.getNumberByName(rname);
0977:                    if (rnumber == -1) {
0978:                        return result.error("No reldef with role '" + rname
0979:                                + "' defined");
0980:                    }
0981:
0982:                    // figure out snumber
0983:                    int snumber = typedef.getIntValue(sname);
0984:                    if (snumber == -1) {
0985:                        return result.error("No builder with name '" + sname
0986:                                + "' defined");
0987:                    }
0988:
0989:                    // figure out dnumber
0990:                    int dnumber = typedef.getIntValue(dname);
0991:                    if (dnumber == -1) {
0992:                        return result.error("No builder with name '" + dname
0993:                                + "' defined");
0994:                    }
0995:
0996:                    if (!typerel.contains(snumber, dnumber, rnumber,
0997:                            TypeRel.STRICT)) {
0998:                        MMObjectNode node = typerel.getNewNode("system");
0999:                        node.setValue("snumber", snumber);
1000:                        node.setValue("dnumber", dnumber);
1001:                        node.setValue("rnumber", rnumber);
1002:                        node.setValue("max", count);
1003:                        int id = typerel.insert("system", node);
1004:                        if (id != -1) {
1005:                            log.debug("TypeRel (" + sname + "," + dname + ","
1006:                                    + rname + ") installed");
1007:                        } else {
1008:                            return result.error("TypeRel (" + sname + ","
1009:                                    + dname + "," + rname
1010:                                    + ") could not be installed");
1011:                        }
1012:                    }
1013:                    return true;
1014:                } else {
1015:                    return result.error("Can't get typerel builder");
1016:                }
1017:            }
1018:
1019:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.