Source Code Cross Referenced for P4ChangelistLabelIncrementer.java in  » Build » cruisecontrol » net » sourceforge » cruisecontrol » labelincrementers » 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 » Build » cruisecontrol » net.sourceforge.cruisecontrol.labelincrementers 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /********************************************************************************
002:         * CruiseControl, a Continuous Integration Toolkit
003:         * Copyright (c) 2006, ThoughtWorks, Inc.
004:         * 200 E. Randolph, 25th Floor
005:         * Chicago, IL 60601 USA
006:         * All rights reserved.
007:         *
008:         * Redistribution and use in source and binary forms, with or without
009:         * modification, are permitted provided that the following conditions
010:         * are met:
011:         *
012:         *     + Redistributions of source code must retain the above copyright
013:         *       notice, this list of conditions and the following disclaimer.
014:         *
015:         *     + Redistributions in binary form must reproduce the above
016:         *       copyright notice, this list of conditions and the following
017:         *       disclaimer in the documentation and/or other materials provided
018:         *       with the distribution.
019:         *
020:         *     + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
021:         *       names of its contributors may be used to endorse or promote
022:         *       products derived from this software without specific prior
023:         *       written permission.
024:         *
025:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
026:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
027:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
028:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
029:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
030:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
031:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
032:         * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
033:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
034:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036:         ********************************************************************************/package net.sourceforge.cruisecontrol.labelincrementers;
037:
038:        import java.io.BufferedReader;
039:        import java.io.File;
040:        import java.io.IOException;
041:        import java.io.InputStream;
042:        import java.io.InputStreamReader;
043:        import java.util.ArrayList;
044:        import java.util.List;
045:        import java.util.StringTokenizer;
046:
047:        import net.sourceforge.cruisecontrol.CruiseControlException;
048:        import net.sourceforge.cruisecontrol.LabelIncrementer;
049:        import net.sourceforge.cruisecontrol.util.Commandline;
050:        import net.sourceforge.cruisecontrol.util.ValidationHelper;
051:        import net.sourceforge.cruisecontrol.util.IO;
052:        import net.sourceforge.cruisecontrol.util.StreamLogger;
053:
054:        import org.apache.log4j.Logger;
055:        import org.apache.tools.ant.BuildException;
056:        import org.apache.tools.ant.Project;
057:        import org.apache.tools.ant.taskdefs.Delete;
058:        import org.apache.tools.ant.types.FileSet;
059:        import org.apache.tools.ant.types.PatternSet.NameEntry;
060:        import org.jdom.Element;
061:
062:        /**
063:         * This class uses the most current changelist of the user in Perforce as the
064:         * label for the builds.  It can also sync the Perforce managed files to that
065:         * changelist number, as well as clean out the existing managed files.
066:         *
067:         * @author <a href="mailto:groboclown@users.sourceforge.net">Matt Albrecht</a>
068:         */
069:        public class P4ChangelistLabelIncrementer implements  LabelIncrementer {
070:
071:            private static final Logger LOG = Logger
072:                    .getLogger(P4ChangelistLabelIncrementer.class);
073:            private static final String CHANGELIST_PREFIX = "@";
074:            private static final String REVISION_PREFIX = "#";
075:            private static final String RECURSE_U = "/...";
076:            private static final String RECURSE_W = "\\...";
077:
078:            private String p4Port;
079:            private String p4Client;
080:            private String p4User;
081:            private String p4View;
082:            private String p4Passwd;
083:
084:            private boolean clean = false;
085:            private boolean delete = false;
086:            private boolean sync = true;
087:
088:            private int baseChangelist = -1;
089:
090:            /**
091:             * Retrieves the current changelist, or, if given, the specified changelist,
092:             * and also performs any necessary actions the user requested.
093:             *
094:             * @param oldLabel Label from previous successful build.
095:             * @return Label to use for most recent successful build.
096:             */
097:            public String incrementLabel(String oldLabel, Element buildLog) {
098:                String label = null;
099:                try {
100:                    validate();
101:
102:                    // Perform conditional actions.
103:                    // Since the settings might change or be executed in any order,
104:                    // we perform the checks on which actions to run here.
105:                    boolean delTree = delete;
106:                    boolean cleanP4 = delTree || clean;
107:                    boolean syncP4 = cleanP4 || sync;
108:
109:                    if (cleanP4) {
110:                        LOG.info("Cleaning Perforce clientspec " + p4Client);
111:                        syncTo(REVISION_PREFIX + 0);
112:                    }
113:                    if (delTree) {
114:                        deleteView();
115:                    }
116:
117:                    label = getDefaultLabel();
118:
119:                    if (syncP4) {
120:                        syncTo(CHANGELIST_PREFIX + label);
121:                    }
122:                } catch (CruiseControlException cce) {
123:                    LOG.warn("Couldn't run expected tasks", cce);
124:                }
125:
126:                return label;
127:            }
128:
129:            public boolean isPreBuildIncrementer() {
130:                // This only has use when used as a pre-build incrementer
131:                return true;
132:            }
133:
134:            /**
135:             * Verify that the label specified -- the previous label -- is a valid label.
136:             * In this case any label is valid because the next label will not be based on
137:             * previous label but on information from Perforce.
138:             */
139:            public boolean isValidLabel(String label) {
140:                return true;
141:            }
142:
143:            /**
144:             * The instance must be fully initialized before calling this method.
145:             * @throws IllegalStateException if the instance is not properly initialized
146:             */
147:            public String getDefaultLabel() {
148:                if (baseChangelist > 0) {
149:                    return Integer.toString(baseChangelist);
150:                }
151:                // else
152:
153:                try {
154:                    validate();
155:
156:                    return getCurrentChangelist();
157:                } catch (CruiseControlException cce) {
158:                    cce.printStackTrace();
159:                    LOG.fatal("Problem accessing Perforce changelist", cce);
160:                    throw new IllegalStateException(
161:                            "Problem accessing Perforce changelist");
162:                }
163:            }
164:
165:            // User settings
166:
167:            /**
168:             * Set the changelist number that you want to build at.  If this isn't
169:             * set, then the class will get the most current submitted changelist
170:             * number.  Note that setting this will cause the build to ALWAYS build
171:             * at this changelist number.
172:             *
173:             * @param syncChange the changelist number to perform the sync to.
174:             */
175:            public void setChangelist(int syncChange) {
176:                baseChangelist = syncChange;
177:            }
178:
179:            public void setPort(String p4Port) {
180:                this .p4Port = p4Port;
181:            }
182:
183:            public void setClient(String p4Client) {
184:                this .p4Client = p4Client;
185:            }
186:
187:            public void setUser(String p4User) {
188:                this .p4User = p4User;
189:            }
190:
191:            public void setView(String p4View) {
192:                this .p4View = p4View;
193:            }
194:
195:            public void setPasswd(String p4Passwd) {
196:                this .p4Passwd = p4Passwd;
197:            }
198:
199:            /**
200:             * Disables the label incrementer from synchronizing Perforce to the
201:             * view.
202:             *
203:             * @param b
204:             */
205:            public void setNoSync(boolean b) {
206:                this .sync = !b;
207:            }
208:
209:            /**
210:             * Perform a "p4 sync -f [view]#0" before syncing anew.  This will force
211:             * the sync to happen.
212:             *
213:             * @param b
214:             */
215:            public void setClean(boolean b) {
216:                this .clean = b;
217:            }
218:
219:            /**
220:             * Perform a recursive delete of the clientspec view.  This
221:             * will force a clean & sync.  Note that this can potentially
222:             * be very destructive, so use with the utmost caution.
223:             *
224:             * @param b
225:             */
226:            public void setDelete(boolean b) {
227:                this .delete = b;
228:            }
229:
230:            public void validate() throws CruiseControlException {
231:                ValidationHelper.assertIsSet(p4View, "view", this .getClass());
232:                ValidationHelper
233:                        .assertNotEmpty(p4View, "view", this .getClass());
234:                ValidationHelper.assertNotEmpty(p4Client, "client", this 
235:                        .getClass());
236:                ValidationHelper
237:                        .assertNotEmpty(p4Port, "port", this .getClass());
238:                ValidationHelper
239:                        .assertNotEmpty(p4User, "user", this .getClass());
240:                ValidationHelper.assertNotEmpty(p4Passwd, "passwd", this 
241:                        .getClass());
242:            }
243:
244:            protected String getCurrentChangelist()
245:                    throws CruiseControlException {
246:                Commandline cmd = buildBaseP4Command();
247:                cmd.createArgument("changes");
248:                cmd.createArgument("-m1");
249:                cmd.createArgument("-ssubmitted");
250:
251:                ParseChangelistNumbers pcn = new ParseChangelistNumbers();
252:                runP4Cmd(cmd, pcn);
253:
254:                String[] changes = pcn.getChangelistNumbers();
255:                if (changes != null && changes.length == 1) {
256:                    return changes[0];
257:                } else {
258:                    throw new CruiseControlException(
259:                            "Could not discover the changelist");
260:                }
261:            }
262:
263:            protected void syncTo(String viewArg) throws CruiseControlException {
264:                Commandline cmd = buildBaseP4Command();
265:                cmd.createArguments("sync", p4View + viewArg);
266:
267:                runP4Cmd(cmd, new P4CmdParserAdapter());
268:            }
269:
270:            protected void deleteView() throws CruiseControlException {
271:                // despite what people tell you, deleting correctly in Java is
272:                // hard.  So, let Ant do our dirty work for us.
273:                try {
274:                    Project p = createProject();
275:                    FileSet fs = getWhereView(p);
276:                    Delete d = createDelete(p);
277:                    d.setProject(p);
278:                    d.setVerbose(true);
279:                    d.addFileset(fs);
280:                    d.execute();
281:                } catch (BuildException be) {
282:                    throw new CruiseControlException(be.getMessage(), be);
283:                }
284:            }
285:
286:            /**
287:             * If the view mapping contains a reference to a single file,
288:             *
289:             * @return the collection of recursive directories inside the Perforce
290:             *      view.
291:             * @throws CruiseControlException
292:             */
293:            protected FileSet getWhereView(Project p)
294:                    throws CruiseControlException {
295:                String view = p4View;
296:                if (view == null) {
297:                    view = "//...";
298:                }
299:                if (!view.endsWith(RECURSE_U) && !view.endsWith(RECURSE_W)) {
300:                    // we'll only care about the recursive view.  Anything else
301:                    // should be handled by the sync view#0
302:                    LOG.debug("view [" + view + "] isn't recursive.");
303:                    return null;
304:                }
305:                Commandline cmd = buildBaseP4Command();
306:                cmd.createArguments("where", view);
307:
308:                ParseOutputParam pop = new ParseOutputParam("");
309:                runP4Cmd(cmd, pop);
310:                String[] values = pop.getValues();
311:                if (values == null || values.length <= 0) {
312:                    LOG.debug("Didn't find any files for view");
313:                    return null;
314:                }
315:                FileSet fs = createFileSet(p);
316:
317:                // on windows, this is considered higher than the drive letter.
318:                fs.setDir(new File("/"));
319:                int count = 0;
320:
321:                for (int i = 0; i < values.length; ++i) {
322:                    // first token: the depot name
323:                    // second token: the client name
324:                    // third token+: the local file system name
325:
326:                    // like above, we only care about the recursive view.  If the
327:                    // line doesn't end in /... or \... (even if it's a %%1), we ignore
328:                    // it.  This makes our life so much simpler when dealing with
329:                    // spaces.
330:                    String s = values[i];
331:                    //LOG.debug("Parsing view line " + i + " [" + s + "]");
332:                    if (!s.endsWith(RECURSE_U) && !s.endsWith(RECURSE_W)) {
333:                        continue;
334:                    }
335:
336:                    String[] tokens = new String[3];
337:                    int pos = 0;
338:                    for (int j = 0; j < 3; ++j) {
339:                        StringBuffer sb = new StringBuffer();
340:                        boolean neot = true;
341:                        while (neot) {
342:                            if (pos >= s.length()) {
343:                                break;
344:                            }
345:                            int q1 = s.indexOf('\'', pos);
346:                            int q2 = s.indexOf('"', pos);
347:                            int sp = s.indexOf(' ', pos);
348:                            if (q1 >= 0 && (q1 < q2 || q2 < 0)
349:                                    && (q1 < sp || sp < 0)) {
350:                                sb.append(s.substring(pos, q1));
351:                                pos = q1 + 1;
352:                            } else if (q2 >= 0 && (q2 < q1 || q1 < 0)
353:                                    && (q2 < sp || sp < 0)) {
354:                                sb.append(s.substring(pos, q2));
355:                                pos = q2 + 1;
356:                            } else if (sp >= 0) {
357:                                // check if we're at the end of the token
358:                                String sub = s.substring(pos, sp);
359:                                pos = sp + 1;
360:                                sb.append(sub);
361:                                if (sub.endsWith(RECURSE_U)
362:                                        || sub.endsWith(RECURSE_W)) {
363:                                    neot = false;
364:                                } else {
365:                                    // keep the space - it's inside the token
366:                                    sb.append(' ');
367:                                }
368:                            } else {
369:                                sb.append(s.substring(pos));
370:                                neot = false;
371:                            }
372:                        }
373:                        tokens[j] = new String(sb).trim();
374:                    }
375:                    if (tokens[0] != null
376:                            && tokens[1] != null
377:                            && tokens[2] != null
378:                            && (tokens[2].endsWith(RECURSE_U) || tokens[2]
379:                                    .endsWith(RECURSE_W))) {
380:                        // convert the P4 recurse expression with the Ant
381:                        // recurse expression
382:                        String f = tokens[2].substring(0, tokens[2].length()
383:                                - RECURSE_W.length())
384:                                + File.separator + "**";
385:                        // a - in front of the depot name means to exclude this path
386:                        if (tokens[0].startsWith("-//")) {
387:                            NameEntry ne = fs.createExclude();
388:                            ne.setName(f);
389:                        } else {
390:                            NameEntry ne = fs.createInclude();
391:                            ne.setName(f);
392:                        }
393:                        ++count;
394:                    }
395:                }
396:                if (count > 0) {
397:                    return fs;
398:                } else {
399:                    LOG.debug("no files in view to delete");
400:                    return null;
401:                }
402:            }
403:
404:            protected Project createProject() {
405:                Project p = new Project();
406:                p.init();
407:                return p;
408:            }
409:
410:            protected Delete createDelete(Project p)
411:                    throws CruiseControlException {
412:                Object o = p.createTask("delete");
413:                if (o == null || !(o instanceof  Delete)) {
414:                    // Backup code just in case we didn't work right.
415:                    // If we can guarantee the above operation works all the time,
416:                    // then this log note should be replaced with an exception.
417:                    LOG
418:                            .info("Could not find <delete> task in Ant.  Defaulting to basic constructor.");
419:                    Delete d = new Delete();
420:                    d.setProject(p);
421:                    o = d;
422:                }
423:                return (Delete) o;
424:            }
425:
426:            protected FileSet createFileSet(Project p)
427:                    throws CruiseControlException {
428:                Object o = p.createDataType("fileset");
429:                if (o == null || !(o instanceof  FileSet)) {
430:                    // Backup code just in case we didn't work right.
431:                    // If we can guarantee the above operation works all the time,
432:                    // then this log note should be replaced with an exception.
433:                    LOG
434:                            .info("Could not find <fileset> type in Ant.  Defaulting to basic constructor.");
435:                    FileSet fs = new FileSet();
436:                    fs.setProject(p);
437:                    o = fs;
438:                }
439:                return (FileSet) o;
440:            }
441:
442:            protected Commandline buildBaseP4Command() {
443:                Commandline commandLine = new Commandline();
444:                commandLine.setExecutable("p4");
445:                commandLine.createArgument("-s");
446:
447:                if (p4Client != null) {
448:                    commandLine.createArguments("-c", p4Client);
449:                }
450:
451:                if (p4Port != null) {
452:                    commandLine.createArguments("-p", p4Port);
453:                }
454:
455:                if (p4User != null) {
456:                    commandLine.createArguments("-u", p4User);
457:                }
458:
459:                if (p4Passwd != null) {
460:                    commandLine.createArguments("-P", p4Passwd);
461:                }
462:                return commandLine;
463:            }
464:
465:            protected void runP4Cmd(Commandline cmd, P4CmdParser parser)
466:                    throws CruiseControlException {
467:                try {
468:                    Process p = cmd.execute();
469:
470:                    try {
471:                        Thread stderr = new Thread(StreamLogger.getWarnPumper(
472:                                LOG, p));
473:                        stderr.start();
474:
475:                        InputStream p4Stream = p.getInputStream();
476:                        parseStream(p4Stream, parser);
477:                        stderr.join();
478:                    } finally {
479:                        p.waitFor();
480:                        IO.close(p);
481:                    }
482:                } catch (IOException e) {
483:                    throw new CruiseControlException(
484:                            "Problem trying to execute command line process", e);
485:                } catch (InterruptedException e) {
486:                    throw new CruiseControlException(
487:                            "Problem trying to execute command line process", e);
488:                }
489:            }
490:
491:            protected void parseStream(InputStream stream, P4CmdParser parser)
492:                    throws IOException {
493:                String line;
494:                BufferedReader reader = new BufferedReader(
495:                        new InputStreamReader(stream));
496:                while ((line = reader.readLine()) != null) {
497:                    if (line.startsWith("error:")) {
498:                        throw new IOException(
499:                                "Error reading P4 stream: P4 says: " + line);
500:                    } else if (line.startsWith("exit: 0")) {
501:                        LOG.debug("p4cmd: Found exit 0");
502:                        break;
503:                    } else if (line.startsWith("exit:")) {
504:                        // not an exit code of 0
505:                        LOG.error("p4cmd: Found exit " + line);
506:                        throw new IOException(
507:                                "Error reading P4 stream: P4 says: " + line);
508:                    } else if (line.startsWith("warning:")) {
509:                        parser.warning(line.substring(8));
510:                    } else if (line.startsWith("info:")
511:                            || line.startsWith("info1:")) {
512:                        parser.info(line.substring(5));
513:                    } else if (line.startsWith("text:")) {
514:                        parser.text(line.substring(5));
515:                    }
516:                }
517:                if (line == null) {
518:                    throw new IOException(
519:                            "Error reading P4 stream: Unexpected EOF reached");
520:                }
521:            }
522:
523:            protected static interface P4CmdParser {
524:                public void warning(String msg);
525:
526:                public void info(String msg);
527:
528:                public void text(String msg);
529:            }
530:
531:            protected static class P4CmdParserAdapter implements  P4CmdParser {
532:                public void warning(String msg) {
533:                    // empty
534:                }
535:
536:                public void info(String msg) {
537:                    // empty
538:                }
539:
540:                public void text(String msg) {
541:                    // empty
542:                }
543:            }
544:
545:            protected static class ParseChangelistNumbers extends
546:                    P4CmdParserAdapter {
547:                private ArrayList changelists = new ArrayList();
548:
549:                public void info(String msg) {
550:                    StringTokenizer st = new StringTokenizer(msg);
551:                    st.nextToken(); // skip 'Change' text
552:                    changelists.add(st.nextToken());
553:                }
554:
555:                public String[] getChangelistNumbers() {
556:                    String[] changelistNumbers = new String[0];
557:                    return (String[]) changelists.toArray(changelistNumbers);
558:                }
559:            }
560:
561:            protected static class ParseOutputParam extends P4CmdParserAdapter {
562:                public ParseOutputParam(String paramName) {
563:                    this .paramName = paramName;
564:                }
565:
566:                private final String paramName;
567:                private List values = new ArrayList();
568:
569:                public void info(final String msg) {
570:                    String m = msg.trim();
571:                    if (m.startsWith(paramName)) {
572:                        String m2 = m.substring(paramName.length()).trim();
573:                        values.add(m2);
574:                    }
575:                }
576:
577:                public String[] getValues() {
578:                    String[] v = new String[0];
579:                    return (String[]) values.toArray(v);
580:                }
581:            }
582:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.