Today I did something I have only ever done once before. I used the goto statement in C#.
In batch files I used goto all the time. For those who don’t know, LANDesk Management Suite supports batch file distribution packages and I became an expert at scripting with batch files. Of course, as a batch file scripting expert, I am very good at using the goto statement, but honestly using it in C# is generally frowned upon. I am sure there are other poeple like me that have used a language where goto is popular and can recognize uses for it when they crop up.
Anyway, I needed to start, stop, or restart a windows service and I need to perform the actions asynchronously in the background. Everytime I tried to create three methods, a Start, Stop, and Restart, the code grew in size and there was lots of duplication. So I kept going back to a single method that takes an action of start, stop, restart.
Since I wanted to run the action in the background, I created a ServiceWorker that inherits from BackgroundWorker and has an Action property (for Stop, Start, Restart) and here is the method I used.
private void StartOrStopService(object sender, DoWorkEventArgs doWorkEventArgs)
{
ServiceWorker worker = sender as ServiceWorker;
if (worker != null)
{
restart:
switch (worker.Action)
{
case "Start":
Log.WriteLine("Attempting to start service: " + worker.ServiceController.DisplayName);
worker.ServiceController.Start();
worker.ServiceController.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(30000));
break;
case "Restart":
case "Stop":
worker.ServiceController.Stop();
worker.ServiceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(30000));
if (worker.Action == "Restart")
{
worker.Action = "Start";
goto restart;
}
break;
default:
return;
}
}
}
I of course have other options, but if I break this method out into more methods, it is actually more code. For example, if I make Start and Stop methods,
We need a standard that adds a requirement to inform the user of how their data, especially their password, is stored in a database.
Most data is commonly stored in plain text. The only data that is usually not in plain text is the password, which is often stored using a cryptographic hash. However, plenty of systems store the password in plain text as well.
Imagine filling out a registration form with a username and password and some peronal data and clicking submit. What if the submit process had a confirmation screen that told how your information is stored in the database. For example, a site might say that the password is stored in plain text with a little “what does this mean” link and you are asked “Are these security needs sufficient?”.
If such a pop-up were required a number of things might happen:
The individual registering may choose not to use a site with such blatant disregard for security.
The individual registering may choose to use the site anyway but…
Use a password that they isn’t used for more secure sites.
Not enter all the information (for example, if a site is not trusted I often put just my initials for first and last name.
Use all false information
Almost no site provides the security information of how data is stored. Because of this, we need a personal data storage standard. Think of your personal data as related to healthcare where standards such as HIPAA already exists and already have security requirements. However, we need a standard that is more general. This is not and RFC or IEEE standard. It is more of an ISOC standard. I would say a government standard would work, however, the internet is fairly global and so it would a multi-government standard.
Digital Information Security Act (DISA)
We need a Digital Information Security Act (DISA). DISA would have rules and regulations and companies over time would start to comply. Just as we have well-known cryptographic algorithms, we would soon have well-known secure data storage methods.
(For a laugh: I first thought to call it the Personal Information Security Standard, but that acronym wasn’t very good.)
I was not surprised that British Columbia has a Personal Information Protection Act already but it hardly addresses the security of digital storage of personal data. However, it is more about how personal information is used, not about how it is securely stored in a database. I saw many privacy acts that have been implemented by various governments. However, most are in desperate need of an update adding rules from the digital perspective.
I want to focus on a rule about passwords that DISA should have.
Problems
Your personal data is your own. There are number of security issues if you lose your personal data. Your personal data includes any data that is connected to you. We are going to talk about two types of data here.
1. Your real identity
Your personal information is not really changeable. Your name is your name. Sure you could have a name legally changed, but aside from that, your name is static. Your address and phone number are usually static but changeable over time.
2. Your online identity
This usually means your user name(s) and password(s), which are completely different from your real identity. Your online identity is dynamic and you can have many of them and use different ones on different sites. You can usually change them at any time.
Security Issues
Example Issue 1 – Identity theft
With enough of your personal information a person can pretend to be you. Steeling your identity to use it fo fraud, slander, theft, and much more. Sensitive personal data, such as driver’s license, SSN, and identifiers should remain protected and secure.
There are many security issues, let me give a couple of examples, but there are many more.
Example Issue 2 – Security of your passwords
Since your username is not exactly secure and is easy to get, your password must be secure. Most people use passwords for multiple sites. Many sites now support authentication using a connection to another site such as OpenId, Yahoo, Google, Facebook, twitter, etc. If you password to one site is found, it is very likely that your password can be used on multiple sites.
Could you imagine someone obtained a password and you also use that password for you bank account. Yes, they could empty your account and the money could be gone and untraceable before you know it.
How your password is stored in a database is extremely important. If the password is in clear text or stored using an easily cracked hash, then your security risk is high.
First, the technology administrators such as the database administrators and others would already know and have access to your password. We usually trust “admins” and usually our data is not used in an incorrect manner, but that is not always the case, and you are vulnerable.
Second, if the database was stolen then your password is now in the hands of someone who does intend to use it maliciously.
Example Issue 3 – The real identity to online identity map
Your real data is easy to get. Knowing your first and last name is almost a non-existent security concern. Such information is in the phone books (or online phone books such as DexOnline) and in your year books and spread around records all over the world. Very few people care to secure their first and last names.
Your username is not really secure either. Usually sites provide any member the rights to see the user names of other members.
However, the connection between a real identity and online identity is a security concern. Should “just anybody” know that bob123 is Bob Robertson? No they shouldn’t. Why? Because if someone wants to target Bob Robertson, they should not easily know that they bob123 is their target.
Lets look at a real identity to online identity map.
Real Identity
Sites
Online Identity
Encrypted
Bob Robertson
twitter.com
user: bob123 pw: passwd123
yes
facebook.com
user: bob123 pw: passwd123
yes
google.com
user: bob123 pw: passwd123
yes
yahoo.com
user: bob123 pw: passwd123
yes
Forum123.tld
user: bob123 pw: passwd123
no
ABCBank.tld
user: bob123 pw: passwd123
yes
For now, let’s ignore the fact that Bob made a crucial mistake of using the same username and password for his bank because a large number of the population does this. Instead, lets focus on the result of losing your password for any accounts above.
Scenario
This is an example of scenario that describes issue 1 and issue 2. Lets say cyber thief plans to steal money from Bob’s bank account. How secure is Bob’s account with ABCBank. ABCBank surely has some great security. Unfortunately, Bob’s account is only as secure as the least secure site for which Bob has use the same account. Because the cyber thief knows that Bob Robertson is bob123, the thief now has half the information needed to get into Bob’s bank account. Next the thief can first finds all the sites where the username bob123 exists and assume that they are Bob Robertson. Then the thief can try to compromise the password at the easiest site. In the above case, the easy site to compromise is forum123.tld. The thief successfully determine’s Bob’s password at Forum123 and tries the password on a number of banks that have a brick and mortar building near Bob’s house. ABCBank is one of them and the credentials work.
At this point there are any number of ways that money can be stolen from Bob’s bank account. Of course, no one should ever have the same username and password for their bank accounts as they do for everything else. There are actually three clear security levels and a user should have a different password at each level.
twitter.com
medium
facebook.com
medium
google.com
medium
yahoo.com
medium
Forum123.tld
low
ABCBank.com
High
However, let’s say Bob is not very computer literate and doesn’t even know that he should have different user names and passwords at each security level. Shouldn’t each site at least tell the user their security level and suggest to the user that they don’t use the same username and password for site with different levels of security?
Now how can we help solve some of these issue with our new DISA standard?
DISA Rule #1 – Disclose your security level
Now, imagine when Bob registered for Forum123.tld, he got a popup as follows:
This site stores the password in clear text and implements little to no security. It is not recommended that you use the same password on this site as you do for more secure sites (such as bank accounts). Would you like to continue or would like you like to use a different password?
[ Continue ] [ Use a different password ]
Were this popup to become a standard and were it implemented on almost every site, this popup would help a large portion of the population improve their username and password security issues because they would know whether their password is encrypted or not.
However, it would likely also improve the sites security because a web site administrator would work to use an well-known authentication library to become DISA compliant and because they now use a well-known authentication library, they will have access to its additional security features such as cartographic hashing of passwords and the site would likely become more secure as well.
Implementation and Enforcement
So lets say we created DISA and we created this password security disclosure rule. How could we enforce it?
Enforcement by Business Entities
Security conscious entities are already enforcing security standards such as Payment Card Industry (PCI) compliance rules for taking credit cards. Banks and credit card vendors have security requirements you must meet before they allow you to use your merchant account to take credit cards online.
However, this is not the focus of where it should be enforced. It should be enforced most on the small sites that are not very secure.
Enforcement by the Government
This is probably not a good solution. So many small one person blogs and other sites pop up each day it would be impossible for a government entity to monitor and enforce this.
Enforcement by Browsers
This is actually the perfect place to enforce this. Almost all browsers can detect when you are filling out a registration form that includes a password. The browser could intercept the submit and perform the popup using a combination of information, some hard-coded in the browser (so websites can’t fool the user) and some gather from the web site itself. I
Conclusion
How a digital information, especially a password, is a huge security concern and standards and well-known practices should exist to help both the security minded as well as the uneducated to maintain a higher state of security.
It is not always about who is better. Often an equal or better candidate loses for reasons that should not apply. This is true for many areas (politics for example) where what matters is overlooked by our humanity. So whether one operating system is technically better than the other is not the only factor for choosing it. Linux is the most used open source operating system and has a larger market share than FreeBSD (OS X not included). This article takes a look at some other reasons one might choose Linux over FreeBSD.
Note: This article also is not taking into account OS X, which while it has some foundations is BSD, is not open source, and this article is to discuss open source market share. Due to OS X, FreeBSD could make the claim that they have a larger market share than Linux.
Reason #1 Advertising
The bottom line to advertising is that Linux has it in quantities and FreeBSD doesn’t.
Advertising
For FreeBSD, there is very little, if any, advertising. I have never seen any ad on any media type for FreeBSD.
Linux has multiple enterprise size companies, Red Hat, SUSE (previously Novel), IBM, and others that are advertising it and using it. Linux is advertised by these companies quite heavily.
Buzz
There are a few user’s groups here and there and that is about it. FreeBSD has no little buzz marketing.
Linux has a lot of buzz. There is no questioning the buzz that was created by Ubuntu that still exists. Thanks to distros like Ubuntu, Linux has an extreme amount of buzz.
What is being done?
Over the past couple of years, iXSystems has provided an increase in advertising. Also the new BSD Magazine is another form of advertising that is beneficial.
Reason #2 – Brand name and Logo
A brand name has the ability to make or break an organization. A logo has this same ability. Why? Because they are the embodiment of the company. They provide the first impressions (don’t tell me you haven’t heard that saying about first impressions) and often the only impression.
And how it sounds is extremely important.
Think about it. Some people want to sound cool when they say the operating system they run.
“I run Linux!”
“I run FreeBSD!”
I have heard people say it many times: Linux as a word just sounds cooler than FreeBSD. Well, lets actually look at from a more scientific point of view than “just sounds cooler”. Let look at reasons
The linguistics of a brand name
Linguistic experts have studied brand names and there are many “best practices” for a brand name, and FreeBSD follows none of them. Because of this, FreeBSD is not a good brand name. It is not even average. In fact, if you were to make a list of below average brand name, FreeBSD would reside near the bottom of the bad list, and here is why.
The goal of a looking at a brand name from a linguistics point of view is to find ways to make the brand easy to say, descriptive, and memorable . A brand name is poetry and all the linguistic elements that benefit or distract from poetry can benefit or distract from a brand name. Here are ten linguistic suggestions for having a good brand name.
Use alliteration in your brand name.
Use equal or more harmonious consonants than cacophonous sounds. Some consonants make sounds that are “in-between” such as F. A letter such as X has two sounds, K and S.
Syllables. Two or three syllables is ideal. One doable too. Four is possible if other items in this list are good. Five syllables and above your pretty much a bad brand name.
Use the correct “foot“. Use disyllables such as pyrrhic, iamb, trochee, but avoid spondee; Use trisyllables such as anaepest, credic, dactyl but avoid molossus etc…
Avoid using acronyms.
Vowels should rhyme or match.
Avoid contrasting vowel sounds, such as a long vowel followed immediately by a short vowel.
The place of articulation of each consonant and transitions between them should be easy.
Use a word that can become a noun or verb.
Know definitions of roots, prefixes, and postfixes and use ones that apply to your business.
So lets compare FreeBSD brand to the Linux brand.
Winner
FreeBSD
Linux
Explanation
1
Tie
n/a
n/a
Neither alliterated.
2
Linux
Good
Bad
Linux has three consonants, but one is X which has two consonant sounds K and S. Sot it has, three harmonious, one cacophanous which is a 3-1 ratio.
FreeBSD has five consonants, two cacophonous, two harmonious, one in-between, which is a 2-2-1 ratio.
3
Linux
Good
Bad
Linux is idea having two syllables.
FreeBSD is four syllables and nothing to save it.
4
Linux
Good
Bad
Linux is a single pyrrhic foot.
FreeBSD has two feet and they are same foot, spondee, which is the one you should avoid.
5
Linux
Good
Bad
Linux avoided acronyms, FreeBSD, has a three-letter acronym.
6
Linux
Good
Average
Linux is two short vowels.
FreeBSD has four vowels, three long Es and one short E.
7
Linux
n/a
Bad
Linux has no vowels next to each other.
FreeBSD has a conflict of a long E followed by a short E between the B and S letters.
8
Linux
Good
Average
Linux has the L and N and S sounds all made by very the same mouth parts and positions, well separated by vowels.
FreeBSD has sounds made by various different places and parts in the mouth less easy transistions.
9
Linux
Average
Bad
Linux can be a noun, and I have heard linuxed used before.
FreeBSD is barely passable as a noun and can in no way be verabalized.
10
Tie
n/a
n/a
Linux has no syllables with any dictionary meaning.
FreeBSD has the word “free” which is too general to provide any meaning. The acronyms detracts from the mean further.
If we rated these on a scale of 0 to 5, with bad being 0, average being 3, and Good being 5, here is how the points come out.
FreeBSD = 2 points. Two item were N/A, so that is 2 out of 40 possible points or 5% of the possible Good points a brand could have.
Linux = 35 points. Three items were N/A, so that is 33 out of 35 possible points or 94% of the possible Good points a brand could have.
As you can see, from a linguistics point of view, FreeBSD is a terrible brand name. If FreeBSD were an enterprise trying to stay alive, the first order of business would be to change the brand name. Also, this analysis proves the obvious, that most of the bad branding stems from the acronym, BSD.
Derivative brand names
Derivatives of Linux, such as Red Hat, and Ubuntu have average or above average brand name as well. Red Hat is two simple words, though they unfortunately have no meaning for an open source operating system, but as brand name these words are simple and easy to say. Simple and easy. Ubuntu has meaning, three syllables, matching vowels, though it isn’t exactly easy to say with 2 cacophonous to only one harmonious consonant. Both of these
Unfortunately, the FreeBSD derivatives don’t get better. The main problem is that more than half of them feel the need to continue to use the BSD acronym in their brand. There reasoning is to show their ties to BSD, but the result is very bad brand names. For example, PC-BSD somehow took a step backward by extending to five syllables, still all accented, and adding one more cacophonous sound. There is no fixing the PC-BSD brand. The only option is a new brand. However, DragonFly BSD can easily be fixed by simply dropping the “BSD” acronym as it is not needed. Alone DragonFly is a good brand. Brands that have dropped the BSD acronym such as m0n0wall or pfSense are adequate brands, not good, not bad. OpenBSD is as bad as PC-BSD with the added negative that the word “open” actually contradicts the security goals of the platform.
As derivative brand names go, Linux derivatives or distros are far ahead of FreeBSD derivatives in brand name quality.
The art of a logo
The logo is every bit as important as the brand name. Lets look at the FreeBSD logo, and the Red Hat logo and compare them.
Here are some logo tips that seemed to be common themes from dozens of sites about tips for making a good logo.
Keep it simple.
Make it memorable.
Make sure colors coordinate.
Make sure the logo has a black and white version.
Color psychology. Avoid having the logo be mostly one color that may be negative.
Don’t stray far from a simply decorated version of the company name.
Make the logo an image that is pertinent to the brand.
Avoid offensive images, even if only offensive to a small portion of the population.
One might argue that the Tux, the penguin, and Beastie, the devil or demon, are both part logo and part mascot so we will look at those, first.
Winner
Linux
FreeBSD
Explanation
1
Tie
Bad
Bad
Neither the penguin or Beastie are simple logos.
2
Tie
Average
Average
Both are memorable
3
Tie
Good
Good
Both have colors that coordinate fine.
4
Linux
Good
Average
The penguin translates well to black and white.
Beastie is displayed as an outline.
5
Tie
Average
Average
Tux is black, white, and yellow. Nothing great.
Beastie is red mostly.
6
Tie
bad
Bad
Both stray from the brand name, probably
because they are more mascots than logos.
7
Tie
bad
Bad
Neither is pertinent to the brand.
8
Linux
Good
Bad
The penguin is nice and cute.
Beastie is a devil and controversially offensive. The reference to daemons and forks is lost on most people.
Ok, so neither mascot makes a good logo, but Tux does have a small edge over Beastie. Now lets look at the logos. I am going to use the Red Hat logo versus the FreeBSD logo, as Linux doesn’t exactly have its own logo.
Winner
Linux
FreeBSD
Explanation
1
Linux
Average
Bad
Red Hat is two colors and is a complex drawing.
FreeBSD is a 3d sphere, it is more than two colors, red and black, as it has many different shades of red.
2
Tie
Average
Average
Both are equally memorable
3
Tie
Good
Good
Both are very well color cordinated.
4
Tie
Bad
Bad
The color red makes both logos. Neither look as good in black and white only.
5
Tie
Average
Average
Both have red and black. Not much difference.
6
Tie
Average
Average
Both are an image to the left of the brand name.
7
Linux
Good
Bad
Red Hat has a logo of a guy in a Red Hat, not pertanent to Linux but very pretinent to the brand.
FreeBSD has sphere with horns, and the relationship to a daemon is a stretch at best.
8
Linux
Good
Bad
The Red Hat logo is a simple image, nothing offensive.
The devil horns comes with tons of religious history and is offensive to certain individuals, even toned down as a sphere with horns.
Using the same point system, 0, 3, 5 for Bad, Average, Good…
Linux gets 27 out of 40 possible points, or 67.5%.
FreeBSD gets 14 of a 40 points, or 35%.
After analyzing this, the FreeBSD logo isn’t as good overall as the Red Hat logo using the measurement above. However, I wouldn’t say the Red Hat logo is great either. I do think that just from a “looks and coolness” despite the rating system, the new BSD logo looks better.
What is being done?
FreeBSD recently updated the logo to the one you see above. There are no plans to improve the name, logo, or brand further that I know of.
Reason #3 – Licensing
Business and enterprise drive use. In my experience, business leaders equate open source software with the GPL license. I have heard so many companies say that they have banned open source software. However, every business leader I have educated in the different open sources licenses change the ban to allow BSD and similar licensed, citing that they didn’t understand the different licenses or the business and enterprise friendliness of the BSD and similar licenses.
Both the FreeBSD license and the GPL are great licenses. However, they have a slight different focus. FreeBSD is a license designed to share code freely. GPL is also a license to share the code freely with the added enforcement that any code that uses GPL code is also GPL.
If you distribute binaries built using BSD Licensed source, there are only two things you shouldn’t do (you wouldn’t do either anyway).
If you distribute binaries built using GPL source, you have to pay attention. 1) your code may also be required to use the GPL license and 2) there are actions you must perform, such as provide access to the source and your source that uses the GPL source.
Businesses and enterprises often don’t understand that there are alternate licenses beyond GPL. Sometimes they actually prefer to buy commercial software just to avoid “open source”. We need to share how enterprise friendly the BSD license is with IT managers and business decisions makers.
I have seen this from personal experience. At a previous company, they mistakenly used GPL software and other software thinking it was free, forgetting that they actually have to perform actions in order to use this software. It cost them a lot of money when they were found out. The sad part is there was alternate software available that was BSD Licensed, so they wasted money because neither the developers nor the business leader knew better. I knew better and they were quite shocked when I gave them a simple solution: Just use this alternate software as it is BSD Licensed. They did and it saved them a lot of money.
Even though I put licensing as the third reason, after thinking about it, this comes back to Reason #1 – Advertising again, because the main problem is that the GPL seems to be advertised more and many business leader are unaware of other open source licenses.
What is being done?
I think nothing is being done. I am not sure if there is any effort to advertise the benefits of the FreeBSD’s permissive licensing over other more restrictive licenses.
Reason #4 – A law suit early on
This was before my time, but I always hear that around the time Linux and BSD were released, BSD was sued and so people shied away from BSD because the threat of a law suit. This occurred well before I cared and if you want to read more about it, check out the wikipedia artcle.
I can’t prove that BSD was slowed by this, or that Linux wouldn’t have the same advantage in market share over BSD had this occurred. But every time I see a question about why FreeBSD is not more popular someone brings this up.
However, when Linux was sued by SCO, it didn’t really affect the market, so I am not sure if this was really valid or not. It is a historical possibility at best.
Reason #5 – Company backing
We know that in the early days of Linux there were multiple business who backed Linux. Then Red Hat and SUSE went enterprise. Ubuntu has Canonical.
For FreeBSD, Apple took it into their product but not as open source, and they didn’t really advertise the fact that they were partially BSD. iXSystems and some hosting companies are about all that FreeBSD has when it comes to an business.
What is being done?
Well, FreeBSD is continuing to get backing from Apple. I have heard rumors that Apple is one of the primary sponsors of Clang and LLVM (tools to replace gcc as a compiler) that uses a permissive license.
iXSystems kept FreeNAS a FreeBSD product by sponsoring it and has sponsored many booths at open source conferences.
I have heard of Yahoo being a strong backer of FreeBSD, though I am not sure of any recent examples. But it is clear that FreeBSD needs more business backing if it plans to compete in the open source market with Linux.
Suppose you are tasked with adding logging to trace when a method starts and when it ends. Now suppose that you are tasked to do this for every method in a project, lets say you have to do this for 1,000 methods scattered throughout all your objects. Every method included would have two lines of logging code, one at the start, one at the end. That means you have to add two lines of code per method or 2,000 lines of code. Sure, you could extract the logging methods into a static or singleton making it “easier”, but in the end, you still end up with 2,000 lines of code, two per method.
Is adding 2,000 lines of code the right solution? No it is not. These lines of code can be distracting and can make a method less readable. A single line method becomes three lines. Your class files get bigger, especially if they are method heavy. Also, these lines of code break the SOLID principles in that 1) you are repeating yourself, and 2) your method no longer has a single responsibility as it is doing what it was design for and it is doing tracing, etc. It doesn’t have to be this way.
AOP can allow you to do the same task but have the code in a single place. Including spaces and brackets, the C# MethodTracingAspect file is only 36 lines of code and to implement this into all methods in a namespace an AspectInfo.cs file is used with only three lines of code.
Which would you rather deal with: 39 lines of code in two class files, or 2,000 lines of code spread throughout ever class file?
This document assumes you have the done the following already:
Installed Visual Studio
Installed PostSharp
Licensed PostSharp
Note: While PostSharp has a free version, my examples will likely require the licensed version.
Step 1 – Create a new C# project for Aspects
In Visual Studio, choose File | New | Project.
Choose a Visual C# Console Application.
Give the project a Name.
Note: I named my project AspectExamples
Click Ok.
Your project is now created.
Step 2 – Add a reference to PostSharp
In Solution Explorer, right-click on your new project and choose Add Reference.
In the Add Reference window, click to select the .NET tab.
Locate PostSharp and click to highlight it.
Click Ok.
You have now added PostSharp as a reference to your project.
Step 3 – Create an Aspect for method tracing
Right-click on your project and choose Add | Class.
Give the class a Name.
Note: I named my version of this class MethodTraceAspect.
Add a using reference to the PostSharp.Aspects namespace.
Make the object inherit from OnMethodBoundaryAspect.
Override the OnEntry method.
Override the OnExit method.
Add code to each method for logging to the Output window using Debug.WriteLine().
Note: Obviously, you can use any logging library you software may use.
Add code to make sure that methods inside methods are properly tabbed.
Here is my final class file.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using PostSharp.Aspects;
namespace AspectsExamples
{
[Serializable]
public class MethodTraceAspect : OnMethodBoundaryAspect
{
private static int _TabCount = 0;
private static Stack<long> _StartTimeStack = new Stack<long>();
public override void OnEntry(MethodExecutionArgs args)
{
Debug.WriteLine(GetTabs() + "Method started: " + args.Method.Name);
_TabCount++;
}
public override void OnExit(MethodExecutionArgs args)
{
_TabCount--;
Debug.WriteLine(GetTabs() + "Method completed:" + args.Method.Name);
}
private static String GetTabs()
{
string tabs = string.Empty;
for (int i = 0; i < _TabCount; i++)
{
tabs += "\t";
}
return tabs;
}
}
}
You now have a modular Aspect that you can use to add method start, method end logging to any method in any C# project.
Step 4 – Implement the Aspect for method tracing
Implementing the Aspect for method tracing is accomplished by using an Attribute. The attribute can be added to a single method, a class, or a namespace.
We will use the following Program.cs file will demonstrate this.
using System;
namespace AspectExamples
{
class Program
{
static void Main(string[] args)
{
HelloWordMethod();
}
private static void HelloWordMethod()
{
Console.WriteLine("Hello, World!");
}
}
}
Option 1 – Adding the Aspect to methods
When adding this to method, you have to add it for each method.
Add the MethodTraceAspect to the Main method.
Add the MethodTraceAspect to the HelloWordMethod.
using System;
namespace AspectExamples
{
class Program
{
[MethodTraceAspect]
static void Main(string[] args)
{
HelloWordMethod();
}
[MethodTraceAspect]
private static void HelloWordMethod()
{
Console.WriteLine("Hello, World!");
}
}
}
Ok, lets test this.
Click Debug | Start Debugging to run the application in debug mode.
Look at the Output and you should see the following lines.
Method started: Main
Method started: HelloWordMethod
Method completed:HelloWordMethod
Method completed:Main
Option 2 – Adding the Aspect to classes
When adding this to a class, you don’t have to add it for each method in the class.
Add the MethodTraceAspect to the Program class.
using System;
namespace AspectExamples
{
[MethodTraceAspect]
class Program
{
static void Main(string[] args)
{
HelloWordMethod();
}
private static void HelloWordMethod()
{
Console.WriteLine("Hello, World!");
}
}
}
Ok, lets test this.
Click Debug | Start Debugging to run the application in debug mode.
Look at the Output and you should see the following lines.
Method started: Main
Method started: HelloWordMethod
Method completed:HelloWordMethod
Method completed:Main
Option 3 – Adding the Aspect to a namespace
When adding this to a namepsace, you don’t have to add it for each class or every method in each class. Instead it is automatically added to every method in every class in the namespace.
Add the MethodTraceAspect to the namespace.
Note: Notice the syntax is slight different for adding to a namespace than for a class or method.
using System;
[assembly: MethodTraceAspect]
namespace AspectExamples
{
class Program
{
static void Main(string[] args)
{
HelloWordMethod();
}
private static void HelloWordMethod()
{
Console.WriteLine("Hello, World!");
}
}
}
Ok, lets test this.
Click Debug | Start Debugging to run the application in debug mode.
Look at the Output and you should see the following lines.
Method started: Main
Method started: HelloWordMethod
Method completed:HelloWordMethod
Method completed:Main
Note: For real projects that aren’t just examples, it is a good idea to implement Aspects to a namespace in a separate file, such as an AspectInfo.cs file.
using Common.Aspects;
[assembly: MethodTraceAspect]
namespace AspectExamples {}
Congratulations, you have implemented an Aspect in C# using PostSharp.
The example code below assumes you have a simple database called ExampleDB, with one table called Person that has an Id (Primary Key and auto increments), a FirstName, and a LastName column.
Further information is in the comments in the sample code below.
using System.Data;
using System.Data.SqlClient;
namespace SQLExamples
{
public class Program
{
static void Main(string[] args)
{
// Step 1 - Create the connection with a Connection string
// Create a connection builder
var connectionBuilder = new SqlConnectionStringBuilder();
connectionBuilder.IntegratedSecurity = true;
connectionBuilder.DataSource = "localhost";
connectionBuilder.InitialCatalog = "ExampleDB";
// Create a connection that uses the connection string
SqlConnection connection = new SqlConnection(connectionBuilder.ConnectionString);
// Step 2 - Open the Connection
connection.Open();
// Step 3 - Perform database tasks with the open connection (Examples provided...)
//
// Example 1 - Insert data with a query
//
// Create an insert query
string insertQuery = "Insert into Person (FirstName, LastName) Values ('Jared', 'Barneck')";
// Create an SqlCommand using the connection and the insert query
SqlCommand insertCommand = new SqlCommand() { Connection = connection, CommandText = insertQuery };
// Run the ExecuteNonQuery() method
int rowsAffected = insertCommand.ExecuteNonQuery();
//
// Example 2 - Select * from a table
//
// Create a String to hold the query.
string selectQuery = "SELECT * FROM Person";
// Create an SqlCommand using the connection and the insert query
SqlCommand selectCommand = new SqlCommand() { Connection = connection, CommandText = selectQuery };
// Use the above SqlCommand object to create a SqlDataReader object.
SqlDataReader queryCommandReader = selectCommand.ExecuteReader();
// Create a DataTable object to hold all the data returned by the query.
DataTable dataTable = new DataTable();
// Use the DataTable.Load(SqlDataReader) function to put the results of the query into a DataTable.
dataTable.Load(queryCommandReader);
//
// Example 3 - Insert many rows DataTable insert
//
// Add to the DataTable from example 2
DataRow row1 = dataTable.NewRow();
row1["FirstName"] = "John";
row1["LastName"] = "Johnson";
dataTable.Rows.Add(row1);
DataRow row2 = dataTable.NewRow();
row2["FirstName"] = "Jenni";
row2["LastName"] = "Jenson";
dataTable.Rows.Add(row2);
string adapterInsertQuery = "Insert into Person (FirstName, LastName) Values (@FirstName, @LastName)";
SqlCommand adapterInsertCommand = new SqlCommand() { Connection = connection, CommandText = adapterInsertQuery };
adapterInsertCommand.Parameters.Add("@FirstName", SqlDbType.NVarChar, 255, "FirstName");
adapterInsertCommand.Parameters.Add("@LastName", SqlDbType.NVarChar, 255, "LastName");
SqlDataAdapter adapter = new SqlDataAdapter(selectCommand);
adapter.InsertCommand = adapterInsertCommand;
adapter.Update(dataTable);
// Step 4 - Close the connection
connection.Close();
}
}
}
You show now have a good starting point for using ADO.NET to manipulate a Database.
I wanted to continue with the C# (Mono) on FreeBSD theme this week. The next C# (Mono) post for FreeBSD is simply running a .C# (Mono) app on FreeBSD. My first thought was this, “I wonder if there is a mono version of Paint.NET?”. Paint.NET is my favorite image editor for Windows. After a quick search, I found the Pintaproject, which is a Mono clone of Paint.NET.
Installing Pinta on FreeBSD
So anyway, the steps for running on FreeBSD are quite simple. This is a preview of my next FreeBSD Friday post, as I will continue the mono them to promote you app.
I have used Camtasia Studio by TechSmith on a number of occasions and I thoroughly enjoy their desktop recording software. Since I like Camtasia Studio so much, I thought I would write a couple of articles on using their software. Since I wanted to write a quick article about them, I contacted them and asked if they would let me host a give away for a free copy of Camtasia Studio right here on my blog. I was totally happy when they said yes.
For details on entering the give-away, see The Give-Away below.
So my blog is not so much about promoting a product as providing instructions for how to do something, so of course, this is going to be a “how to” article. So here is how easy it is to record a video.
Sometimes you want to record something on your desktop. For a blogger like myself, I want to record how something hard is done on a computer. I have int the past used VMWare’s recording feature but it doesn’t record sound. I want both sound and video.
Even though I am geek and a developer and I don’t mind compiling some open source tool from scratch, I am also a fan of quality technology that just works. For recording my desktop or any application with video and sound, Camtasia Studio studio just works. While it is not open source, Camtasia Studio is well worth the license fee for me.
About Camtasia Studio
Let’s talk about Camtasia Studio. Camtasia Studio has a single installer, but like many products it is more of a suite or “studio” of feature.
There are five features installed:
Camtasia Studio
Camtasia MenuMaker
Camtasia Player
Camtasia Recorder
Camtasia Theater
I have mostly used the Recorder and Camtasia Studio.
Easy posting to YouTube or ScreenCast
Camtasia Studio makes uploading a video to YouTube or ScreenCast easy. All you need is your username and password and Camtasia Studio does the work for you.
It automatically opens your browser and takes you to the link to your online video.
The Give-Away
So Camtasia Studio is giving away a free License.
Mac or Windows? They have a version for Windows and Mac and so the winner can choose which license they want.
Version: Yes, we will be giving away the new version of Camtasia Studio.
Start date: Friday, June 1, 2012.
End date: Monday, July 2, 2012.
Here is how you can enter to win it.
Step 1
Like Camtasia Studio on Facebook. Just click the image as it is a link.
Step 2
Enter your email address. Yes, I will need your email address to contact you if you win!
Your done!
That is it. You are now entered into the give-away.
Commercial apps. Like it or not the best apps, from MS Office, Adobe Creative Suite, and thousands more, exist only for Windows and most cross-platform apps just mean Windows and Mac.
Internal custom apps are almost all written for Windows only. And when they are web apps they often use SharePoint with IE only features.
Lack of enterprise product support for any operating system but Windows.
Rapid desktop application development on Windows with Visual Studio is orders of magnitude faster than on Linux with its best IDE, which is arguably Eclipse.
Infrastructure
Most existing desktop operating systems are already Windows.
Desktop Management solutions that Enterprise IT departments use to manage their workstations only manage Windows or if they manage multiple operating systems, they manage Windows the best.
Existing infrastructure (such as phone systems, etc…) integrate with Windows but not with Linux.
Employees
Existing Full-time employees (FTE) in IT are skilled in Windows and employee replacement or training costs are high.
The cost of Linux FTE in IT is higher than Windows FTE in IT.
Advertising
Most companies start small and grow to be an enterprise. When most companies are started, they are started by people who have never heard of or seen Linux.
Will this change in the future?
Maybe. Change is possible but it takes a lot of time and I don’t mean just years, I mean decades. And during these decades every OS vendor is going to fight to gain a monopoly in the enterprise desktop world.
If it does happen, the changes are for the following reasons.
To better support mobile devices such as iOS and Android (which is sort of Linux)
As more applications become browser apps or cloud apps that work in any browser.
Cross platform development tools, such as Mono and Java and AIR are really improving.
For those who are pro-Linux because it is open source and you believe knowledge belongs to the world, the enterprise doesn’t care. This argument is completely irrelevant from an enterprise perspective. I care, though, if that makes you feel any better (though I am a person not an Enterprise).
What if a Startup uses an Open Source Operating System
Well, look at the 10 items above and you will see you can eliminate 2, 5, 7, 8, and 10. Half the reasons are eliminated by starting with an Open Source OS. However, on the other hand, half the reasons still exist.
You may want to implement role-based security, where you only allow users assigned a certain role to perform certain actions in an application. Many different classes in your code will need role-based security added to them. As it turns out, role-based security is a cross-cutting concern. Well, Aspect Oriented Programming (AOP) can help you modular such a role-based security structure.
Lets start with an example. Maybe you have a database filled with people (people being a list of user or person objects). You want to control the list of people. Now think of the Create, Read, Update, Delete (CRUD) pattern. Now turn those into four permissions. Any role could potentially have or not have rights to create a person, read a person’s info, update a person’s info, or delete a person. An admin user would likely have all of the four CRUD rights. A user would likely have CRUD rights for their own user, but just read rights for other users. Your design might have multiple levels of rights as well. You may want to provide multiple levels of read permissions. Think of any social network where you have more read rights if you are a friend of another Person.
If it was just for a Person object, you probably would implement an AOP-based solution. However, a large application will have dozens of classes around the Person class. It will have many entities besides Person and those entities have many surrounding data classes as well. What if you had to add code to over 100 class objects? Now you can really benefit from an AOP-based design.
Well, I am going to show you example to help get you started.
Lets say you want to encrypt a field of a class. You might think that this is not a crosscutting concern, but it is. What if throughout and entire solution you need to encrypt random fields in many of your classes. Adding encryption to each of the classes can be a significant burden and breaks the “single responsibility principle” by having many classes implementing encryption. Of course, a static method or a single might be used to help, but even with that, code is must be added to each class. With Aspect Oriented Programming, this encryption could happen in one Aspect file, and be nice and modular.
Prereqs
This example assumes you have a development environment installed with at least the following:
JDK
AspectJ
Eclipse (Netbeans would work too)
Step 1 – Create an AspectJ project
In Eclipse, choose File | New | Project.
Select AspectJ | AspectJ Project.
Click Next.
Name your project.
Note: I named my project AOPRolePermissions
Click Finish.
The project is now created.
Step 2 – Create a class containing main()
Right-click on the project in Package Explorer and choose New | Class.
Provide a package name.
Note: I named my package the same as the project name.
Give the class a name.
Note: I often name my class Main.
Check the box to include a public static void main(String[] args) method.
Click Finish.
package AOPRolePermissions;
public class Main
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
}
}
Step 3 – Create an object that needs Role-based security
For this example, I am going to use a simple Person object.
Right-click on the package in Package Explorer and choose New | Class.
Note: The package should already be filled out for you.
Give the class a name.
Note: I named mine Person.
Click Finish.
Add String fields for FirstName and LastName.
Add a getter and setter for each.
package AOPRolePermissions;
public class Person
{
// First Name
private String FirstName = "";
public String getFirstName()
{
return FirstName;
}
public void setFirstName(String inFirstName)
{
FirstName = inFirstName;
}
// Last Name
private String LastName = "";
public String getLastName()
{
return LastName;
}
public void setLastName(String inLastName)
{
LastName = inLastName;
}
}
a
Step 4 – Implement example role-based code
For this I created the following objects:
Role
Permission
Permissions
FakeSession
The implementation of these is not important to this article, so I am not posting their code. However, you will see these classes if you download the project.
Step 5 – Implement an Annotation for Role-based Security
Lets add an annotation to mark methods that should use role-based security.
Right-click on the package in Package Explorer and choose New | Annotation.
Note: The package should already be filled out for you.
Give the annotation a name.
Note: I named mine RoleBasedSecurity.
Click Finish.
Add a value for the permission type.
Add a value for the Field name (in case the method is named completely different from the field).
Set the Retention to RetentionPolicy.RUNTIME.
Maybe add a comment that this annotation is for use by the Aspect (which we will create shortly).
Step 8 – Implement around advice to check for permissions
Add around advice that returns an Object.
Implement it to be for the RoleBasedSecurityMethod pointcut.
Add code to check for permissions.
Add a return statement.
package AOPRolePermissions;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
public aspect SecureByRoleAspect
{
pointcut RoleBasedSecurityMethod() : call(@RoleBasedSecurity * *(..))
&& !within(SecureByRoleAspect);
Object around() : RoleBasedSecurityMethod()
{
System.out.println("Checking permissions...");
RoleBasedSecurity rbs = getRBSAnnotation(thisJoinPointStaticPart);
// Use the FieldName if specified, otherwise guess it from the method name
String field = (rbs.FieldName().equals("")) ? removeLowerCasePrefix(thisJoinPointStaticPart
.getSignature().getName()) : rbs.FieldName();
if (FakeSession.Instance.getCurrentRole().GetPermissions()
.can(rbs.value(), field))
{
System.out.println(String.format(
"Success: Role has permissions to %s field named %s.%s.",
rbs.value(), thisJoinPointStaticPart.getSignature()
.getDeclaringType().getName(), field));
return proceed();
}
else
{
System.out
.println(String
.format("Failure: Role has insufficient permissions to %s field named %s.%s.",
rbs.value(), thisJoinPointStaticPart
.getSignature().getDeclaringType()
.getName(), field));
}
return null;
}
private String removeLowerCasePrefix(String inString)
{
int startPoint = 0;
for (int i = 0; i < inString.length(); i++)
{
if (Character.isUpperCase(inString.charAt(i)))
{
startPoint = i;
break;
}
}
return inString.substring(startPoint);
}
private RoleBasedSecurity getRBSAnnotation(JoinPoint.StaticPart inStaticPart)
{
RoleBasedSecurity rbs = null;
Signature sig = inStaticPart.getSignature();
if (sig instanceof MethodSignature)
{
// this must be a call or execution join point
Method method = ((MethodSignature) sig).getMethod();
rbs = method.getAnnotation(RoleBasedSecurity.class);
}
return rbs;
}
}
You are done. Go ahead and run the program. You should get the following output.
Checking permissions...
Success: Role has permissions to Update field named AOPRolePermissions.Person.FirstName.
Checking permissions...
Success: Role has permissions to Update field named AOPRolePermissions.Person.LastName.
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName.
John
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName.
Johnson
Checking permissions...
Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.FirstName.
Checking permissions...
Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.LastName.
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName.
John
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName.
Johnson
This is not a walk-thru. This is just an example AspectJ class.
Note: For logging, the log singleton which I previously posted is used, but of course you can hook this up to your own logging methods or just print to the console.
This class is intended to log when a method executes and when a method ends and include the time it took for a method to execute in nanoseconds. Methods inside methods are tabbed. This is an enhancement to this post: AOP – Logging all method calls and executions
I ran it multiple times and the executions times were sporadic. I remember reading somewhere that System.nanoTime() in java was not extremely accurate, but it is accurate enough for this example.
This is not a walk-thru. This is just an example AspectJ class.
Note: For logging, the log singleton which I previously posted is used, but of course you can hook this up to your own logging methods or just print to the console.
This class is intended to log when a method executes and when a method ends. Methods inside are tabbed.
This is a continuation of AOP – Encrypting with AspectJ. It is expected you have read (or skimmed) that article first. This article uses the same project. The files in the project so far are these:
Encrypt.java
EncryptFieldAspect.aj
FakeEncrypt.java
Main.java
Person.java
The final version of EncryptFieldAspect.aj in the previous article is not exactly a “good” Aspect. The problem with it is that it isn’t very reusable. There is a one to one relationship between this Aspect and the field it encrypts. We want a one to many relationship where one Aspect works for encrypting many fields.
Another problem is there is nothing in the objects that would inform a developer that any Aspect Oriented Programming is occurring.
Step 9 – Making the Aspect reusable
Lets make the aspect reusable. Lets make one aspect with a single pointcut and a single around advice work for multiple setters in a class.
In the Person class, add a forth field, DriversLicense. This field should also be encrypted.
Add a getter and setter for the DriversLicense field.
In the Main class, add sample code to set and later print out the DriversLicense field.
In the EncryptFieldAspect, change it to work for all setters by using a * after the word set and making it work for any method that takes a string, not just the SSN setter.
Ok, now it is reusable but we now have another problem. It is encrypting all the fields, including FirstName and LastName. It is definitely reusable, but now we need something to differentiate what is to be encrypted from what isn’t.
Step 10 – Create an Encrypt annotation
Lets add and use an annotation to mark setters that should use encryption.
Right-click on the package in Package Explorer and choose New | Annotation.
Note: The package should already be filled out for you.
Give the annotation a name.
Note: I named mine Encrypt.
Click Finish.
Maybe add a comment that this annotation is for use by the Encrypt Aspect.
public @interface Encrypt
{
// Handled by EncryptFieldAspect
}
Step 11 – Add the @Encrypt annotation to setters
In the Person class, add @Encrypt above the setSSN setter.
Also add @Encrypt above the setDriversLicense setter.
@Encrypt
public void setSSN(String inSSN)
{
SSN = inSSN;
}
Step 12 – Alter the EncryptFieldAspect to work for multiple objects
Well, now that it works for any setter in the Person object that is marked with @Encrypt, the next step is to make it work for any setter marked with @Encrypt no matter what object it is in.
Remove any reference to Person. We don’t even need it or the parameter ‘p’.
Ok, let’s create a second object that has an ecrypted field to test this. Lets create a Credentials.java file with a UserName and Password fields, getters and setters. Of course the Password should be encrypted.
Right-click on the package in Package Explorer and choose New | Class.
Note: The package should already be filled out for you.
Give the class a name.
Note: I named mine Credentials.
Click Finish.
Add both a UserName and Password field.
Add a getter and setter for both.
Add the @Encrypt annotation above the setPassword setter.
package AOPEncryptionExample;
public class Credentials
{
// UserName
private String UserName;
public String getUserName()
{
return UserName;
}
public void setUserName(String userName)
{
UserName = userName;
}
// Password
private String Password;
public String getPassword()
{
return Password;
}
@Encrypt
public void setPassword(String password)
{
Password = password;
}
}
Now lets create a Credentials object in the main() method and print out the values.
package AOPEncryptionExample;
public class Main
{
public static void main(String[] args)
{
Person p = new Person();
p.setFirstName("Billy");
p.setLastName("Bob");
p.setSSN("123456789");
p.setDriversLicense("987654321");
System.out.println("Person:");
System.out.println(" FirstName: " + p.getFirstName());
System.out.println(" LastName: " + p.getLastName());
System.out.println(" SSN: " + p.getSSN());
System.out.println(" Driver's License: " + p.getDriversLicense());
System.out.println();
Credentials c = new Credentials();
c.setUserName("billybob");
c.setPassword("P@sswd!");
System.out.println("Person:");
System.out.println(" UserName: " + c.getUserName());
System.out.println(" Password: " + c.getPassword());
}
}
Ok, test it. The output should be as follows:
Person:
FirstName: Billy
LastName: Bob
SSN: #encrypted#123456789#encrypted#
Driver's License: #encrypted#987654321#encrypted#
Person:
UserName: billybob
Password: #encrypted#P@sswd!#encrypted#
Well, now you have learned how to encrypt using Aspect Oriented Programming.
Here are a couple of benefits of encrypting with AOP.
The crosscutting concern of security is now modular.
If you wanted to change/replace the encryption mechanism, including the encryption method names, you can do that in a single place, the EncryptFieldAspect object.
The code to encrypt any field in your entire solution is nothing more than an annotation, @Encrypt.
The @Encrypt annotation can provide documentation in the class and in API documentation so the fact that encryption is occurring is known.
You don’t have to worry about developers implementing encryption differently as it is all done in a single file in the same predictable manner.
Congratulations on learning to encrypt using AOP, specifically with AspectJ and Annotations.
What about decryption?
By the way, I didn’t show you how to decrypt. Hopefully I don’t have to and after reading you know how. Maybe in your project the design is that the getters return the encrypted values and you don’t need to decrypt. However, maybe in your design you need your getters to decrypt. Well, you should be able to impement a DecryptFieldAspect and a @Decrypt annotation for that.
If you use decrypt on the getter, the output is the same as if there were no encrypt/decrypt occuring. However, it is still enhanced security because the value is stored encrypted in memory and not as plain text in memory.
However, I have a version of the project that decrypts that you can download.
Lets say you want to encrypt a field of a class. You might think that this is not a crosscutting concern, but it is. What if throughout and entire solution you need to encrypt random fields in many of your classes. Adding encryption to each of the classes can be a significant burden and breaks the “single responsibility principle” by having many classes implementing encryption. Of course, a static method or a single might be used to help, but even with that, code is must be added to each class. With Aspect Oriented Programming, this encryption could happen in one Aspect file, and be nice and modular.
Prereqs
This example assumes you have a development environment installed with at least the following:
JDK
AspectJ
Eclipse (Netbeans would work too)
Step 1 – Create an AspectJ project
In Eclipse, choose File | New | Project.
Select AspectJ | AspectJ Project.
Click Next.
Name your project.
Note: I named my project AOPEncryptionExample
Click Finish.
The project is now created.
Step 2 – Create a class containing main()
Right-click on the project in Package Explorer and choose New | Class.
Provide a package name.
Note: I named my package the same as the project name.
Give the class a name.
Note: I often name my class Main.
Check the box to include a public static void main(String[] args) method.
Click Finish.
package AOPEncryptionExample;
public class Main
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
}
}
Step 3 – Create an object with an encrypted value
For this example, I am going to use a Person object, and we are going to encrypt the SSN on that object.
Right-click on the package in Package Explorer and choose New | Class.
Note: The package should already be filled out for you.
Give the class a name.
Note: I named mine Person.
Click Finish.
Add String fields for FirstName, LastName, and SSN.
Add getters and setters for each.
package AOPEncryptionExample;
public class Person
{
// First Name
private String FirstName = "";
public String getFirstName()
{
return FirstName;
}
public void setFirstName(String inFirstName)
{
FirstName = inFirstName;
}
// Last Name
private String LastName = "";
public String getLastName()
{
return LastName;
}
public void setLastName(String inLastName)
{
LastName = inLastName;
}
// Social Security Number
private String SSN = "";
public String getSSN()
{
return SSN;
}
public void setSSN(String inSSN)
{
SSN = inSSN;
}
}
Right now, SSN has no encryption. We don’t want to clutter our Person class with encryption code. So we are going to put that in an aspect.
Step 4 – Add sample code to main()
Create in instance of Person.
Set a FirstName, LastName, and SSN.
Ouput each value.
public static void main(String[] args)
{
Person p = new Person();
p.setFirstName("Billy");
p.setLastName("Bob");
p.setSSN("123456789");
System.out.println("FirstName: " + p.getFirstName());
System.out.println(" LastName: " + p.getLastName());
System.out.println(" SSN: " + p.getSSN());
}
If you run your project, you will now have the following output.
FirstName: Billy
LastName: Bob
SSN: 123456789
Step 5 – Create and object to Simulate Encryption
You don’t have to do full encryption, or any encryption at all for that matter, to test this. The important thing to realize is that you can configure how the value is stored in an object without cluttering the object with the encryption code.
I created a FakeEncrypt static object and will use this object as an example.
package AOPEncryptionExample;
public class FakeEncrypt
{
public static String Encrypt(String inString)
{
return "#encrypted#" + inString + "#encrypted#";
}
}
The goal is to passing in an SSN, 123-456-789, and have it return an encrypted value (or in this case a fake encrypted value), #encrypted#123-456-789#encrypted#.
Step 6 – Create an Aspect object
Right-click on the package in Package Explorer and choose New | Other.
Choose AspectJ | Aspect.
Click Next.
Note: The package should already be filled out for you.
Give the Aspect a name.
Note: I named mine EncryptFieldAspect.
Click Finish.
package AOPEncryptionExample;
public aspect EncryptFieldAspect
{
}
Step 7 – Add the pointcut
Add a pointcut called SetSSN.
Include two parameters, the Person object and the SSN string.
Implement it with a call to void Person.setSSN(String).
Add a target for the Person p.
Add an args for the SSN string.
Add a !within this class (to prevent an infinite loop).
You are done with this one method. Here is the output of running this program.
FirstName: Billy
LastName: Bob
SSN: #encrypted#123456789#encrypted#
So we aren’t exactly done because we have two issues that would be nice to resolve. First, the Aspect is not reusable and second, their is no way for a developer to know by looking at the Person object that the SSN should be encrypted. Both of these issue are resolved by using annotations and will be explained in the next article.
This is a very easy example of Aspect Oriented Programming. Lets add advice (code to run) before the main() executs and when main() finishes. You will see how without cluttering our Main class or our main() method, we can add modular code to run before or after main().
Prereqs
This example assumes you have a development environment installed with at least the following:
JDK
AspectJ
Eclipse (Netbeans would work too)
Step 1 – Create an AspectJ project
In Eclipse, choose File | New | Project.
Select AspectJ | AspectJ Project.
Click Next.
Name your project.
Note: I named my project mainExample
Click Finish.
The project is now created.
Step 2 – Create a class containing main()
Right-click on the project in Package Explorer and choose New | Class.
Provide a package name.
Note: I named my package mainExample, the same as the project name.
Give the class a name.
Note: I often name my class Main.
Check the box to include a public static void main(String[] args) method.
Click Finish.
package mainExample;
public class MainExample
{
static void main(String[] args)
{
// TODO Auto-generated method stub
}
}
Step 3 – Create an Aspect object
Right-click on the mainExample package in Package Explorer and choose New | Other.
Choose AspectJ | Aspect.
Click Next.
Note: The package should already be filled out for you with “mainExample”.
Give the Aspect a name.
Note: I named mine StartEndAspect.
Click Finish.
package mainExample;
public aspect StartEndAspect
{
}
Step 4 – Add a pointcut to the StartEndAspect
Create a pointcut named mainMethod().
Configure the pointcut to use “execution”.
Configure the pointcut to be specifically for the “public static void main(String[] args)” method.
Example 4 – Serializing a list of objects that inherit from Person
Lets create some objects that inherit from Person. I looked at some documentation to try to get it right the first time. And then I hoped that it would just work….
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
@Root
public class Person
{
@Element(name="FirstName")
private String _FirstName = "";
@Element(name="LastName")
private String _LastName = "";
public String getFirstName()
{
return _FirstName;
}
public void setFirstName(String inFirstName)
{
_FirstName = inFirstName;
}
public String getLastName()
{
return _LastName;
}
public void setLastName(String inLastName)
{
_LastName = inLastName;
}
}
import java.util.ArrayList;
import java.util.List;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
@Root
public class People
{
@ElementList(inline=true)
List<Person> List = new ArrayList<Person>();
}
I didn’t want to get too complex so I only added a single item to Patient, a list of Symptoms.
import java.util.ArrayList;
import java.util.List;
import org.simpleframework.xml.ElementList;
public class Patient extends Person
{
@ElementList(entry = "Symptom", inline = true)
public List<String> Symptoms = new ArrayList<String>();
}
For the Physician, again to keep it simple, I only added a list of Hospitals.
import java.util.ArrayList;
import java.util.List;
import org.simpleframework.xml.ElementList;
public class Physician extends Person
{
@ElementList(entry = "Hospital", inline = true)
public List<String> Hospitals = new ArrayList<String>();
}
And here is the main method where I create the instances and serialize them.
import java.io.File;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
public class Run
{
public static void main(String[] args) throws Exception
{
People people = new People();
Patient p1 = new Patient();
p1.setFirstName("Jared");
p1.setLastName("Barneck");
p1.Symptoms.add("Runny nose");
p1.Symptoms.add("Congestion");
people.List.add(p1);
Physician p2 = new Physician();
p2.setFirstName("Mike");
p2.setLastName("Michaels");
p2.Hospitals.add("Intermount Health Care");
p2.Hospitals.add("St. Marks");
people.List.add(p2);
Serializer serializer = new Persister();
File file = new File("people.xml");
serializer.write(people, file);
}
}