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


001:        /********************************************************************************
002:         * CruiseControl, a Continuous Integration Toolkit
003:         * Copyright (c) 2007, 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.sourcecontrols;
037:
038:        import net.sourceforge.cruisecontrol.CruiseControlException;
039:        import net.sourceforge.cruisecontrol.Modification;
040:        import net.sourceforge.cruisecontrol.SourceControl;
041:        import net.sourceforge.cruisecontrol.util.Commandline;
042:        import net.sourceforge.cruisecontrol.util.IO;
043:        import net.sourceforge.cruisecontrol.util.StreamLogger;
044:        import net.sourceforge.cruisecontrol.util.ValidationHelper;
045:        import org.apache.log4j.Logger;
046:        import org.jdom.Document;
047:        import org.jdom.Element;
048:        import org.jdom.JDOMException;
049:        import org.jdom.input.SAXBuilder;
050:
051:        import java.io.BufferedReader;
052:        import java.io.File;
053:        import java.io.InputStream;
054:        import java.io.InputStreamReader;
055:        import java.io.IOException;
056:        import java.io.Reader;
057:        import java.io.StringReader;
058:        import java.text.ParseException;
059:        import java.util.ArrayList;
060:        import java.util.Calendar;
061:        import java.util.Collections;
062:        import java.util.Date;
063:        import java.util.Iterator;
064:        import java.util.List;
065:        import java.util.Map;
066:        import java.util.TimeZone;
067:        import java.util.regex.Matcher;
068:        import java.util.regex.Pattern;
069:
070:        /**
071:         * This class implements the SourceControl methods for a Mercurial repository.
072:         *
073:         * @author <a href="jerome@coffeebreaks.org">Jerome Lacoste</a>
074:         * @see <a href="http://www.selenic.com/mercurial">Mercurial web site</a>
075:         */
076:        public class Mercurial implements  SourceControl {
077:
078:            private static final Logger LOG = Logger.getLogger(Mercurial.class);
079:
080:            private final SourceControlProperties properties = new SourceControlProperties();
081:
082:            /**
083:             * Configuration parameters
084:             */
085:            private String localWorkingCopy;
086:
087:            static final String INCOMING_XML_TEMPLATE = "<hgChange>\n\t<author>{author}</author>\n\t<rev>{rev}</rev>\n\t"
088:                    + "<node>{node}</node>\n\t<description>{desc|escape}</description>\n\t<date>{date|hgdate}</date>\n\t"
089:                    + "<addedFiles>{file_adds}</addedFiles>\n\t<removedFiles>{file_dels}</removedFiles>\n\t"
090:                    + "<changedFiles>{files}</changedFiles>\n</hgChange>\n";
091:
092:            public Map getProperties() {
093:                return properties.getPropertiesAndReset();
094:            }
095:
096:            public void setProperty(String property) {
097:                properties.assignPropertyName(property);
098:            }
099:
100:            public void setPropertyOnDelete(String propertyOnDelete) {
101:                properties.assignPropertyOnDeleteName(propertyOnDelete);
102:            }
103:
104:            /**
105:             * Sets the local working copy to use when making calls to mercurial.
106:             *
107:             * @param localWorkingCopy String indicating the relative or absolute path
108:             *                         to the local working copy of the mercurial
109:             *                         repository of which to find the log history.
110:             */
111:            public void setLocalWorkingCopy(String localWorkingCopy) {
112:                this .localWorkingCopy = localWorkingCopy;
113:            }
114:
115:            /**
116:             * This method validates that at least the repository location or the local
117:             * working copy location has been specified.
118:             *
119:             * @throws net.sourceforge.cruisecontrol.CruiseControlException
120:             *          Thrown when the repository location and
121:             *          the local working copy location are both
122:             *          null
123:             */
124:            public void validate() throws CruiseControlException {
125:                if (localWorkingCopy != null) {
126:                    File workingDir = new File(localWorkingCopy);
127:                    ValidationHelper.assertTrue(workingDir.exists()
128:                            && workingDir.isDirectory(),
129:                            "'localWorkingCopy' must be an existing directory. Was "
130:                                    + workingDir.getAbsolutePath());
131:                }
132:            }
133:
134:            /**
135:             * Returns a list of modifications detailing all the changes between
136:             * the last build and the latest revision in the repository.
137:             *
138:             * @return the list of modifications, or an empty list if we failed
139:             *         to retrieve the changes.
140:             */
141:            public List getModifications(Date lastBuildDate, Date now) {
142:                String version = getMercurialVersion();
143:                LOG.info("Using Mercurial: '" + version + "'");
144:                Commandline command = null;
145:                List modifications = Collections.EMPTY_LIST;
146:                try {
147:                    command = buildHistoryCommand();
148:
149:                    modifications = execHistoryCommand(command);
150:
151:                    // TODO: should we filter out the results ?
152:                    // modifications = filterModifications(modifications, lastBuildDate, now);
153:
154:                } catch (Exception e) {
155:                    LOG.error("Error executing mercurial history command "
156:                            + command, e);
157:                }
158:                fillPropertiesIfNeeded(modifications);
159:                return modifications;
160:            }
161:
162:            private String getMercurialVersion() {
163:                Commandline command = null;
164:                try {
165:                    command = buildVersionCommand();
166:
167:                    return execVersionCommand(command);
168:                } catch (Exception e) {
169:                    LOG.error("Error executing mercurial version command "
170:                            + command, e);
171:                    return "version unresolved...";
172:                }
173:            }
174:
175:            /**
176:             * Generates the command line for the hg incoming command.
177:             * <p/>
178:             * For example:
179:             * <p/>
180:             * 'hg incoming --template "........."'
181:             *
182:             * @return history command
183:             * @throws net.sourceforge.cruisecontrol.CruiseControlException
184:             *          exception
185:             */
186:            Commandline buildHistoryCommand() throws CruiseControlException {
187:
188:                Commandline command = new Commandline();
189:                command.setExecutable("hg");
190:
191:                if (localWorkingCopy != null) {
192:                    command.setWorkingDirectory(localWorkingCopy);
193:                }
194:
195:                command.createArgument("incoming");
196:                // --debug required to get file_adds and file_dels to work in this version of mercurial (0.9.4+20070830)
197:                command.createArgument("--debug");
198:                command.createArgument("--template");
199:                command.createArgument(INCOMING_XML_TEMPLATE);
200:
201:                return command;
202:            }
203:
204:            private static List execHistoryCommand(Commandline command)
205:                    throws InterruptedException, IOException, ParseException,
206:                    JDOMException {
207:
208:                LOG.debug("Executing command: " + command);
209:
210:                Process p = command.execute();
211:
212:                Thread stderr = logErrorStream(p);
213:                InputStream commandOutputStream = p.getInputStream();
214:                List modifications = parseStream(commandOutputStream);
215:
216:                p.waitFor();
217:                stderr.join();
218:                IO.close(p);
219:
220:                return modifications;
221:            }
222:
223:            /**
224:             * Generates the command line for the hg version command.
225:             * <p/>
226:             * 'hg version'
227:             *
228:             * @return version command
229:             * @throws net.sourceforge.cruisecontrol.CruiseControlException
230:             *          exception
231:             */
232:            Commandline buildVersionCommand() throws CruiseControlException {
233:
234:                Commandline command = new Commandline();
235:                command.setExecutable("hg");
236:
237:                if (localWorkingCopy != null) {
238:                    command.setWorkingDirectory(localWorkingCopy);
239:                }
240:
241:                command.createArgument("version");
242:
243:                return command;
244:            }
245:
246:            private String execVersionCommand(Commandline command)
247:                    throws CruiseControlException {
248:
249:                LOG.debug("Executing command: " + command);
250:
251:                try {
252:                    Process p = command.execute();
253:
254:                    Thread stderr = logErrorStream(p);
255:                    InputStream svnStream = p.getInputStream();
256:                    String revision = parseVersionStream(svnStream);
257:
258:                    p.waitFor();
259:                    stderr.join();
260:                    IO.close(p);
261:
262:                    return revision;
263:                } catch (IOException e) {
264:                    throw new CruiseControlException(e);
265:                } catch (ParseException e) {
266:                    throw new CruiseControlException(e);
267:                } catch (InterruptedException e) {
268:                    throw new CruiseControlException(e);
269:                }
270:            }
271:
272:            static String parseVersionStream(InputStream svnStream)
273:                    throws ParseException, IOException {
274:                InputStreamReader reader = new InputStreamReader(svnStream,
275:                        "UTF-8");
276:                return HgVersionParser.parse(reader);
277:            }
278:
279:            private static Thread logErrorStream(Process p) {
280:                Thread stderr = new Thread(StreamLogger.getWarnPumper(LOG, p
281:                        .getErrorStream()));
282:                stderr.start();
283:                return stderr;
284:            }
285:
286:            static List/*Modification*/parseStream(InputStream inputStream)
287:                    throws JDOMException, IOException, ParseException {
288:
289:                Reader reader = new InputStreamReader(inputStream, "UTF-8");
290:                BufferedReader br = new BufferedReader(reader);
291:                String line;
292:                StringBuffer buffer = new StringBuffer();
293:                boolean startFound = false;
294:                while ((line = br.readLine()) != null) {
295:                    startFound |= line.startsWith("<");
296:                    if (startFound) {
297:                        buffer.append(line).append("\n");
298:                    }
299:                }
300:                reader = new StringReader("<hgChanges>" + buffer.toString()
301:                        + "</hgChanges>");
302:                try {
303:                    return HgLogParser.parse(reader);
304:                } finally {
305:                    reader.close();
306:                }
307:            }
308:
309:            void fillPropertiesIfNeeded(List modifications) {
310:                if (!modifications.isEmpty()) {
311:                    properties.modificationFound();
312:
313:                    String maxRevision = "";
314:                    for (int i = 0; i < modifications.size(); i++) {
315:                        Modification modification = (Modification) modifications
316:                                .get(i);
317:                        Modification.ModifiedFile file = (Modification.ModifiedFile) modification.files
318:                                .get(0);
319:                        if (i == modifications.size() - 1) {
320:                            maxRevision = modification.revision;
321:                        }
322:                        if (file.action.equals("deleted")) {
323:                            properties.deletionFound();
324:                        }
325:                    }
326:                    properties.put("hgrevision", maxRevision);
327:                }
328:            }
329:
330:            /*
331:            public static DateFormat getOutDateFormatter() {
332:                return Iso8601DateParser.ISO8601_DATE_PARSER;
333:            }
334:             */
335:
336:            static final class HgLogParser {
337:
338:                private HgLogParser() {
339:                }
340:
341:                static List/*Modification*/parse(Reader reader)
342:                        throws ParseException, JDOMException, IOException {
343:
344:                    SAXBuilder builder = new SAXBuilder(false);
345:                    Document document = builder.build(reader);
346:                    return parseDOMTree(document);
347:                }
348:
349:                static List/*Modification*/parseDOMTree(Document document)
350:                        throws ParseException {
351:                    List modifications = new ArrayList();
352:
353:                    Element rootElement = document.getRootElement();
354:                    List logEntries = rootElement.getChildren("hgChange");
355:                    for (Iterator iterator = logEntries.iterator(); iterator
356:                            .hasNext();) {
357:                        Element logEntry = (Element) iterator.next();
358:
359:                        List/*Modification*/modificationsOfRevision = parseLogEntry(logEntry);
360:                        modifications.addAll(modificationsOfRevision);
361:                    }
362:
363:                    return modifications;
364:                }
365:
366:                static List/*Modification*/parseLogEntry(Element logEntry)
367:                        throws ParseException {
368:                    List modifications = new ArrayList();
369:
370:                    String userName = logEntry.getChildText("author");
371:                    String revision = logEntry.getChildText("rev") + ":"
372:                            + logEntry.getChildText("node");
373:                    String comment = logEntry.getChildText("description");
374:                    // Date modifiedTime = convertIso8601Date(logEntry.getChildText("date"));
375:                    Date modifiedTime = convertHgDate(logEntry
376:                            .getChildText("date"));
377:                    String[] addedFiles = getFiles(logEntry
378:                            .getChildText("addedFiles"));
379:                    String[] removedFiles = getFiles(logEntry
380:                            .getChildText("removedFiles"));
381:                    String[] changedFiles = getFiles(logEntry
382:                            .getChildText("changedFiles"));
383:
384:                    addModifications(modifications, userName, revision,
385:                            comment, modifiedTime, addedFiles, "added");
386:                    addModifications(modifications, userName, revision,
387:                            comment, modifiedTime, changedFiles, "modified");
388:                    addModifications(modifications, userName, revision,
389:                            comment, modifiedTime, removedFiles, "removed");
390:
391:                    return modifications;
392:                }
393:
394:                private static void addModifications(List modifications,
395:                        String userName, String revision, String comment,
396:                        Date modifiedTime, String[] files, String action) {
397:                    for (int i = 0; i < files.length; i++) {
398:                        String filePath = files[i];
399:                        addModifications(modifications, userName, revision,
400:                                comment, modifiedTime, filePath, action);
401:                    }
402:                }
403:
404:                private static void addModifications(List modifications,
405:                        String userName, String revision, String comment,
406:                        Date modifiedTime, String filePath, String action) {
407:                    Modification modification = new Modification("mercurial");
408:
409:                    modification.modifiedTime = modifiedTime;
410:                    modification.userName = userName;
411:                    modification.comment = comment;
412:                    modification.revision = revision;
413:
414:                    Modification.ModifiedFile modfile = modification
415:                            .createModifiedFile(filePath, null);
416:                    modfile.action = action;
417:                    modfile.revision = modification.revision;
418:
419:                    modifications.add(modification);
420:                }
421:
422:                private static String[] getFiles(String childText) {
423:                    if (childText.length() == 0) {
424:                        return new String[0];
425:                    }
426:                    return childText.split(" ");
427:                }
428:
429:                /**
430:                 * Converts the specified SVN date string into a Date.
431:                 *
432:                 * @param date with format "2007-08-29 21:44 +0200"
433:                 * @return converted date
434:                 * @throws java.text.ParseException if specified date doesn't match the expected format
435:                 */
436:                /*
437:                private static Date convertIso8601Date(String date) throws ParseException {
438:                    try {
439:                        return Iso8601DateParser.parse(date);
440:                    } catch (IllegalArgumentException e) {
441:                        throw new ParseException(e.getMessage(), 0);
442:                    }
443:                }
444:                 */
445:
446:                /**
447:                 * Converts the specified SVN date string into a Date.
448:                 *
449:                 * @param date with format "2007-08-29 21:44 +0200"
450:                 * @return converted date
451:                 * @throws java.text.ParseException if specified date doesn't match the expected format
452:                 */
453:                static Date convertHgDate(String date) throws ParseException {
454:                    try {
455:                        return HgDateParser.parse(date);
456:                    } catch (IllegalArgumentException e) {
457:                        ParseException parseException = new ParseException(e
458:                                .getMessage(), 0);
459:                        parseException.initCause(e);
460:                        throw parseException;
461:                    }
462:                }
463:            }
464:
465:            // not used as Mercurial don't display the seconds. Too bad. Will this be fixed in a further revision ?
466:            // would be nice as is a more readable thatn the hgdate format... 
467:            // 2007-08-29 21:44 +0200
468:            /*
469:            private static final class Iso8601DateParser {
470:                private Iso8601DateParser() {
471:                }
472:
473:                private static final SimpleDateFormat ISO8601_DATE_PARSER = new SimpleDateFormat("yyyy-MM-d HH:mm Z");
474:
475:                private static Date parse(String date) throws ParseException {
476:                    return ISO8601_DATE_PARSER.parse(date);
477:                }
478:            }
479:             */
480:
481:            // 1188223879 -7200
482:            private static final class HgDateParser {
483:                private HgDateParser() {
484:                }
485:
486:                private static Date parse(String date) throws ParseException {
487:                    Pattern p = Pattern.compile("([0-9]*) (.*)");
488:                    Matcher m = p.matcher(date);
489:                    if (!m.matches()) {
490:                        throw new ParseException("HgDateParser: no match of "
491:                                + date, 0);
492:                    }
493:                    Calendar c = Calendar.getInstance(TimeZone
494:                            .getTimeZone("GMT"));
495:                    c.setTimeInMillis(Long.parseLong(m.group(1)) * 1000);
496:                    return c.getTime();
497:                }
498:            }
499:
500:            static final class HgVersionParser {
501:                private HgVersionParser() {
502:                }
503:
504:                public static String parse(Reader reader)
505:                        throws ParseException, IOException {
506:                    BufferedReader myReader = new BufferedReader(reader);
507:                    String versionLine = myReader.readLine();
508:                    if (versionLine == null) {
509:                        throw new IllegalStateException(
510:                                "hg version returned nothing");
511:                    }
512:
513:                    Pattern p = Pattern
514:                            .compile("Mercurial Distributed SCM \\((.*)\\)");
515:                    Matcher m = p.matcher(versionLine);
516:                    if (!m.matches()) {
517:                        throw new ParseException(
518:                                "HgVersionParser: no match of " + versionLine,
519:                                0);
520:                    }
521:                    return m.group(1);
522:                }
523:            }
524:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.