Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Like this presentation? Why not share!

Application-Specific Models and Pointcuts using a Logic Meta Language

on

  • 542 views

Application-Specific Models and Pointcuts using a Logic Meta Language, Johan Brichau, Andy Kellens Kris Gybels, Kim Mens, ESUG 2006, Prague

Application-Specific Models and Pointcuts using a Logic Meta Language, Johan Brichau, Andy Kellens Kris Gybels, Kim Mens, ESUG 2006, Prague

Statistics

Views

Total Views
542
Views on SlideShare
542
Embed Views
0

Actions

Likes
0
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Application-Specific Models and Pointcuts using a Logic Meta Language Application-Specific Models and Pointcuts using a Logic Meta Language Presentation Transcript

  • Application-Specific Models and Pointcuts using a Logic Meta Language Johan Brichau Andy Kellens Kris Gybels Kim Mens Robert Hirschfeld Theo D’Hondt
  • Crosscutting Concerns */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( import java.io.*; new FileOutputStream(localFileName)); import java.util.zip.*; conn = url.openConnection(); /** in = conn.getInputStream(); * Command line program to copy a file to another directory. * @author Marco Schmidt byte[] buffer = new byte[1024]; */ int numRead; public class CopyFile { // constant values for the override option long numWritten = 0; public static final int OVERWRITE_ALWAYS = 1; while ((numRead = in.read(buffer)) != -1) { public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; out.write(buffer, 0, numRead); numWritten += numRead; // program options initialized to default values private static int bufferSize = 4 * 1024; } private static boolean clock = true; System.out.println(localFileName + "t" + numWritten); private static boolean copyOriginalTimestamp = true; private static boolean verify = true; } catch (Exception exception) { private static int override = OVERWRITE_ASK; exception.printStackTrace(); public static Long copyFile(File srcFile, File destFile) } finally { throws IOException { try { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); if (in != null) { long millis = System.currentTimeMillis(); in.close(); CRC32 checksum = null; if (verify) { } checksum = new CRC32(); if (out != null) { checksum.reset(); } out.close(); byte[] buffer = new byte[bufferSize]; } int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { } catch (IOException ioe) { if (verify) { } checksum.update(buffer, 0, bytesRead); } } out.write(buffer, 0, bytesRead); } } out.close(); in.close(); public static void download(String address) { if (clock) { millis = System.currentTimeMillis() - millis; int lastSlashIndex = address.lastIndexOf('/'); System.out.println("Second(s): " + (millis/1000L)); if (lastSlashIndex >= 0 && } if (verify) { lastSlashIndex < address.length() - 1) { return new Long(checksum.getValue()); download(address, address.substring(lastSlashIndex + 1)); } else { return null; } else { } System.err.println("Could not figure out local file name for " + } address); public static Long createChecksum(File file) throws IOException { } long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); } CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; public static void main(String[] args) { int bytesRead; for (int i = 0; i < args.length; i++) { while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); download(args[i]); } } in.close(); if (clock) { } millis = System.currentTimeMillis() - millis; } System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. */ * Take into consideration override option and public class HappyNewYear implements Runnable * ask user in case file exists and override option is ask. * @param file File object for potential destination file { * @return true if data is to be copied to file, false if not private static NumberFormat formatter = NumberFormat.getInstance(); */ public static boolean doCopy(File file) { private JFrame frame; boolean exists = file.exists(); private JLabel label; if (override == OVERWRITE_ALWAYS || !exists) { return true; private long newYearMillis; } else private String message; if (override == OVERWRITE_NEVER) { return false; } else public HappyNewYear(JFrame frame, JLabel label) if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + { "Overwrite (y/n)?"); // store argument GUI elements } else { throw new InternalError("Program error. Invalid " + this.frame = frame; "value for override: " + override); this.label = label; } } // compute beginning of next year Calendar cal = new GregorianCalendar(); public static void main(String[] args) throws IOException { // make sure there are exactly two arguments int nextYear = cal.get(Calendar.YEAR) + 1; if (args.length != 2) { cal.set(Calendar.YEAR, nextYear); System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); cal.set(Calendar.MONTH, Calendar.JANUARY); } cal.set(Calendar.DAY_OF_MONTH, 1); // make sure the source file is indeed a readable file File srcFile = new File(args[0]); cal.set(Calendar.HOUR_OF_DAY, 0); if (!srcFile.isFile() || !srcFile.canRead()) { cal.set(Calendar.MINUTE, 0); System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); cal.set(Calendar.SECOND, 0); } newYearMillis = cal.getTime().getTime(); // make sure the second argument is a directory File destDir = new File(args[1]); // prepare a message if (!destDir.isDirectory()) { message = "Happy " + nextYear + "!"; System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, // check if copying is desired given overwrite option if (!doCopy(destFile)) { String text) return; { } int fontSize = componentWidth * 2 / text.length(); // copy file, optionally creating a checksum Font font = new Font(fontName, fontStyle, fontSize); Long checksumSrc = copyFile(srcFile, destFile); FontMetrics fontMetrics = frame.getGraphics(). // copy timestamp of last modification getFontMetrics(font); if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { int stringWidth = fontMetrics.stringWidth(text); System.err.println("Error: Could not set " + return (int)(fontSize * 0.95 * "timestamp of copied file."); } componentWidth / stringWidth); } } // optionally verify file if (verify) { public static void main(String[] args) System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); { if (checksumSrc.equals(checksumDest)) { JFrame frame = new JFrame(); System.out.println(" OK, files are equal."); } else { frame.addKeyListener(new KeyListener() System.out.println(" Error: Checksums differ."); { } } public void keyPressed(KeyEvent event) {} } public void keyReleased(KeyEvent event) { /** if (event.getKeyChar() == KeyEvent.VK_ESCAPE) * Print a message to standard output and read lines from { * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user System.exit(0); * @return user answer, true for yes, false for no. } */ public static boolean readYesNoFromStandardInput(String message) { } System.out.println(message); public void keyTyped(KeyEvent event) {} String line; BufferedReader in = new BufferedReader(new InputStreamReader( } System.in)); ); Boolean answer = null; try frame.setUndecorated(true); { JLabel label = new JLabel("."); while ((line = in.readLine()) != null) { line = line.toLowerCase(); label.setBackground(Color.BLACK); if ("y".equals(line) || "yes".equals(line)) { label.setForeground(Color.WHITE); answer = Boolean.TRUE; break; label.setOpaque(true); } label.setHorizontalAlignment(SwingConstants.CENTER); else if ("n".equals(line) || "no".equals(line)) { frame.getContentPane().add(label); answer = Boolean.FALSE; GraphicsEnvironment.getLocalGraphicsEnvironment(). break; } getDefaultScreenDevice().setFullScreenWindow(frame); else final int fontStyle = Font.BOLD; { System.out.println("Could not understand answer ("" + final String fontName = "SansSerif"; line + ""). Please use y for yes or n for no."); int fontSizeNumber = determineFontSize(frame, } } Toolkit.getDefaultToolkit().getScreenSize().width, if (answer == null) { fontName, fontStyle, formatter.format(88888888)); throw new IOException("Unexpected end of input from stdin."); } int fontSizeText = determineFontSize(frame, in.close(); Toolkit.getDefaultToolkit().getScreenSize().width, return answer.booleanValue(); } fontName, fontStyle, "Happy 8888!"); catch (IOException ioe) label.setFont(new Font(fontName, fontStyle, { throw new InternalError( Math.min(fontSizeNumber, fontSizeText))); "Cannot read from stdin or write to stdout."); new HappyNewYear(frame, label).run(); } } } } public void run() { boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); } } 2
  • Crosscutting Concerns */ public class FileDownload { Synchronization public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( import java.io.*; new FileOutputStream(localFileName)); import java.util.zip.*; conn = url.openConnection(); /** in = conn.getInputStream(); * Command line program to copy a file to another directory. * @author Marco Schmidt byte[] buffer = new byte[1024]; */ int numRead; public class CopyFile { // constant values for the override option long numWritten = 0; public static final int OVERWRITE_ALWAYS = 1; while ((numRead = in.read(buffer)) != -1) { public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; out.write(buffer, 0, numRead); numWritten += numRead; // program options initialized to default values private static int bufferSize = 4 * 1024; } private static boolean clock = true; System.out.println(localFileName + "t" + numWritten); private static boolean copyOriginalTimestamp = true; private static boolean verify = true; } catch (Exception exception) { private static int override = OVERWRITE_ASK; exception.printStackTrace(); public static Long copyFile(File srcFile, File destFile) } finally { throws IOException { try { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); if (in != null) { long millis = System.currentTimeMillis(); in.close(); CRC32 checksum = null; if (verify) { } checksum = new CRC32(); if (out != null) { checksum.reset(); } out.close(); byte[] buffer = new byte[bufferSize]; } int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { } catch (IOException ioe) { if (verify) { } checksum.update(buffer, 0, bytesRead); } } out.write(buffer, 0, bytesRead); } } out.close(); in.close(); public static void download(String address) { if (clock) { millis = System.currentTimeMillis() - millis; int lastSlashIndex = address.lastIndexOf('/'); System.out.println("Second(s): " + (millis/1000L)); if (lastSlashIndex >= 0 && } if (verify) { lastSlashIndex < address.length() - 1) { return new Long(checksum.getValue()); download(address, address.substring(lastSlashIndex + 1)); } else { return null; } else { } System.err.println("Could not figure out local file name for " + } address); public static Long createChecksum(File file) throws IOException { } long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); } CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; public static void main(String[] args) { int bytesRead; for (int i = 0; i < args.length; i++) { while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); download(args[i]); } } in.close(); if (clock) { } millis = System.currentTimeMillis() - millis; } System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. */ * Take into consideration override option and public class HappyNewYear implements Runnable * ask user in case file exists and override option is ask. * @param file File object for potential destination file { * @return true if data is to be copied to file, false if not private static NumberFormat formatter = NumberFormat.getInstance(); */ public static boolean doCopy(File file) { private JFrame frame; boolean exists = file.exists(); private JLabel label; if (override == OVERWRITE_ALWAYS || !exists) { return true; private long newYearMillis; } else private String message; if (override == OVERWRITE_NEVER) { return false; } else public HappyNewYear(JFrame frame, JLabel label) if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + { "Overwrite (y/n)?"); // store argument GUI elements } else { throw new InternalError("Program error. Invalid " + this.frame = frame; "value for override: " + override); this.label = label; } } // compute beginning of next year Calendar cal = new GregorianCalendar(); public static void main(String[] args) throws IOException { // make sure there are exactly two arguments int nextYear = cal.get(Calendar.YEAR) + 1; if (args.length != 2) { cal.set(Calendar.YEAR, nextYear); System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); cal.set(Calendar.MONTH, Calendar.JANUARY); } cal.set(Calendar.DAY_OF_MONTH, 1); // make sure the source file is indeed a readable file File srcFile = new File(args[0]); cal.set(Calendar.HOUR_OF_DAY, 0); if (!srcFile.isFile() || !srcFile.canRead()) { cal.set(Calendar.MINUTE, 0); System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); cal.set(Calendar.SECOND, 0); } newYearMillis = cal.getTime().getTime(); // make sure the second argument is a directory File destDir = new File(args[1]); // prepare a message if (!destDir.isDirectory()) { message = "Happy " + nextYear + "!"; System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, // check if copying is desired given overwrite option if (!doCopy(destFile)) { String text) return; { } int fontSize = componentWidth * 2 / text.length(); // copy file, optionally creating a checksum Font font = new Font(fontName, fontStyle, fontSize); Long checksumSrc = copyFile(srcFile, destFile); FontMetrics fontMetrics = frame.getGraphics(). // copy timestamp of last modification getFontMetrics(font); if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { int stringWidth = fontMetrics.stringWidth(text); System.err.println("Error: Could not set " + return (int)(fontSize * 0.95 * "timestamp of copied file."); } componentWidth / stringWidth); } } // optionally verify file if (verify) { public static void main(String[] args) System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); { if (checksumSrc.equals(checksumDest)) { JFrame frame = new JFrame(); System.out.println(" OK, files are equal."); } else { frame.addKeyListener(new KeyListener() System.out.println(" Error: Checksums differ."); { } } public void keyPressed(KeyEvent event) {} } public void keyReleased(KeyEvent event) { /** if (event.getKeyChar() == KeyEvent.VK_ESCAPE) * Print a message to standard output and read lines from { * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user System.exit(0); * @return user answer, true for yes, false for no. } */ public static boolean readYesNoFromStandardInput(String message) { } System.out.println(message); public void keyTyped(KeyEvent event) {} String line; BufferedReader in = new BufferedReader(new InputStreamReader( } System.in)); ); Boolean answer = null; try frame.setUndecorated(true); { JLabel label = new JLabel("."); while ((line = in.readLine()) != null) { line = line.toLowerCase(); label.setBackground(Color.BLACK); if ("y".equals(line) || "yes".equals(line)) { label.setForeground(Color.WHITE); answer = Boolean.TRUE; break; label.setOpaque(true); } label.setHorizontalAlignment(SwingConstants.CENTER); else if ("n".equals(line) || "no".equals(line)) { frame.getContentPane().add(label); answer = Boolean.FALSE; GraphicsEnvironment.getLocalGraphicsEnvironment(). break; } getDefaultScreenDevice().setFullScreenWindow(frame); else final int fontStyle = Font.BOLD; { System.out.println("Could not understand answer ("" + final String fontName = "SansSerif"; line + ""). Please use y for yes or n for no."); int fontSizeNumber = determineFontSize(frame, } } Toolkit.getDefaultToolkit().getScreenSize().width, if (answer == null) { fontName, fontStyle, formatter.format(88888888)); throw new IOException("Unexpected end of input from stdin."); } int fontSizeText = determineFontSize(frame, in.close(); Toolkit.getDefaultToolkit().getScreenSize().width, return answer.booleanValue(); } fontName, fontStyle, "Happy 8888!"); catch (IOException ioe) label.setFont(new Font(fontName, fontStyle, { throw new InternalError( Math.min(fontSizeNumber, fontSizeText))); "Cannot read from stdin or write to stdout."); new HappyNewYear(frame, label).run(); } } } } public void run() { boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); } } 2
  • Crosscutting Concerns */ public class FileDownload { Synchronization public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( import java.io.*; new FileOutputStream(localFileName)); import java.util.zip.*; conn = url.openConnection(); /** in = conn.getInputStream(); * Command line program to copy a file to another directory. * @author Marco Schmidt byte[] buffer = new byte[1024]; */ int numRead; public class CopyFile { // constant values for the override option long numWritten = 0; public static final int OVERWRITE_ALWAYS = 1; while ((numRead = in.read(buffer)) != -1) { public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; out.write(buffer, 0, numRead); numWritten += numRead; // program options initialized to default values private static int bufferSize = 4 * 1024; } private static boolean clock = true; System.out.println(localFileName + "t" + numWritten); private static boolean copyOriginalTimestamp = true; private static boolean verify = true; } catch (Exception exception) { private static int override = OVERWRITE_ASK; exception.printStackTrace(); public static Long copyFile(File srcFile, File destFile) } finally { throws IOException { try { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); if (in != null) { in.close(); UI dependency long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { } checksum = new CRC32(); if (out != null) { checksum.reset(); } out.close(); byte[] buffer = new byte[bufferSize]; } int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { } catch (IOException ioe) { if (verify) { } checksum.update(buffer, 0, bytesRead); } } out.write(buffer, 0, bytesRead); } } out.close(); in.close(); public static void download(String address) { if (clock) { millis = System.currentTimeMillis() - millis; int lastSlashIndex = address.lastIndexOf('/'); System.out.println("Second(s): " + (millis/1000L)); if (lastSlashIndex >= 0 && } if (verify) { lastSlashIndex < address.length() - 1) { return new Long(checksum.getValue()); download(address, address.substring(lastSlashIndex + 1)); } else { return null; } else { } System.err.println("Could not figure out local file name for " + } address); public static Long createChecksum(File file) throws IOException { } long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); } CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; public static void main(String[] args) { int bytesRead; for (int i = 0; i < args.length; i++) { while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); download(args[i]); } } in.close(); if (clock) { } millis = System.currentTimeMillis() - millis; } System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. */ * Take into consideration override option and public class HappyNewYear implements Runnable * ask user in case file exists and override option is ask. * @param file File object for potential destination file { * @return true if data is to be copied to file, false if not private static NumberFormat formatter = NumberFormat.getInstance(); */ public static boolean doCopy(File file) { private JFrame frame; boolean exists = file.exists(); private JLabel label; if (override == OVERWRITE_ALWAYS || !exists) { return true; private long newYearMillis; } else private String message; if (override == OVERWRITE_NEVER) { return false; } else public HappyNewYear(JFrame frame, JLabel label) if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + { "Overwrite (y/n)?"); // store argument GUI elements } else { throw new InternalError("Program error. Invalid " + this.frame = frame; "value for override: " + override); this.label = label; } } // compute beginning of next year Calendar cal = new GregorianCalendar(); public static void main(String[] args) throws IOException { // make sure there are exactly two arguments int nextYear = cal.get(Calendar.YEAR) + 1; if (args.length != 2) { cal.set(Calendar.YEAR, nextYear); System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); cal.set(Calendar.MONTH, Calendar.JANUARY); } cal.set(Calendar.DAY_OF_MONTH, 1); // make sure the source file is indeed a readable file File srcFile = new File(args[0]); cal.set(Calendar.HOUR_OF_DAY, 0); if (!srcFile.isFile() || !srcFile.canRead()) { cal.set(Calendar.MINUTE, 0); System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); cal.set(Calendar.SECOND, 0); } newYearMillis = cal.getTime().getTime(); // make sure the second argument is a directory File destDir = new File(args[1]); // prepare a message if (!destDir.isDirectory()) { message = "Happy " + nextYear + "!"; System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, // check if copying is desired given overwrite option if (!doCopy(destFile)) { String text) return; { } int fontSize = componentWidth * 2 / text.length(); // copy file, optionally creating a checksum Font font = new Font(fontName, fontStyle, fontSize); Long checksumSrc = copyFile(srcFile, destFile); FontMetrics fontMetrics = frame.getGraphics(). // copy timestamp of last modification getFontMetrics(font); if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { int stringWidth = fontMetrics.stringWidth(text); System.err.println("Error: Could not set " + return (int)(fontSize * 0.95 * "timestamp of copied file."); } componentWidth / stringWidth); } } // optionally verify file if (verify) { public static void main(String[] args) System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); { if (checksumSrc.equals(checksumDest)) { JFrame frame = new JFrame(); System.out.println(" OK, files are equal."); } else { frame.addKeyListener(new KeyListener() System.out.println(" Error: Checksums differ."); { } } public void keyPressed(KeyEvent event) {} } public void keyReleased(KeyEvent event) { /** if (event.getKeyChar() == KeyEvent.VK_ESCAPE) * Print a message to standard output and read lines from { * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user System.exit(0); * @return user answer, true for yes, false for no. } */ public static boolean readYesNoFromStandardInput(String message) { } System.out.println(message); public void keyTyped(KeyEvent event) {} String line; BufferedReader in = new BufferedReader(new InputStreamReader( } System.in)); ); Boolean answer = null; try frame.setUndecorated(true); { JLabel label = new JLabel("."); while ((line = in.readLine()) != null) { line = line.toLowerCase(); label.setBackground(Color.BLACK); if ("y".equals(line) || "yes".equals(line)) { label.setForeground(Color.WHITE); answer = Boolean.TRUE; break; label.setOpaque(true); } label.setHorizontalAlignment(SwingConstants.CENTER); else if ("n".equals(line) || "no".equals(line)) { frame.getContentPane().add(label); answer = Boolean.FALSE; GraphicsEnvironment.getLocalGraphicsEnvironment(). break; } getDefaultScreenDevice().setFullScreenWindow(frame); else final int fontStyle = Font.BOLD; { System.out.println("Could not understand answer ("" + final String fontName = "SansSerif"; line + ""). Please use y for yes or n for no."); int fontSizeNumber = determineFontSize(frame, } } Toolkit.getDefaultToolkit().getScreenSize().width, if (answer == null) { fontName, fontStyle, formatter.format(88888888)); throw new IOException("Unexpected end of input from stdin."); } int fontSizeText = determineFontSize(frame, in.close(); Toolkit.getDefaultToolkit().getScreenSize().width, return answer.booleanValue(); } fontName, fontStyle, "Happy 8888!"); catch (IOException ioe) label.setFont(new Font(fontName, fontStyle, { throw new InternalError( Math.min(fontSizeNumber, fontSizeText))); "Cannot read from stdin or write to stdout."); new HappyNewYear(frame, label).run(); } } } } public void run() { boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); } } 2
  • Crosscutting Concerns */ public class FileDownload { Synchronization public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( import java.io.*; new FileOutputStream(localFileName)); import java.util.zip.*; conn = url.openConnection(); /** in = conn.getInputStream(); * Command line program to copy a file to another directory. * @author Marco Schmidt byte[] buffer = new byte[1024]; */ int numRead; public class CopyFile { // constant values for the override option long numWritten = 0; public static final int OVERWRITE_ALWAYS = 1; while ((numRead = in.read(buffer)) != -1) { public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; out.write(buffer, 0, numRead); numWritten += numRead; // program options initialized to default values private static int bufferSize = 4 * 1024; } private static boolean clock = true; System.out.println(localFileName + "t" + numWritten); private static boolean copyOriginalTimestamp = true; private static boolean verify = true; } catch (Exception exception) { private static int override = OVERWRITE_ASK; exception.printStackTrace(); public static Long copyFile(File srcFile, File destFile) } finally { throws IOException { try { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); if (in != null) { in.close(); UI dependency long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { } checksum = new CRC32(); if (out != null) { checksum.reset(); } out.close(); byte[] buffer = new byte[bufferSize]; } int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { } catch (IOException ioe) { if (verify) { } checksum.update(buffer, 0, bytesRead); } } out.write(buffer, 0, bytesRead); } } out.close(); in.close(); public static void download(String address) { if (clock) { millis = System.currentTimeMillis() - millis; int lastSlashIndex = address.lastIndexOf('/'); System.out.println("Second(s): " + (millis/1000L)); if (lastSlashIndex >= 0 && } if (verify) { lastSlashIndex < address.length() - 1) { return new Long(checksum.getValue()); download(address, address.substring(lastSlashIndex + 1)); } else { return null; } else { } System.err.println("Could not figure out local file name for " + } address); public static Long createChecksum(File file) throws IOException { } long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); } CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; public static void main(String[] args) { int bytesRead; for (int i = 0; i < args.length; i++) { while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); download(args[i]); } } in.close(); if (clock) { } millis = System.currentTimeMillis() - millis; } System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. */ * Take into consideration override option and public class HappyNewYear implements Runnable * ask user in case file exists and override option is ask. * @param file File object for potential destination file { * @return true if data is to be copied to file, false if not private static NumberFormat formatter = NumberFormat.getInstance(); */ public static boolean doCopy(File file) { private JFrame frame; boolean exists = file.exists(); private JLabel label; if (override == OVERWRITE_ALWAYS || !exists) { return true; private long newYearMillis; } else private String message; if (override == OVERWRITE_NEVER) { return false; } else public HappyNewYear(JFrame frame, JLabel label) if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + { "Overwrite (y/n)?"); // store argument GUI elements } else { throw new InternalError("Program error. Invalid " + this.frame = frame; "value for override: " + override); this.label = label; } } // compute beginning of next year Calendar cal = new GregorianCalendar(); public static void main(String[] args) throws IOException { // make sure there are exactly two arguments int nextYear = cal.get(Calendar.YEAR) + 1; if (args.length != 2) { cal.set(Calendar.YEAR, nextYear); System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); cal.set(Calendar.MONTH, Calendar.JANUARY); } cal.set(Calendar.DAY_OF_MONTH, 1); // make sure the source file is indeed a readable file File srcFile = new File(args[0]); cal.set(Calendar.HOUR_OF_DAY, 0); if (!srcFile.isFile() || !srcFile.canRead()) { cal.set(Calendar.MINUTE, 0); System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); cal.set(Calendar.SECOND, 0); } newYearMillis = cal.getTime().getTime(); // make sure the second argument is a directory Scattering File destDir = new File(args[1]); // prepare a message if (!destDir.isDirectory()) { message = "Happy " + nextYear + "!"; System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, // check if copying is desired given overwrite option if (!doCopy(destFile)) { String text) return; { } int fontSize = componentWidth * 2 / text.length(); // copy file, optionally creating a checksum Font font = new Font(fontName, fontStyle, fontSize); Long checksumSrc = copyFile(srcFile, destFile); FontMetrics fontMetrics = frame.getGraphics(). & // copy timestamp of last modification getFontMetrics(font); if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { int stringWidth = fontMetrics.stringWidth(text); System.err.println("Error: Could not set " + return (int)(fontSize * 0.95 * "timestamp of copied file."); } componentWidth / stringWidth); } } // optionally verify file if (verify) { public static void main(String[] args) System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); { if (checksumSrc.equals(checksumDest)) { JFrame frame = new JFrame(); System.out.println(" OK, files are equal."); } else { frame.addKeyListener(new KeyListener() System.out.println(" Error: Checksums differ."); { Tangling } } public void keyPressed(KeyEvent event) {} } public void keyReleased(KeyEvent event) { /** if (event.getKeyChar() == KeyEvent.VK_ESCAPE) * Print a message to standard output and read lines from { * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user System.exit(0); * @return user answer, true for yes, false for no. } */ public static boolean readYesNoFromStandardInput(String message) { } System.out.println(message); public void keyTyped(KeyEvent event) {} String line; BufferedReader in = new BufferedReader(new InputStreamReader( } System.in)); ); Boolean answer = null; try frame.setUndecorated(true); { JLabel label = new JLabel("."); while ((line = in.readLine()) != null) { line = line.toLowerCase(); label.setBackground(Color.BLACK); if ("y".equals(line) || "yes".equals(line)) { label.setForeground(Color.WHITE); answer = Boolean.TRUE; break; label.setOpaque(true); } label.setHorizontalAlignment(SwingConstants.CENTER); else if ("n".equals(line) || "no".equals(line)) { frame.getContentPane().add(label); answer = Boolean.FALSE; GraphicsEnvironment.getLocalGraphicsEnvironment(). break; } getDefaultScreenDevice().setFullScreenWindow(frame); else final int fontStyle = Font.BOLD; { System.out.println("Could not understand answer ("" + final String fontName = "SansSerif"; line + ""). Please use y for yes or n for no."); int fontSizeNumber = determineFontSize(frame, } } Toolkit.getDefaultToolkit().getScreenSize().width, if (answer == null) { fontName, fontStyle, formatter.format(88888888)); throw new IOException("Unexpected end of input from stdin."); } int fontSizeText = determineFontSize(frame, in.close(); Toolkit.getDefaultToolkit().getScreenSize().width, return answer.booleanValue(); } fontName, fontStyle, "Happy 8888!"); catch (IOException ioe) label.setFont(new Font(fontName, fontStyle, { throw new InternalError( Math.min(fontSizeNumber, fontSizeText))); "Cannot read from stdin or write to stdout."); new HappyNewYear(frame, label).run(); } } } } public void run() { boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); } } 2
  • AOP */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { conn = url.openConnection(); public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); in = conn.getInputStream(); InputStream in = new FileInputStream(file); byte[] buffer = new byte[1024]; byte[] buffer = new byte[bufferSize]; int numRead; int bytesRead; long numWritten = 0; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); while ((numRead = in.read(buffer)) != -1) { } out.write(buffer, 0, numRead); in.close(); if (clock) { import java.io.*; numWritten += numRead; millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); import java.util.zip.*; } /** } finally { return new Long(checksum.getValue()); * Command line program to copy a file to another directory. try { } * @author Marco Schmidt */ if (in != null) { public class CopyFile { in.close(); // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; } public static final int OVERWRITE_NEVER = 2; if (out != null) { public static final int OVERWRITE_ASK = 3; out.close(); // program options initialized to default values } private static int bufferSize = 4 * 1024; private static boolean clock = true; } catch (IOException ioe) { } public static Long copyFile(File srcFile, File destFile) throws IOException { } } } byte[] buffer = new byte[bufferSize]; int bytesRead; public static void download(String address) { while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { int lastSlashIndex = address.lastIndexOf('/'); checksum.update(buffer, 0, bytesRead); } System.err.println("Could not figure out local file name for " + public static Long createChecksum(File file) throws IOException { return new Long(checksum.getValue()); address); } else { } public HappyNewYear(JFrame frame, JLabel label) return null; } } { } public static Long createChecksum(File file) throws IOException { public static void main(String[] args) { cal.set(Calendar.YEAR, nextYear); long millis = System.currentTimeMillis(); for (int i = 0; i < args.length; i++) { cal.set(Calendar.MONTH, Calendar.JANUARY); InputStream in = new FileInputStream(file); download(args[i]); cal.set(Calendar.DAY_OF_MONTH, 1); byte[] buffer = new byte[bufferSize]; } cal.set(Calendar.HOUR_OF_DAY, 0); int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { } cal.set(Calendar.MINUTE, 0); checksum.update(buffer, 0, bytesRead); } cal.set(Calendar.SECOND, 0); } in.close(); newYearMillis = cal.getTime().getTime(); if (clock) { // prepare a message millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); message = "Happy " + nextYear + "!"; } } return new Long(checksum.getValue()); } */ /** public class HappyNewYear implements Runnable * Determine if data is to be copied to given file. { * @param file File object for potential destination file private static NumberFormat formatter = NumberFormat.getInstance(); * @return true if data is to be copied to file, false if not private JFrame frame; */ public static boolean doCopy(File file) { private JLabel label; boolean exists = file.exists(); private long newYearMillis; if (override == OVERWRITE_ALWAYS || !exists) { return true; private String message; } else } else { public HappyNewYear(JFrame frame, JLabel label) throw new InternalError("Program error. Invalid " + { "value for override: " + override); } } cal.set(Calendar.YEAR, nextYear); public static void main(String[] args) throws IOException { cal.set(Calendar.MONTH, Calendar.JANUARY); // make sure there are exactly two arguments cal.set(Calendar.DAY_OF_MONTH, 1); if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); cal.set(Calendar.HOUR_OF_DAY, 0); System.exit(1); cal.set(Calendar.MINUTE, 0); } // make sure the source file is indeed a readable file cal.set(Calendar.SECOND, 0); File srcFile = new File(args[0]); newYearMillis = cal.getTime().getTime(); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); // prepare a message System.exit(1); message = "Happy " + nextYear + "!"; } // make sure the second argument is a directory } File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); public static int determineFontSize(JFrame frame, System.exit(1); int componentWidth, String fontName, int fontStyle, } // create File object for destination file String text) File destFile = new File(destDir, srcFile.getName()); { // check if copying is desired given overwrite option if (!doCopy(destFile)) { return (int)(fontSize * 0.95 * return; } componentWidth / stringWidth); } // copy timestamp of last modification public static void main(String[] args) } { /** JFrame frame = new JFrame(); * @return user answer, true for yes, false for no. frame.addKeyListener(new KeyListener() */ { public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); public void keyPressed(KeyEvent event) {} String line; public void keyReleased(KeyEvent event) { BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); if (event.getKeyChar() == KeyEvent.VK_ESCAPE) Boolean answer = null; { try { System.exit(0); while ((line = in.readLine()) != null) { } line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { } answer = Boolean.TRUE; public void keyTyped(KeyEvent event) {} break; } } else ); if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; frame.setUndecorated(true); break; JLabel label = new JLabel("."); } else label.setBackground(Color.BLACK); { label.setForeground(Color.WHITE); System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); label.setOpaque(true); } label.setHorizontalAlignment(SwingConstants.CENTER); } frame.getContentPane().add(label); catch (IOException ioe) GraphicsEnvironment.getLocalGraphicsEnvironment(). Modularized { getDefaultScreenDevice().setFullScreenWindow(frame); } final int fontStyle = Font.BOLD; } } label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); } public void run() { boolean newYear = false; do { newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); } } 3
  • Pointcuts Often point to details in source code (e.g. names) */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { conn = url.openConnection(); public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); in = conn.getInputStream(); InputStream in = new FileInputStream(file); byte[] buffer = new byte[1024]; byte[] buffer = new byte[bufferSize]; int numRead; int bytesRead; long numWritten = 0; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); while ((numRead = in.read(buffer)) != -1) { } out.write(buffer, 0, numRead); in.close(); if (clock) { import java.io.*; numWritten += numRead; millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); import java.util.zip.*; } /** } finally { return new Long(checksum.getValue()); * Command line program to copy a file to another directory. try { } * @author Marco Schmidt */ if (in != null) { public class CopyFile { in.close(); // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; } public static final int OVERWRITE_NEVER = 2; if (out != null) { public static final int OVERWRITE_ASK = 3; out.close(); // program options initialized to default values } private static int bufferSize = 4 * 1024; private static boolean clock = true; } catch (IOException ioe) { } public static Long copyFile(File srcFile, File destFile) throws IOException { } } } byte[] buffer = new byte[bufferSize]; int bytesRead; public static void download(String address) { while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { int lastSlashIndex = address.lastIndexOf('/'); checksum.update(buffer, 0, bytesRead); } System.err.println("Could not figure out local file name for " + public static Long createChecksum(File file) throws IOException { return new Long(checksum.getValue()); address); } else { } public HappyNewYear(JFrame frame, JLabel label) return null; } } { } public static Long createChecksum(File file) throws IOException { public static void main(String[] args) { cal.set(Calendar.YEAR, nextYear); long millis = System.currentTimeMillis(); for (int i = 0; i < args.length; i++) { cal.set(Calendar.MONTH, Calendar.JANUARY); InputStream in = new FileInputStream(file); download(args[i]); cal.set(Calendar.DAY_OF_MONTH, 1); byte[] buffer = new byte[bufferSize]; } cal.set(Calendar.HOUR_OF_DAY, 0); int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { } cal.set(Calendar.MINUTE, 0); checksum.update(buffer, 0, bytesRead); } cal.set(Calendar.SECOND, 0); } in.close(); newYearMillis = cal.getTime().getTime(); if (clock) { // prepare a message millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); message = "Happy " + nextYear + "!"; } } return new Long(checksum.getValue()); } */ /** public class HappyNewYear implements Runnable * Determine if data is to be copied to given file. { * @param file File object for potential destination file private static NumberFormat formatter = NumberFormat.getInstance(); * @return true if data is to be copied to file, false if not private JFrame frame; */ public static boolean doCopy(File file) { private JLabel label; boolean exists = file.exists(); private long newYearMillis; if (override == OVERWRITE_ALWAYS || !exists) { return true; private String message; } else } else { public HappyNewYear(JFrame frame, JLabel label) throw new InternalError("Program error. Invalid " + { "value for override: " + override); } } cal.set(Calendar.YEAR, nextYear); public static void main(String[] args) throws IOException { cal.set(Calendar.MONTH, Calendar.JANUARY); // make sure there are exactly two arguments cal.set(Calendar.DAY_OF_MONTH, 1); if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); cal.set(Calendar.HOUR_OF_DAY, 0); System.exit(1); cal.set(Calendar.MINUTE, 0); } // make sure the source file is indeed a readable file cal.set(Calendar.SECOND, 0); File srcFile = new File(args[0]); newYearMillis = cal.getTime().getTime(); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); // prepare a message System.exit(1); message = "Happy " + nextYear + "!"; } // make sure the second argument is a directory } File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); public static int determineFontSize(JFrame frame, System.exit(1); int componentWidth, String fontName, int fontStyle, } // create File object for destination file String text) File destFile = new File(destDir, srcFile.getName()); { // check if copying is desired given overwrite option if (!doCopy(destFile)) { return (int)(fontSize * 0.95 * return; } componentWidth / stringWidth); } // copy timestamp of last modification public static void main(String[] args) } { /** JFrame frame = new JFrame(); * @return user answer, true for yes, false for no. frame.addKeyListener(new KeyListener() */ { public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); public void keyPressed(KeyEvent event) {} String line; public void keyReleased(KeyEvent event) { BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); if (event.getKeyChar() == KeyEvent.VK_ESCAPE) Boolean answer = null; { try { System.exit(0); while ((line = in.readLine()) != null) { } line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { } answer = Boolean.TRUE; public void keyTyped(KeyEvent event) {} break; } } else ); if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; frame.setUndecorated(true); break; JLabel label = new JLabel("."); } else label.setBackground(Color.BLACK); { label.setForeground(Color.WHITE); System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); label.setOpaque(true); } label.setHorizontalAlignment(SwingConstants.CENTER); } frame.getContentPane().add(label); catch (IOException ioe) GraphicsEnvironment.getLocalGraphicsEnvironment(). { getDefaultScreenDevice().setFullScreenWindow(frame); } final int fontStyle = Font.BOLD; } } label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); } public void run() { boolean newYear = false; do { newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); } } 4
  • Pointcuts Often point to details in source code (e.g. names) */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { conn = url.openConnection(); public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); in = conn.getInputStream(); InputStream in = new FileInputStream(file); byte[] buffer = new byte[1024]; byte[] buffer = new byte[bufferSize]; int numRead; int bytesRead; long numWritten = 0; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); while ((numRead = in.read(buffer)) != -1) { } out.write(buffer, 0, numRead); in.close(); if (clock) { import java.io.*; numWritten += numRead; millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); import java.util.zip.*; } /** } finally { return new Long(checksum.getValue()); * Command line program to copy a file to another directory. try { } * @author Marco Schmidt */ if (in != null) { public class CopyFile { in.close(); // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; } public static final int OVERWRITE_NEVER = 2; if (out != null) { public static final int OVERWRITE_ASK = 3; out.close(); // program options initialized to default values } private static int bufferSize = 4 * 1024; private static boolean clock = true; } catch (IOException ioe) { } public static Long copyFile(File srcFile, File destFile) throws IOException { } } } byte[] buffer = new byte[bufferSize]; int bytesRead; public static void download(String address) { while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { int lastSlashIndex = address.lastIndexOf('/'); checksum.update(buffer, 0, bytesRead); } System.err.println("Could not figure out local file name for " + public static Long createChecksum(File file) throws IOException { return new Long(checksum.getValue()); address); } else { } public HappyNewYear(JFrame frame, JLabel label) return null; } } { } public static Long createChecksum(File file) throws IOException { public static void main(String[] args) { cal.set(Calendar.YEAR, nextYear); long millis = System.currentTimeMillis(); for (int i = 0; i < args.length; i++) { cal.set(Calendar.MONTH, Calendar.JANUARY); InputStream in = new FileInputStream(file); download(args[i]); cal.set(Calendar.DAY_OF_MONTH, 1); byte[] buffer = new byte[bufferSize]; } cal.set(Calendar.HOUR_OF_DAY, 0); int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { } cal.set(Calendar.MINUTE, 0); checksum.update(buffer, 0, bytesRead); } cal.set(Calendar.SECOND, 0); } in.close(); newYearMillis = cal.getTime().getTime(); if (clock) { // prepare a message millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); message = "Happy " + nextYear + "!"; } } return new Long(checksum.getValue()); } */ /** public class HappyNewYear implements Runnable * Determine if data is to be copied to given file. { * @param file File object for potential destination file private static NumberFormat formatter = NumberFormat.getInstance(); * @return true if data is to be copied to file, false if not private JFrame frame; */ public static boolean doCopy(File file) { private JLabel label; boolean exists = file.exists(); private long newYearMillis; if (override == OVERWRITE_ALWAYS || !exists) { return true; private String message; } else } else { public HappyNewYear(JFrame frame, JLabel label) throw new InternalError("Program error. Invalid " + { "value for override: " + override); } } cal.set(Calendar.YEAR, nextYear); public static void main(String[] args) throws IOException { cal.set(Calendar.MONTH, Calendar.JANUARY); // make sure there are exactly two arguments cal.set(Calendar.DAY_OF_MONTH, 1); if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); cal.set(Calendar.HOUR_OF_DAY, 0); System.exit(1); cal.set(Calendar.MINUTE, 0); } // make sure the source file is indeed a readable file cal.set(Calendar.SECOND, 0); File srcFile = new File(args[0]); newYearMillis = cal.getTime().getTime(); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); // prepare a message System.exit(1); message = "Happy " + nextYear + "!"; } // make sure the second argument is a directory } File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); public static int determineFontSize(JFrame frame, System.exit(1); int componentWidth, String fontName, int fontStyle, } // create File object for destination file String text) File destFile = new File(destDir, srcFile.getName()); { // check if copying is desired given overwrite option if (!doCopy(destFile)) { return (int)(fontSize * 0.95 * return; } componentWidth / stringWidth); } // copy timestamp of last modification public static void main(String[] args) } { /** JFrame frame = new JFrame(); * @return user answer, true for yes, false for no. frame.addKeyListener(new KeyListener() */ { public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); public void keyPressed(KeyEvent event) {} String line; public void keyReleased(KeyEvent event) { BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); if (event.getKeyChar() == KeyEvent.VK_ESCAPE) Boolean answer = null; { try { System.exit(0); while ((line = in.readLine()) != null) { } line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { } answer = Boolean.TRUE; public void keyTyped(KeyEvent event) {} break; } } else ); if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; frame.setUndecorated(true); break; JLabel label = new JLabel("."); } else label.setBackground(Color.BLACK); { label.setForeground(Color.WHITE); System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); label.setOpaque(true); } label.setHorizontalAlignment(SwingConstants.CENTER); } frame.getContentPane().add(label); catch (IOException ioe) GraphicsEnvironment.getLocalGraphicsEnvironment(). { getDefaultScreenDevice().setFullScreenWindow(frame); } final int fontStyle = Font.BOLD; } } label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); } public void run() { boolean newYear = false; do { newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); } } 4
  • Aspects in Smalltalk AspectS •Framework based •Pointcut using Smalltalk •Advice using block AsBeforeAfterAdvice qualifier:... pointcut: [WindowSensor withAllSubclasses select: [:each includesSelector: #eventDoubleClick:] thenCollect:[:each | AsJoinPointDescriptor targetClass: each targetSelector:#eventDoubleClick:]] beforeBlock: [:receiver :args :aspect :client | ...] 5
  • Aspects in Smalltalk AspectS •Framework based •Pointcut using Smalltalk •Advice using block AsBeforeAfterAdvice qualifier:... pointcut: [WindowSensor withAllSubclasses select: [:each includesSelector: #eventDoubleClick:] Pointcut thenCollect:[:each | AsJoinPointDescriptor targetClass: each targetSelector:#eventDoubleClick:]] beforeBlock: [:receiver :args :aspect :client | ...] 5
  • Aspects in Smalltalk AspectS •Framework based •Pointcut using Smalltalk •Advice using block AsBeforeAfterAdvice qualifier:... pointcut: [WindowSensor withAllSubclasses select: [:each includesSelector: #eventDoubleClick:] Pointcut thenCollect:[:each | AsJoinPointDescriptor targetClass: each targetSelector:#eventDoubleClick:]] beforeBlock: [:receiver :args :aspect :client | ...] Advice 5
  • Aspects in Carma Carma •Pointcut language •Declarative Meta Programming •Based on SOUL after ?jp matching reception(?jp, #eventDoubleClick:,?args), within(?jp, ?class, ?selector), classInHierarchyOf(?class,[WindowSensor]) do Transcript show: ?class. ... 6
  • Aspects in Carma Carma •Declarative •Unification •Pointcut language •Recursion •Declarative Meta Programming •Based on SOUL after ?jp matching reception(?jp, #eventDoubleClick:,?args), within(?jp, ?class, ?selector), classInHierarchyOf(?class,[WindowSensor]) do Transcript show: ?class. ... 6
  • Aspects in Carma Carma •Declarative •Unification •Pointcut language •Recursion •Declarative Meta Programming •Based on SOUL after ?jp matching reception(?jp, #eventDoubleClick:,?args), within(?jp, ?class, ?selector), Pointcut classInHierarchyOf(?class,[WindowSensor]) do Transcript show: ?class. ... 6
  • Aspects in Carma Carma •Declarative •Unification •Pointcut language •Recursion •Declarative Meta Programming •Based on SOUL after ?jp matching reception(?jp, #eventDoubleClick:,?args), within(?jp, ?class, ?selector), Pointcut classInHierarchyOf(?class,[WindowSensor]) do Transcript show: ?class. Advice ... 6
  • AspectSOUL AspectS Carma •Framework •Pointcuts 7
  • AspectSOUL AspectS Carma •Framework •Pointcuts AsCARMABeforeAfterAdvice qualifier:... pointcutQuery: ‘reception(?jp, #eventDoubleClick:,?args), within(?jp, ?class, ?selector), classInHierarchyOf(?class,[WindowSensor])’ beforeBlock: [:receiver :args :aspect :client | ...] 7
  • AspectSOUL AspectS Carma •Framework •Pointcuts AsCARMABeforeAfterAdvice qualifier:... pointcutQuery: ‘reception(?jp, #eventDoubleClick:,?args), within(?jp, ?class, ?selector), Pointcut classInHierarchyOf(?class,[WindowSensor])’ beforeBlock: [:receiver :args :aspect :client | ...] 7
  • AspectSOUL AspectS Carma •Framework •Pointcuts AsCARMABeforeAfterAdvice qualifier:... pointcutQuery: ‘reception(?jp, #eventDoubleClick:,?args), within(?jp, ?class, ?selector), Pointcut classInHierarchyOf(?class,[WindowSensor])’ beforeBlock: [:receiver :args :aspect :client | ...] Advice 7
  • Fragility 1.accessing protocol 2.selector corresponds to Person>>name variable name ^name Person>>name: anObject name := anObject 8
  • Fragility 1.accessing protocol 2.selector corresponds to Person>>name variable name ^name Person>>name: anObject name := anObject Synchronization class(?class), methodWithNameInClass(?method,?accessor,?class), instanceVariableInClassChain(?accessor,?class), methodInProtocol(?method,accessing), reception(?joinpoint,?accessor,?args), withinClass(?joinpoint,?class) 8
  • Fragility 1.accessing protocol 2.selector corresponds to Person>>name variable name ^name Person>>name: anObject Person>>getName name := anObject ^name Person>>setName: anObject name := anObject Synchronization class(?class), methodWithNameInClass(?method,?accessor,?class), instanceVariableInClassChain(?accessor,?class), methodInProtocol(?method,accessing), reception(?joinpoint,?accessor,?args), withinClass(?joinpoint,?class) 8
  • Fragility 1.accessing protocol 2.selector corresponds to variable name X Person>>name ^name Person>>name: anObject name := anObject ? ? Person>>getName ^name Person>>setName: anObject name := anObject Synchronization class(?class), methodWithNameInClass(?method,?accessor,?class), instanceVariableInClassChain(?accessor,?class), methodInProtocol(?method,accessing), reception(?joinpoint,?accessor,?args), withinClass(?joinpoint,?class) 8
  • Complexity 1.accessor: return instance var 2.mutator: assign instance var Person>>name ^name Person>>name: anObject name := anObject 9
  • Complexity 1.accessor: return instance var 2.mutator: assign instance var Person>>name ^name Person>>name: anObject name := anObject Synchronization class(?class), methodWithNameInClass(?method,?accessor,?class), instanceVariableInClassChain(?accessor,?class), returnStatement(?method,variable(?var)), reception(?joinpoint,?accessor,?args), withinClass(?joinpoint,?class) 9
  • Complexity 1.accessor: return instance var 2.mutator: assign instance var Person>>name Person>>friends ^name ^friends isNil ifTrue:[friends := Set new] Person>>name: anObject ifFalse:[friends] name := anObject ? Synchronization class(?class), methodWithNameInClass(?method,?accessor,?class), instanceVariableInClassChain(?accessor,?class), returnStatement(?method,variable(?var)), reception(?joinpoint,?accessor,?args), withinClass(?joinpoint,?class) 9
  • Complexity 1.accessor: return instance var 2.mutator: assign instance var Person>>name Person>>friends ^name ^friends isNil ifTrue:[friends := Set new] Person>>name: anObject ifFalse:[friends] name := anObject ? Synchronization Synchronisation Synchronisation class(?class), class(?class), methodWithNameInClass(?method,?accessor,?class), class(?class), methodWithNameInClass(?method,?accessor,?class), instanceVariableInClassChain(?accessor,?class), methodWithNameInClass(?method,?accessor,?class), instanceVariableInClassChain(?accessor,?class), returnStatement(?method,variable(?var)), instanceVariableInClassChain(?accessor,?class), returnStatement(?method,variable(?var)), reception(?joinpoint,?accessor,?args), returnStatement(?method,variable(?var)), reception(?joinpoint,?accessor,?args), withinClass(?joinpoint,?class) reception(?joinpoint,?accessor,?args), withinClass(?joinpoint,?class) withinClass(?joinpoint,?class) 9
  • Problem Analysis Base program developer Aspect developer Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code 10
  • Problem Analysis Base program developer Aspect developer Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code Tight coupling 10
  • Problem Analysis Base program developer Aspect developer Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code Tight coupling Complex 10
  • Problem Analysis Base program developer Aspect developer Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code Tight coupling Complex Fragile 10
  • Application-specific Base program developer Aspect developer Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code 11
  • Application-specific Base program developer Aspect developer Application-specific model Model-based pointcut (defined in terms of application-specific model) Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code 11
  • Application-specific Base program developer Aspect developer Application-specific model Model-based pointcut (defined in terms of application-specific model) Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code Explicit Model 11
  • Application-specific Base program developer Aspect developer Application-specific model Model-based pointcut (defined in terms of application-specific model) Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code Explicit Expressed in terms of Model structure 11
  • Application-specific Base program developer Aspect developer des ui res Provi Application-specific model Req Model-based pointcut (defined in terms of application-specific model) Class Name Class Class Attributes Name Name Attributes Attributes Attributes Attributes Operations Operations Operations Attributes Operations Source code based Operations 1 1 1 Operations pointcut * Class * Class * (defined directly in terms Class Name Attributes Name Attributes Name Attributes of source code) Attributes Attributes Attributes Operations Operations Operations Operations Operations Operations Source code Explicit Expressed in terms of Contract Model structure 11
  • Application-specific pointcuts in AspectSOUL Logic Pointcuts Application-specific model Extensible pointcut language Keep in sync with code Logic representation specialisation parameters & unification 12
  • Application-specific pointcuts in AspectSOUL Logic Pointcuts Application-specific model Extensible pointcut language Keep in sync with code Logic representation specialisation parameters & unification 12
  • Application-specific pointcuts in AspectSOUL Logic Pointcuts Application-specific model Extensible pointcut language Keep in sync with code Logic representation specialisation parameters & unification Managing the Evolution of Aspect-Oriented Software with Model-based Pointcuts Andy Kellens, Kim Mens, Johan Brichau, Kris Gybels In "Proceedings of the 20th European Conference on Object-Oriented Programming (ECOOP)", 2006 12
  • Accessors Person>>name ^name Source Person>>name: anObject name := anObject Pointcut Model 13
  • Accessors Person>>name ^name Source Person>>name: anObject name := anObject Synchronization Pointcut reception(?joinpoint,?selector,?args), accessor(?class,?selector,?var), withinClass(?joinpoint,?class) Model 13
  • Accessors Person>>name ^name Source Person>>name: anObject name := anObject Synchronization Pointcut reception(?joinpoint,?selector,?args), accessor(?class,?selector,?var), withinClass(?joinpoint,?class) accessor(?class,?method,?varname) if class(?class), instanceVariableInClassChain(?varName,?class), methodWithNameInClass(?method,?varName,?class), Model methodInProtocol(?method,accessing), accessorForm(?method,?varname) accessorForm(?method,?var) if returnStatement(?method,variable(?var)) 13
  • Model specialisation Person>>name ^name Source Person>>name: anObject name := anObject Pointcut Model 14
  • Model specialisation Person>>name Person>>friends ^name ^friends isNil Source ifTrue:[friends := Set new] Person>>name: anObject ifFalse:[friends] name := anObject Pointcut Model 14
  • Model specialisation Person>>name Person>>friends ^name ^friends isNil Source ifTrue:[friends := Set new] Person>>name: anObject ifFalse:[friends] name := anObject Synchronization Pointcut reception(?joinpoint,?selector,?args), accessor(?class,?selector,?var), withinClass(?joinpoint,?class) Model 14
  • Model specialisation Person>>name Person>>friends ^name ^friends isNil Source ifTrue:[friends := Set new] Person>>name: anObject ifFalse:[friends] name := anObject Synchronization Pointcut reception(?joinpoint,?selector,?args), accessor(?class,?selector,?var), withinClass(?joinpoint,?class) accessor(?class,?method,?varname) if ... accessorForm(?method,?var) if returnStatement(?method,send(?var)) Model accessorForm(?method,?var) if returnStatement(?method,send(?check),<?true,?false>), nilCheckStatement(?check), statementsOfBlock(assign(?var,?varinit),?true), statementsOfBlock(<?var>,?false) 14
  • Parameters & Unification 15
  • Parameters & Unification Synchronization reception(?joinpoint,?selector,?args), accessor(?class,?selector,?var), withinClass(?joinpoint,?class) 15
  • Parameters & Unification Synchronization reception(?joinpoint,?selector,?args), accessor(?class,?selector,?var), withinClass(?joinpoint,?class) Synchronization reception(?joinpoint,?selector,?args), accessor(Array,at:put:,?var), withinClass(?joinpoint,?class) 15
  • Parameters & Unification Synchronization reception(?joinpoint,?selector,?args), accessor(?class,?selector,?var), withinClass(?joinpoint,?class) Synchronization reception(?joinpoint,?selector,?args), accessor(Array,at:put:,?var), withinClass(?joinpoint,?class) Synchronization reception(?joinpoint,?selector,?args), accessor(?class,?selector,address), withinClass(?joinpoint,?class) 15
  • Drag & Drop Drop Start Drag Over Drag Drag Ok DragDrop Manager Enter Drag 16
  • Drag & Drop Drop Start Drag dragOkMethod(?class,?sel,?component) dragEnterMethod(?class,?sel,?component) dragSource(?dragdropmanager,?source) Over Drag Drag Ok draggedObject(?dragdropmanager,?object) DragDrop Manager Enter Drag 16
  • Drag & Drop Drop Start Drag dragOkMethod(?class,?sel,?component) dragEnterMethod(?class,?sel,?component) dragSource(?dragdropmanager,?source) Over Drag Drag Ok draggedObject(?dragdropmanager,?object) DragDrop Manager Enter Drag reception(?jp,?sel,?args), dragEnterMethod(?class,?sel,?component), equals(?args,<?dragdropmanager>), dragSource(?dragdropmanager,?source), instanceOf(?source,FigureManager), draggedObject(?dragdropmanager,?object), instanceOf(?object,Line) 16
  • Refactoring transform Refactoring preconditions ... ... ... 17
  • Refactoring transform Refactoring transformMethod(?class,?sel,?refactoring) preconditions ... preconditions(?refactoring,?preconditions) refactoring(?refactoring,?class,?method) ... ... 17
  • Refactoring transform Refactoring transformMethod(?class,?sel,?refactoring) preconditions ... preconditions(?refactoring,?preconditions) refactoring(?refactoring,?class,?method) ... affected entities 17
  • Refactoring transform Refactoring transformMethod(?class,?sel,?refactoring) preconditions ... preconditions(?refactoring,?preconditions) refactoring(?refactoring,?class,?method) ... affected entities affectedEntity(?ref,[PushUpMethod],?input,?entity) if originalClassOfPushUpMethod(?input,?entity) affectedEntity(?ref,[PushUpMethod],?input,?entity) if originalClassOfPushUpMethod(?input,?class), superclassOf(entity,?class) 17
  • Summary AspectS + Carma = AspectSOUL Pointcut in terms of application-specific model Extensible pointcut language Logic language to express model Further integration of AspectS/Carma Integration with support for fragile pointcuts 18
  • Questions More information: ? http://prog.vub.ac.be/carma/ 19