001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: /*
042: * ProjectGroup.java
043: *
044: * Created on May 14, 2002, 9:34 AM
045: */
046:
047: package org.netbeans.xtest.pes.xmlbeans;
048:
049: import org.netbeans.xtest.pe.xmlbeans.*;
050: import org.netbeans.xtest.pes.XSLTransformers;
051: import org.netbeans.xtest.util.*;
052: import org.netbeans.xtest.pe.*;
053: import java.io.*;
054: import java.util.*; // logging stuff
055: import org.netbeans.xtest.pes.PESLogger;
056: import java.util.logging.Level;
057:
058: /**
059: *
060: * @author breh
061: */
062: public class PESProjectGroup extends XMLBean {
063:
064: public static final int ALL_BUILDS = -1;
065: public static final int NO_MATRICES = 0;
066:
067: /** Creates a new instance of ProjectGroup */
068: public PESProjectGroup() {
069: }
070:
071: // attributes
072: // name of the project group
073: public String xmlat_name = null;
074: // description of the project group
075: public String xmlat_description = null;
076: // is it main project group - main is displayed on the first page
077: public boolean xmlat_main = false;
078: // are history matrices generated for this web
079: public int xmlat_historyMatrices = PESProjectGroup.NO_MATRICES;
080: // number of current builds to be available on the first
081: // page - older builds are moved to a separate page
082: public int xmlat_currentBuilds = PESProjectGroup.ALL_BUILDS;
083: // are old builds truncated ?
084: public int xmlat_detailedData = PESProjectGroup.ALL_BUILDS;
085: // are any very old builds deleted ?
086: public int xmlat_deleteAge = 0;
087:
088: // is this project group uploaded to database (default = yes if there was specified database upload path )
089: public boolean xmlat_uploadToDatabase = true;
090:
091: // elements
092: // projects in the group
093: public PESProject xmlel_PESProject[];
094:
095: // business methods
096: // name of the group
097: public String getName() {
098: return xmlat_name;
099: }
100:
101: // description of the group
102: public String getDescription() {
103: return xmlat_description;
104: }
105:
106: // is this group current - the main one, where all unsorted results are published
107: public boolean isMain() {
108: return xmlat_main;
109: }
110:
111: // transform matrices
112: public int getHistoryMatricesAge() {
113: return xmlat_historyMatrices;
114: }
115:
116: // truncate Old builds ?
117: public int getDetailedDataAge() {
118: return xmlat_detailedData;
119: }
120:
121: // get number of builds to be on the first page
122: public int getNumberOfCurrentBuilds() {
123: return xmlat_currentBuilds;
124: }
125:
126: // get age after which are builds considered for removal
127: public int getDeleteAge() {
128: return xmlat_deleteAge;
129: }
130:
131: // validator
132: public void checkValidity() throws PESConfigurationException {
133: if (xmlat_name == null)
134: throw new PESConfigurationException(
135: "PESConfig: PESWeb: PESProjectGroup: name is not set");
136: if (xmlat_description == null)
137: throw new PESConfigurationException(
138: "PESConfig: PESWeb: PESProjectGroup: description is not set");
139: if (!isMain()) {
140: if ((xmlel_PESProject == null)
141: | (xmlel_PESProject.length == 0))
142: throw new PESConfigurationException(
143: "PESConfig: PESWeb: PESProjectGroup: group is not main and no projects are defined within");
144: }
145: if (xmlel_PESProject != null) {
146: for (int i = 0; i < xmlel_PESProject.length; i++) {
147: xmlel_PESProject[i].checkValidity();
148: }
149:
150: }
151: }
152:
153: // business methods
154:
155: // pesWeb
156: private PESWeb parentWeb;
157: private ManagedGroup myManagedGroup;
158:
159: // all incoming reports belonging to this group
160: private Collection incomingReports = new ArrayList();
161:
162: public boolean addIncomingReport(IncomingReport report,
163: boolean always) {
164: // check whether the incoming report does belong to any of the
165: // included projects in this web
166: if (isThisReportMine(report) | (always & isMain())) {
167: // include it to incomings ....
168: PESLogger.logger.finer("processing incoming report from :"
169: + report.getReportRoot());
170: incomingReports.add(report);
171: // are hostnames mapped ?
172: if (parentWeb.areHostnamesMapped()) {
173: String mappedHostname = parentWeb
174: .getMappedHostname(report);
175: report.setMappedHostname(mappedHostname);
176: PESLogger.logger.finer("Mapping hostname "
177: + report.getHost() + " to "
178: + report.getMappedHostname());
179: }
180:
181: return true;
182: }
183: return false;
184: }
185:
186: // process this part of web
187: public ManagedGroup processResults() throws IOException {
188: PESLogger.logger
189: .fine("processing results in group" + getName());
190: Iterator i = incomingReports.iterator();
191: Collection failedReports = new ArrayList();
192: // copy reports and retransform them
193: while (i.hasNext()) {
194: Object o = i.next();
195: if (o instanceof IncomingReport) {
196: // this is what we need
197: IncomingReport report = (IncomingReport) o;
198:
199: if (!report.isReconfiguration()) {
200: PESLogger.logger
201: .finer("processing incoming report from :"
202: + report.getArchiveFile().getPath());
203: // get output directory
204: File outputDir = parentWeb.assignDirectory(report);
205: PESLogger.logger
206: .finest("outputdir is:" + outputDir);
207: // set the webLink attribute
208: report.setWebLink(parentWeb.getWebLink(outputDir));
209: PESLogger.logger.finest("weblink is:"
210: + report.getWebLink());
211:
212: try {
213: // unpack the whole report
214: if (report.isReplace()) {
215: FileUtils.deleteDirectory(outputDir, true);
216: }
217: File zipFile = report.getArchiveFile();
218: PESLogger.logger.finer("unpacking zip");
219: ZipUtils.unpackZip(zipFile, outputDir);
220:
221: // try to get the whole report in one bean -> if it fails
222: // then this zip is invalid ...
223: PESLogger.logger
224: .finer("loading the whole report (checking it's validity)");
225: XTestResultsReport xtr = ResultsUtils
226: .loadXTestResultsReport(outputDir);
227: // now try to save the report to a uploadworkdir (only if this projectgroup should be uploaded)
228: if (isUploadToDatabase()) {
229: prepareDatabaseData(report, xtr);
230: }
231: // clean not needed stuff (if required)
232: if (parentWeb.isTruncated()) {
233: report.deleteDetailedData(outputDir, false,
234: false);
235: }
236:
237: // retransform if needed
238: try {
239: boolean indexExists = (new File(outputDir,
240: "index.html")).isFile();
241: PESLogger.logger
242: .finest("Does index exist = "
243: + indexExists);
244: boolean retransform = parentWeb
245: .isTruncated()
246: | (!indexExists);
247: PESLogger.logger.finest("Retransform = "
248: + retransform);
249: String mappedHostname = parentWeb
250: .getMappedHostname(report);
251: XSLTransformers.transformResultsForServer(
252: outputDir, parentWeb.isTruncated(),
253: parentWeb.includeIDELogs(),
254: parentWeb.includeExceptions(),
255: mappedHostname, this , retransform);
256: } catch (Exception e) {
257: PESLogger.logger
258: .log(
259: Level.WARNING,
260: "Results retransformation failed for report from"
261: + report
262: .getReportRoot(),
263: e);
264: }
265: } catch (Exception e) {
266: PESLogger.logger.log(Level.WARNING,
267: "Caught exception when processing report from "
268: + report.getReportRoot()
269: + " report is not valid", e);
270: // exception - delete the directory
271: FileUtils.deleteDirectory(outputDir, false);
272: // this report cannot be added to web
273: failedReports.add(report);
274: report.setValid(false,
275: "Caught exception when processing report from "
276: + report.getReportRoot() + ". "
277: + e.getMessage());
278: }
279:
280: } else { // reconfiguration stuff
281: // we need to retransform the main navigator ...
282: try {
283: //PESLogger.logger.finer("this report is going to reconfigured");
284: File outputDir = report.getReportDir();
285: PESLogger.logger
286: .finer("Retransforming result in "
287: + outputDir);
288: String mappedHostname = parentWeb
289: .getMappedHostname(report);
290: XSLTransformers.transformResultsForServer(
291: outputDir, parentWeb.isTruncated(),
292: parentWeb.includeIDELogs(), parentWeb
293: .includeExceptions(),
294: mappedHostname, this , parentWeb
295: .isTruncated());
296: } catch (Exception e) {
297: PESLogger.logger.log(Level.WARNING,
298: "Results retransformation failed for report from"
299: + report.getReportRoot(), e);
300: failedReports.add(report);
301: }
302: }
303: } else {
304: // hey - how is this possible ?????
305: }
306: }
307: // Ok, we're done - remove failed results from incoming reports
308: // and save this the group's report
309: incomingReports.removeAll(failedReports);
310: IncomingReport[] icArray = (IncomingReport[]) incomingReports
311: .toArray(new IncomingReport[0]);
312: myManagedGroup = ManagedGroup.loadManagedGroup(parentWeb, this );
313: myManagedGroup.addIncomingReports(icArray);
314: // now what to so with failedReports ????
315: // move failed reports to invalids to invalid and removed from this place
316: moveInvalidReports(failedReports);
317: // is saving really necessary ? I don't think so ..
318: // myManagedGroup.saveManagedGroup();
319: return myManagedGroup;
320: }
321:
322: public void processWebPages() throws IOException {
323: if (myManagedGroup != null) {
324: myManagedGroup.processWebPages();
325: }
326: myManagedGroup.saveManagedGroup();
327: }
328:
329: // get all projects available in this group
330: public String[] getProjectsIDs() {
331: if (xmlel_PESProject == null)
332: return null;
333: String projects[] = new String[xmlel_PESProject.length];
334: for (int i = 0; i < xmlel_PESProject.length; i++) {
335: projects[i] = xmlel_PESProject[i].xmlat_project;
336: }
337: return projects;
338: }
339:
340: // does this report belong to this web
341: private boolean isThisReportMine(XTestResultsReport xtr) {
342: if (xmlel_PESProject != null) {
343: for (int i = 0; i < xmlel_PESProject.length; i++) {
344: if (xmlel_PESProject[i].isThisReportMine(xtr)) {
345: return true;
346: }
347: }
348: }
349: return false;
350: }
351:
352: // set parent web
353: public void finishInitialization(PESWeb web) {
354: if (xmlel_PESProject != null) {
355: for (int i = 0; i < xmlel_PESProject.length; i++) {
356: if (xmlel_PESProject[i] != null) {
357: xmlel_PESProject[i].finishInitialization();
358: }
359: }
360: }
361: // finish initialization of this object
362: this .parentWeb = web;
363: }
364:
365: /** are results from this project group uploaded to database ?
366: * @return Value of property xmlat_uploadToDatabase.
367: *
368: */
369: public boolean isUploadToDatabase() {
370: if (parentWeb.isUploadToDatabase()) {
371: return xmlat_uploadToDatabase;
372: } else {
373: return false;
374: }
375: }
376:
377: //
378: private void moveInvalidReports(Collection invalidReports) {
379: if (invalidReports == null)
380: return;
381: if (invalidReports.isEmpty())
382: return;
383: PESLogger.logger
384: .info("Proecssing invalid results found when processing zips");
385: Iterator i = invalidReports.iterator();
386: try {
387: File invalidDir = parentWeb.pesConfig
388: .getIncomingInvalidDir();
389: while (i.hasNext()) {
390: Object o = i.next();
391: if (o instanceof IncomingReport) {
392: IncomingReport report = (IncomingReport) o;
393: try {
394: PESLogger.logger
395: .warning("found invalid archive: "
396: + report.getArchiveFile()
397: + ", moving it to "
398: + invalidDir
399: + "\nThe reason is: "
400: + report.getInvalidMessage());
401: FileUtils.moveFileToDir(
402: report.getArchiveFile(), invalidDir);
403: } catch (IOException ioe) {
404: PESLogger.logger.log(Level.WARNING,
405: "Caugth IOException when moving invalid zips to 'invalid':"
406: + ioe.getMessage(), ioe);
407: }
408: }
409: }
410: } catch (IOException ioe) {
411: PESLogger.logger
412: .log(
413: Level.WARNING,
414: "IOException cautgh when getting incoming/invalid dir",
415: ioe);
416: }
417: }
418:
419: // preapres data for database upload (creates files in the upload workdir)
420: public void prepareDatabaseData(IncomingReport ir,
421: XTestResultsReport xtr) throws IOException {
422: PESLogger.logger.finer("report will be uploaded to database");
423: // save report
424: String localHostName = NetUtils.getLocalHostName();
425: // wait one second, so we can be 100% sure the filename is unique
426: try {
427: Thread.sleep(1000);
428: } catch (InterruptedException ie) {
429: }
430: String timeStamp = (new java.text.SimpleDateFormat(
431: "yyMMdd-HHmmss")).format(new java.util.Date());
432: String baseFilename = "pr-" + localHostName + "-" + timeStamp
433: + ".";
434: File xtrFile = new File(parentWeb.pesConfig
435: .getDBUploadsWorkdir(), baseFilename + "xtr.xml");
436: xtr.saveXMLBean(xtrFile);
437:
438: // prepare and save metadata report
439: IncomingReport uploadedIR = new IncomingReport();
440: uploadedIR.readIncomingReport(ir);
441: // set report root to show to the xml file name
442: uploadedIR.setReportRoot(xtrFile.getName());
443: // set weblink to the http:// format
444: String webURL = parentWeb.getWebURL();
445: // set team (if not set)
446: if (uploadedIR.getTeam() == null) {
447: String pesTeam = parentWeb.pesConfig.getTeam();
448: PESLogger.logger
449: .warning("Team is not specified in the report from ${pes_web_home}/"
450: + ir.getWebLink()
451: + " Assigning team to this PES default:"
452: + pesTeam);
453: uploadedIR.setTeam(pesTeam);
454: }
455:
456: if (webURL != null) {
457: uploadedIR.setWebLink(webURL + ir.getWebLink());
458: } else {
459: PESLogger.logger
460: .warning("webURL is not specified in PESWeb -> results will not be reachable from database ");
461: }
462:
463: File irFile = new File(parentWeb.pesConfig
464: .getDBUploadsWorkdir(), baseFilename + "ir.xml");
465: uploadedIR.saveXMLBean(irFile);
466: }
467:
468: }
|