/** * Perforce Reviewer. * * Requires JavaMail and Activation packages from Sun. When you have these, * make sure mail.jar and activation.jar are on your CLASSPATH as well as * p4.jar. * * @author <a href="mailto:david@markley.cc">David Markley</a> * @version $Date: 2002/01/11 $ $Revision: #2 $ */ import java.util.*; import java.io.*; import java.text.*; import javax.mail.*; import javax.mail.internet.*; import javax.activation.*; import com.perforce.api.*; public class Reviewer extends Thread { private static Properties props; private Env env; private Counter cntr; private Session session = null; private String from = null; private String suffix = null; /** * Constructor. */ public Reviewer(Env env) { this(env, env.getProperty("p4.counter","review")); } public Reviewer(Env env, String counter) { super(); this.env = env; this.cntr = new Counter(env, counter); } /** * Check the counter every five seconds. */ public void run() { if (null == from) from = props.getProperty("p4.reviewer.from","nobody"); if (null == suffix) suffix = props.getProperty("p4.reviewer.suffix"); if (null == session) session = Session.getDefaultInstance(props, null); while (true) { checkCounter(); try { sleep(5000); } catch (InterruptedException iex) { /* don't care */ } } } private DataHandler getChangeData(Change chng) { Object[] args_change = { new Integer(chng.getNumber()) }; Object[] args_user = { chng.getUser().getId(), chng.getUser().getEmail(), chng.getUser().getFullName() }; String chng_fmt = props.getProperty("p4.reviewer.url.change"); String result; StringBuffer sb = new StringBuffer("<HTML><BODY>"); sb.append("Change "); if (null == chng_fmt) { sb.append(chng.getNumber()); } else { result = MessageFormat.format("<A href=\""+chng_fmt+ "\">{0,number,#}</A>", args_change); sb.append(result); } sb.append(" by "); result = MessageFormat.format("<A href=\"mailto:{1}\">{2}</A>",args_user); sb.append(result); sb.append(" on "); sb.append(chng.getModtimeString()); sb.append("<P>"); sb.append(chng.getShortDescription(true)); sb.append("<P>Affected Files...<P><PRE>"); Enumeration en = chng.getFiles().elements(); while (en.hasMoreElements()) { sb.append("\t"); sb.append(en.nextElement()); sb.append("\n"); } sb.append("</PRE>"); sb.append(props.getProperty("p4.reviewer.sig.html","<HR>P4 Reviewer")); sb.append("</BODY></HTML>"); return new DataHandler(new StringDataSource(sb.toString(),"text/html")); } /** * Notify users about the change. */ private void notifyUsers(Change chng, User[] usrs) { Vector v = new Vector(); int i; // Let's only send to users within the company. for (i = 0; i < usrs.length; i++) { if (null == suffix || usrs[i].getEmail().endsWith(suffix)) { v.addElement(usrs[i]); } } // session.setDebug(debug); try { chng.sync(); // create a message Message msg = new MimeMessage(session); msg.setFrom(new InternetAddress(from)); InternetAddress[] address = new InternetAddress[v.size()]; for (i = 0; i < v.size(); i++) { address[i] = new InternetAddress(((User)v.elementAt(i)).getEmail()); } User owner = chng.getUser(); owner.sync(); InternetAddress[] replyto = { new InternetAddress(owner.getEmail()) }; msg.setRecipients(Message.RecipientType.TO, address); msg.setReplyTo(replyto); msg.setSubject("Change Review: "+chng.getNumber()); msg.setSentDate(new Date()); // If the desired charset is known, you can use // setText(text, charset) // msg.setText(chng.getDescription()); // create and fill the first message part with text/plain version MimeBodyPart mbp1 = new MimeBodyPart(); String sig = props.getProperty("p4.reviewer.sig.plain",""); mbp1.setText(chng.getDescription()+"\n\n"+sig); // create and fill the second message part with text/html version MimeBodyPart mbp2 = new MimeBodyPart(); mbp2.setDataHandler(getChangeData(chng)); // create the Multipart and its parts to it Multipart mp = new MimeMultipart("alternative"); mp.addBodyPart(mbp1); mp.addBodyPart(mbp2); // add the Multipart to the message msg.setContent(mp); Transport.send(msg); } catch (MessagingException mex) { System.out.println("Reviewer: Trouble notifying users.\n"); mex.printStackTrace(System.out); System.out.println(); Exception ex = mex; do { if (ex instanceof SendFailedException) { SendFailedException sfex = (SendFailedException)ex; Address[] invalid = sfex.getInvalidAddresses(); if (invalid != null) { System.out.println(" ** Invalid Addresses"); if (invalid != null) { for (i = 0; i < invalid.length; i++) System.out.println(" " + invalid[i]); } } Address[] validUnsent = sfex.getValidUnsentAddresses(); if (validUnsent != null) { System.out.println(" ** ValidUnsent Addresses"); if (validUnsent != null) { for (i = 0; i < validUnsent.length; i++) System.out.println(" "+validUnsent[i]); } } Address[] validSent = sfex.getValidSentAddresses(); if (validSent != null) { System.out.println(" ** ValidSent Addresses"); if (validSent != null) { for (i = 0; i < validSent.length; i++) System.out.println(" "+validSent[i]); } } } System.out.println(); if (ex instanceof MessagingException) ex = ((MessagingException)ex).getNextException(); else ex = null; } while (ex != null); } } /** * Check to see if the counter has changed and who reviews the change. */ private void checkCounter() { Change[] chngs; User[] usrs; int i, j, max = 0; try { chngs = cntr.review(); for (i = 0; i < chngs.length; i++) { System.out.println("Reviewing change: "+chngs[i].getNumber()); if (max < chngs[i].getNumber()) max = chngs[i].getNumber(); usrs = chngs[i].reviews(); if (null != usrs) notifyUsers(chngs[i], usrs); } } catch (Exception ex) { /* Print out the exception, but don't stop the reviewer! */ ex.printStackTrace(); } if (0 < max) { cntr.setValue(max); try { cntr.commit(); } catch (PerforceException pex) { /* If the counter can not be set, die an ugly death. */ /* It's better to die, then to spam users with e-mail. */ System.err.println("Reviewer: Could not set the counter!"); System.exit(-1); } } } public static void main(String[] argv) { Env env = null; Debug.setDebugLevel(Debug.VERBOSE); try { env = new Env(argv[0]); } catch (PerforceException ex) { ex.printStackTrace(); System.exit(-1); } System.out.println(env); Reviewer r = new Reviewer(env); r.start(); } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 1985 | Sean Nolan | my initial branch | ||
//guest/perforce_software/utils/reviewd/reviewer/build/Reviewer.java | |||||
#1 | 1682 | rmg | Add David's Java Reviewer to //public. | ||
//guest/david_markley/reviewer/build/Reviewer.java | |||||
#1 | 1362 | David Markley |
Added a Reviewer that uses the p4package Java API. Had this for a while, but it's updated and best to be checked in. Lost one hard drive today...that's enough loss for today. |