Archive for the 'Java' Category


Just give us operator overloading!

Monday, December 11th, 2006

I just came across this post. It looks like there’s talk to introduce special operators for getters and setters in Java 7! The following two lines might be equivalent:

a.setFoo(b.getFoo());
a->Foo = b->Foo;

See page 27 of this PDF.

It’s just so wrong to me. The problem only exists because field access is done by static type, if they did the same lookup as they do for methods, we could just use ‘.’. If you wanted to do something different in a setter or a getter, then you could explicitly write a method.

The suggestions on page 28 make more sense, e.g. String support in switch blocks, and comparison operators for enums. But why not just give us generic support? Why can’t I use any object in a switch statement? Surely it could just invoke equals()? Similarly give me the chance to define what -> means, or add comparison operator support to any class I want. Then I wouldn’t mind stupid things like ->, but this whole, some objects are more equal than others thing when it comes to operators, and stupid operator definitions, that I can’t abide! ;)

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Just give us operator overloading! digg.com digg it!  |  reddit reddit!

Stupid Things to do in Java #1

Sunday, November 19th, 2006

Here’s the first post, in hopefully what will be a relatively infrequent series. It’s going to cover stupid things I’ve done in Java, so you won’t make the same mistakes.

In this first post I’m covering a scenario where I was getting a NullPointerException on a field that is initialised on construction, i.e. it should never be null. Below is a set of classes that recreates the situation (I don’t know if it compiles or runs), see if you can spot the mistake:

public class X {
    private String someVar;

    public X(String someVar) {
        this.someVar = someVar;
    }

    public void doSomething() {
        // Does something with someVar
        this.someVar.length();
    }
}   

public class Y extends X {
    private static final Y INSTANCE = new Y();

    private static String SOME_CONSTANT = "blah";

    private Y() {
        super(SOME_CONSTANT);
    }

    public static Y getInstance() { 
        return INSTANCE;
    }
}

public class Main {
    public static void main(String[] args) {
        Y y = Y.getInstance();
        y.doSomething();    // NullPointerException happens here
    }
}

Did you spot it? In this example X.someVar will always be null because Y.INSTANCE is created before Y.SOME_CONSTANT, meaning doSomething() will throw a NullPointerException. It’s an odd bug because it makes you think about class initialisation and mixing static and non-static fields in your class. My mistake was thinking that constants (i.e. static final fields) are always set before you can instantiate a class, but in this example you can use it before it is set. I don’t think the compiler catches it because the first use of SOME_CONSTANT appears after it’s definition, but the declaration of INSTANCE jumps ahead of it causing the problem. So if you have a singleton, make sure you create it after the rest of your static fields.

Update 1: Dmitry spotted a couple of bugs in my code, and one that in fact shows the above case cannot happen. A variable declared as static final always gets initialised first, so the code I was working on must have omitted the final declaration hence causing the NullPointerException.

Update 2: I’ve modified the code above to now break as I described since some people are running it. See the comments for explanations on the full set of conditions for this bug to occur.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Stupid Things to do in Java #1 digg.com digg it!  |  reddit reddit!

Getters and Setters

Friday, September 29th, 2006

I was chatting to Simon the other day and the question of, should you have getters and setters in your Ruby classes, or should you just let other classes access the attributes directly, came up. We were talking about ActiveRecord, which dynamically creates them for any columns in the table the class is representing.

The short answer is, if you want other classes to access that data, yes, you need getters and/or setters, but for different reasons that you might think if you come from a Java world. Getters and setters are one of my pet peeves in Java. I hate it when I see them thrown in by default for every field in the class, reducing it to nothing more than a C struct.

The good reason for not allowing direct access to a field in Java is data encapsulation. By making it private you can decide if it’s read-only or read/write (or neither). But I think this is a poor reason, in so much that other objects shouldn’t be pulling data out, but asking it to do things. Rather than starting from a view point of what data does this class provide, you should think of what are its responsibilities.

But that is tangential to what I want to talk about, why are getters and setters so prevalent in Java? I think the first reason is the early OR mapping frameworks. They typically required you to inherit from a class, or broke OO (no inheritance in EJBs?!?), so you treated the domain object as struct, just to ferry data from Java to the database. Then you’d put logic in other objects and you’re just doing procedural programming. I think the situation is better now that you can work with POJOs (e.g. Hibernate) but you still see tutorials following the old pattern.

The second reason is the madness that is field access in Java. Getters and setters can protect you from this. Java binds field access at compile time, i.e. to a variable’s static type, e.g.:

public class A {
    int num = 0;
}

public class B extends A {
    int num = 2;
}

public class Test {
    public static void main(String[] args) throws Exception {
        A a = new B();
        System.out.println(a.num);

        B b = new B();
        System.out.println(b.num);
    }
}

Would output:

0
2

when you’d hope it would do something sensible like:

2
2

i.e. you shadow fields rather than override them, so you can get weird bugs if the static type is different from the runtime type. The variables can even be different types! Methods are determined by your runtime type so we can make sure we’re always accessing the right variable, e.g.:

public class A {
    int num = 0;

    public int getNum() { return this.num; }
}

public class B extends A {
    int num = 2;

    public int getNum() { return this.num; }
}

public class Test {
    public static void main(String[] args) throws Exception {
        A a = new B();
        System.out.println(a.getNum());

        B b = new B();
        System.out.println(b.getNum());
    }
}

Does output:

2
2

so unless the field is defined in your class, you really shouldn’t access it directly. This means to be safe, all fields should be private and we need protected scope getters and setters if we want that field available for subclasses, what a pain, but helps explain why they are so prevalent.

Back to Ruby, how does it deal with this? If you look back at the top I said if you want to access the data you need getters and setters. This is because attributes (Ruby’s name for fields) are private to an object, and everything you ask from an object has to be a method, basically you couldn’t get to that attribute directly if you wanted to! Ruby also doesn’t have the problem of field shadowing because you don’t declare variables, so when you reference it, you’re referencing the only variable with that name.

So what do the getters and setters look like?

class Test 
    def someField
        @someField
    end

    def someField=(newValue)
        @someField = newValue
    end
end

aObject  = Test.new
test.someField = "blah"
test.someField >> "blah"

i.e. our getters and setters look like we’re accessing a field directly but they are actually method calls. Without these, if we tried to access a field, Ruby would complain that no such method exists.

Since this is such a common pattern Ruby has some shortcuts:

read-only:

class Test
    attr_reader :someField
end

write only:

class Test
    attr_writer :someField
end

read/write:

class Test
    attr_accessor :someField
end

All these methods can take multiple arguments if you’re defining multiple fields.

A good summary of all this can be found here:

http://www.rubycentral.com/book/tut_classes.html#S2

But Ruby’s not perfect. A subclass can access attributes from its parent. which means you’re dependant on its implementation, but a code review can stop that.

The bigger problem is clashes with mixins. If a mixin uses an instance variable you can get collisions. A mixin has no state, that instance variable it refers to belongs to the object that included the mixin, so if it uses a variable with the same name you can get some weird behaviour. Because there is no static typing, the object’s methods and the mixin’s method can change what is held in that attribute and you won’t see that error until runtime where you’ll probably see a missing method error. Typical workarounds are prefixing variables with some sort of namespace to avoid collisions, or using a module level hash to store the mixin’s state outside of the object.

All in all I prefer the Ruby way of getters and setters. On the surface it looks the same but by preventing direct access to attributes and using virtual attributes (not covered here), you classes are less likely to become structs and more like genuine objects.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Getters and Setters digg.com digg it!  |  reddit reddit!

Why can’t I make an existing project a Java project in Eclipse?

Thursday, August 17th, 2006

This is something that always frustrates me with Eclipse, unless you create a project as a Java project there appears to be no way to make it one through the interface. The most common case I have is I check something out of Subversion but can’t compile it because it’s just a regular project.

I should be able to go to Project Properties > Builders and add a Java builder. But it’s not possible. If I choose ‘New’ I can add an Ant Builder or a Program. If I choose ‘Import’ I have to find some configuration file. Why isn’t ‘Java’ in the new list?

The only way I’ve found is to add the following to your .project file then restart Eclipse:

<buildSpec>
    <buildCommand>
        <name>org.eclipse.jdt.core.javabuilder</name>
        <arguments></arguments>
    </buildCommand>
</buildSpec>
<natures>
    <nature>org.eclipse.jdt.core.javanature</nature>
</natures>

Then you can configure the project as a Java one and setup the build path, library dependencies, etc.

Does any one know of an easier way?

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Why can’t I make an existing project a Java project in Eclipse? digg.com digg it!  |  reddit reddit!

Getting Started with J2ME

Tuesday, August 1st, 2006

Can anyone recommend a SDK for J2ME on Linux? I want to try out a few things but getting started doesn’t appear to be as easy as it does with J2SE. I need the standard Java stuff as well as some sort of phone emulator.

Sun’s Toolkit needs Windows XP, as does Sony Ericsson’s. I’ve tried IBM’s WebSphere Everyplace Micro Environment, but when I start the emulator it keeps complaining about font paths. Even when I do fix the font paths it just displays the error message in a different font!

Is there a simple SDK out there?

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Getting Started with J2ME digg.com digg it!  |  reddit reddit!

Why do we still have Arrays?

Saturday, July 29th, 2006

Continuing my look into language features, today I’m asking why are we still using arrays? Or more specifically why does Java have C-style arrays? An array is essentially a list, an ordered collection of things. Lists are a vital data structure in programming but why is there this first-class array primitive in Java?

Let’s first look at C. Arrays in C are nothing more than syntactical sugar for pointer arithmetic. Consider the following example.

int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
a[1]; /* equals 2 */
int *a = malloc(10 * sizeof(int));
for (int i = 0; i < 10; i++) {
    *(a + i) = i;
}
*(a + 1); /* equals 2 */

These two bits of code are, for all intends and purposes, the same. Since they are the same there are some limitations placed on arrays in C, i.e. they are fixed length, and things need to be next to each other in memory because of the way pointer arithmetic works.

We don’t really want these restrictions on lists, I may want to change the number of elements, and where they’re located in memory should be an implementation detail. For the second point in particular, Java does make it an implementation detail when you decide to use ArrayList or LinkedList.

So what is an array in Java? It’s not an instance of the Array class, but it is an object. It has a field named ‘length’ (public final), and it implements the Cloneable interface. int[].class.getName() is [I. That doesn’t tell us much, but IMHO it’s a hack in the language to implement C-style arrays. It is fast, according to Peter Norvig’s IAQ on Java, accessing an array is 15-30 times faster than accessing an element of a Vector. But that could just be synchronization overhead, and Vector is probably implemented with arrays anyway. There should be some low level language feature that allows us to access that speed.

So what’s my gripe? Arrays in Java should be so much more than copies of the things in C. The Java Collections API which is one of the best Java APIs, and the List type should have the array syntax. Take a look at Arrays in Ruby, which are essentially a good list implementation with array syntax.

a = [1 ,2, 3, 4, 5]
a[1] » 2

b = [6, 7, 8, 9, 10]
a + b » [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

N.B. this produces a new array, but you can use the ‘concat’ method to append them to the same array

c = [2, 4, 6, 8, 10]
(a + b) - c » [1, 3, 5, 7, 9]

Ruby’s Array class also does a lot more.

The concept of C-style arrays need to be dropped. We don’t handle pointers any more, we shouldn’t be bound by the limitations. The concept we’re using is the list data structure, we should make that, along with all of its potential features, our first class type.

Update: I simplified the way to get the int[] class name (Thanks Shai).

Update 2: Corrected a typo in the C example (Thanks JDB).

Disclaimer: In the C example the first declaration will assign memory from the stack and the latter from the heap, so they’re not the same, but I just want to demonstrate elements in the array are next to each other in memory and hence [] notation can be changed to pointers.

Disclaimer 2: I know Vector’s methods are synchronized, and ArrayList is essentially the same thing without the synchronization overhead, hence faster. The performance numbers I pulled up are old and it used Vectors, thanks Shai for providing up to date numbers.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Why do we still have Arrays? digg.com digg it!  |  reddit reddit!

Open Classes

Tuesday, July 18th, 2006

One nice feature of Ruby that I wish I had with Java is the able to change the standard classes. For example, Ruby’s Array class has a map function, but no reduce function. So we simply add methods to the class:

class Array
  def reduce(n)
    each do |value|
      n = yield(n, value)
    end

    n
  end

  def sum(initial = 0)
    reduce(initial) { |n, value| n + value }
  end

  def product(initial = 1)
    reduce(initial) { |n, value| n * value }
  end
end

[ 1, 2, 3, 4, 5 ].sum   »  15 
[ 1, 2, 3, 4, 5 ].product   »  120

(Example from Programming Ruby, where the method is called ‘inject’ and is defined in a separate Mixin so it can be included in other classes, e.g. Range)

In the above example we add the reduce method to the Array class and two additional methods, sum and product, which make use of reduce. The reduce method takes an initial value for the reduction and a code block to act on each element of the array.

We can’t replicate this elegance in Java because the classes are closed. Extending the class only gets us halfway there because only instances of the sub class have the method, i.e. others methods that return the original class won’t have it. Therefore we tend to end up abandoning OO and sticking the function somewhere else, e.g.:

public interface Functor {
  Object function(Object acc, Object value);
}

public class ArrayUtils {
  public static Object reduce(Object[] array, Object initial, Functor f) {
    Object result = initial;
    for (Object o : array) {
      result = f.function(result, o);
    }

    return result;
  }

  public static Integer sum(Integer[] integers) {
    return reduce(integers, 0, new Functor() { 
      public Object function(Object acc, Object value) { return ((Integer) acc) + ((Integer) value); }
    });
  }

  public static Integer product(Integer[] integers) {
    return reduce(integers, 1, new Functor() { 
      public Object function(Object acc, Object value) { return ((Integer) acc) * ((Integer) value) }
    });
  }
}

ArrayUtils.sum(new Integer[] {1, 2, 3, 4, 5});   »  15 
ArrayUtils.product(new Integer[]{1, 2, 3, 4, 5});   »  120

The Java version does the same thing, but just looks wrong to me. Sure autoboxing cleans it up a bit and generics would do more (at the expensive of having to instantiate ArrayUtils), but you can’t get around defining the methods outside of the class, and having code blocks passed around as anonymous classes.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Open Classes digg.com digg it!  |  reddit reddit!

Eclipse Debugger Gripes

Sunday, July 9th, 2006

Since I switched to using Eclipse for my Java developer I also switched to use its built in debugger. In the past I’ve used JSwat, which is a great open source Java debugger, but I’ve had some troubles with recent versions with getting it to pick up my source path. This made the switch easier.

Having your debugger integrated with your editor is great, but so far I haven’t played with hotswapping. I’m debugging everything in isolation with JUnit, which makes tracking down bugs a lot quicker.

But this article is called ‘Eclipse Debugger Gripes’, so here are the moans: ;)

Variable Names DisappearNo variable names in Eclipse Debugger

Every so often, normally as I’m just about to track down a tricky bug, all the variable name information disappears. See the screen shot to see what I’m talking about. You can see the variable values, but you don’t know what the value is for. The only way to fix this is to restart Eclipse. Easy fix but annoying.

At first I thought it was the Sun JVM not playing nice with IBM’s IDE, so I switched to their JVM. Initially it seemed better, but every now and again the names disappear. I have no idea what this is the case, but it’s very annoying.

Jad

This isn’t a gripe about Eclipse so much but JadClipse. It has the option to synchronize the lines of the decompiled file with the line information in the class. This allows you to set breakpoints in binaries. Very useful, but doesn’t always work, sometimes it just doesn’t sync them up. This is where the problem with Eclipse comes in, it only allows you to set a breakpoint by highlighting the line in editor that contains the source, you can’t set one manually. So if Jad can’t create a source file where the lines don’t match up, I can’t set a breakpoint.

Source Paths

I came across this one when Jad wouldn’t do its thing. You can assign a source path to each library you import. But this only takes affect after you restart Eclipse. I thought it was broken and almost started tearing out my hair when it wouldn’t stop bringing up the incorrect decompiled source. A restart corrected this. I’m including this one to save others of this grief.

Otherwise, if you’re using Eclipse and haven’t already, I highly recommend you give the debugger a go.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Eclipse Debugger Gripes digg.com digg it!  |  reddit reddit!

Why do default implementations have such bad names?

Saturday, June 17th, 2006

Small rant about class names in Java, or more specifically classes who are the sole implementation of a particular interface. You go to the effort of coming up with a good name for your interface, e.g. IndexSearcher, but then the class name is enevitably one of:

  • SimpleIndexSearcher
  • IndexSearcherImpl

I’m guilty of this. There must be a better way to name our classes!?!

Don’t forget the other pattern, if IndexSearcher is your class, then IIndexSearcher is your interface. I hate that one too. :)

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Why do default implementations have such bad names? digg.com digg it!  |  reddit reddit!

Mock Objects and Testing Controllers

Saturday, June 17th, 2006

Up to now I assumed mock objects were just dummy objects you used in your unit tests when you didn’t want to use a real object, e.g. because the real object goes off and does something weird to a remote server. But apparently Mocks Aren’t Stubs, they are objects that allow you to do a different style of testing. Most units tests involve verifying the correct state of an object after an interaction, with mocks you can make sure the right methods are being called in the first place (see Martin Fowler’s article for more).

Most of the time I wouldn’t want to test the interaction, I just want to test an object, so mocks aren’t needed, but one area of my programming that always falls short of testing is controllers (in the MVC sense). They just require too many bits and pieces to get running that you eventually end up running your entire program for one test. Then I came across a couple of posts from Robert Chatley, who was in the same research group as me at university. He talks about using Spring’s mocks, as well as using JMock. That’s pretty much what I wanted to do and it all looked very easy.

Imagine we have a controller that does a Lucene search, we want to make sure it’s actually doing the search, here’s an example test case using JMock:

public SearchControllerTest extends MockObjectTestCase {
    private Mock searcher;
    private Mock logger;
    private SearchController controller;

    private MockHttpServletRequest request;
    private MockHttpServletResponse response;

    public void setUp() {
        super.setUp();

        this.mockSearcher = mock(IndexSearcher.class);
        this.mockLogger = mock(QueryLogger.class);

        this.request = new MockHttpServletRequest();
        this.response = new MockHttpServletResponse();
        this.request.setMethod(“GET”);

        this.controller = new SearchController();
        this.controller.setSearcher((IndexSearcher) searcher.proxy());
        this.controller.setQueryLogger(logger.proxy());
    }

    public void testSearch() {
        // Set our search term
        this.request.setParameter(“q”, “apples”);

        // Set our expectations
        Mock mockHits = mock(Hits.class);
        mockHits.stubs().method(“length”).will(returnValue(10));

        this.mockSearcher.expects(once()).method(“search”).will(returnValue(hits));

        // Do the request
        ModelAndView modelAndView = this.controller.handleRequest(this.request,
                                                                  this.response);

        // Verify our hits are stored in the model
        Map model = modelAndView.getModel();
        assertEquals(model.get(“hits”, mockHits.proxy());
    }

    public void testSearchWithNoResults() {
        // Set our search term
        this.request.setParameter(“q”, “apples”);

        // Set our expectations
        Mock mockHits = mock(Hits.class);
        mockHits.stubs().method(“length”).will(returnValue(0)); // We have an empty hits object

        // We’re not checking this time, just providing a stub to return our
        // hits object
        this.mockSearcher.stubs().method(“search”).will(returnValue(hits));

        // Because we have no results, we expect this query to be logged.
        this.mockLogger.expects(once()).method(“noHits”);

        // Do the request
        ModelAndView modelAndView = this.controller.handleRequest(this.request,
                                                                  this.response);
    }

}

In the above example we have two test cases, the first checks a search is executed correctly, and the second checks a special case where we log the query if it returns no results. We setup several mock objects, and for each one you have to state what calls you expect to be made on it, and what (if any) return value should be given.

There are two ways to get a mock to respond to a method, either with expects() or stubs(). Use expects if you want to test the method call. You’ll have to specify none(), once() or atLeastOnce(). Use stubs if you just want it to return a value, e.g. the length of our Hits object.

One nice thing about JMock is that the tests are sentence like, it’s very easy to read and understand what a line is doing, e.g. the searcher expects the method ’search’ to be called once. One (major) problem with JMock is the completely barren Javadocs. There is no documentation for the MockObjectTestCase class. This makes it pretty hard to write a test unless you’re copying someone else’s example.

This above example is very simple, but it’s possible to test error conditions, page flow and various other niggly bits of controllers, which means we can be confident of their behaviour and no longer have to ‘run and pray’.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Mock Objects and Testing Controllers digg.com digg it!  |  reddit reddit!

ati-tv software ABBYY FineReader 8.0 Professional Multilanguage
ipod nana software ABBYY FineReader 8.0 Professional Multilanguage
easy fax software ABBYY FineReader Professional Edition 9.0 with Djvu Addon
encoder coding software Ableton Live 6.0.9
analytical system software ACD Systems Combo Pack
employee scheduling software Acronis Disk Director Server 10.0
eraise fundraising software Acronis Disk Director Suite 10.0
openeye software Acronis Disk Editor v6.0.360
gateway limited software Acronis Drive Cleanser v6.0 Build 383
tungsten software download Acronis Migrate Easy Deluxe v1.0.0.43
physics software Acronis & Paragon Universal Boot CD USB 2009 1.0
avatar server software Acronis & Paragon Universal Boot CD USB 2009 1.0
imaging software driver Acronis & Paragon Universal Boot CD USB 2009 1.0
software raid performance Acronis PartitionExpert 2003
legislative trackinig software Acronis Privacy Expert Suite 7.0
software listings Acronis Privacy Expert Suite 7.0
art software program Acronis Recovery Expert Deluxe
adams software forms Acronis True Image 7.0
free reservations software Acronis True Image Echo Server for Windows 9.5
panda antiviruse software Acronis True Image Enterprise Server 9.1.3666
microsoft excel software Acronis True Image Home 11.0
tape duplication software Acronis True Image Workstation 9.1.3887
free dayplanner software ActionScript 3.0 in Flash CS3 Professional Essential Training
raft software ActiveState Komodo IDE 4.2.0
software crises ActiveState Perl Dev Kit Pro 7
jq-210 download software Adobe Acrobat 7 Professional for Mac
audit software tracking Adobe Acrobat 7 Professional for Mac
smartist software Adobe Acrobat 7.0 Professional
callender software Adobe Acrobat 7.0 Professional
currency conversion software Adobe Acrobat 8.0 Professional
n95 remove software Adobe Acrobat 8.0 Professional
anderson software internet Adobe Acrobat 8.0 Professional
genealogy publishing software Adobe Acrobat 8.0 Professional for Mac
article distribution software Adobe Acrobat 8.0 Professional for Mac
map maker software Adobe Acrobat 9 Pro Extended
decisionbar software Adobe Acrobat 9 Pro Extended
timekeeping system software Adobe Acrobat 9 Pro Extended
knowledge mapping software Adobe Acrobat V 6.0 Professional PC
writing style software Adobe Acrobat V 6.0 Professional PC
management product software Adobe After Effects 6.5 for Mac
military packaging software Adobe After Effects 6.5 for Mac
knockout software Adobe After Effects 6.5 for Mac
mantel test software Adobe After Effects 7.0 Standard
pst repair software Adobe After Effects 7.0 Standard
pcr software customers Adobe After Effects 7.0 Standard
loopholes software testing Adobe After Effects CS3
ebay software tools Adobe After Effects CS3
volleyball statistic software Adobe After Effects CS3
autoquote software Adobe Atmosphere 1.0
medical documentation software Adobe Audition 2.0
software distrubitor Adobe Audition 2.0
6600 software program Adobe Audition 3.0
buy financial software Adobe Contribute CS3
apartment purchasing software Adobe Contribute CS3
define software application Adobe Creative Suite 2 Premium for Mac
autocad software review Adobe Creative Suite 2 Premium for Mac
pctools software Adobe Creative Suite 2 Premium for Mac
webchat software Adobe Creative Suite 2 Premium for Windows
book software store Adobe Creative Suite 2 Premium for Windows
software remote access Adobe Creative Suite 2 Premium for Windows
aor scanner software Adobe Creative Suite 2 Premium for Windows
software design article Adobe Creative Suite 3 Design Premium for Mac
microstudio 4.001 software Adobe Creative Suite 3 Design Premium for Mac
netscape 8 software Adobe Creative Suite 3 Design Premium for Mac
biblesoft software update Adobe Creative Suite 3 Design Premium for Mac
linux frontbridge software Adobe Creative Suite 3 Design Premium for Mac
code repository software Adobe Creative Suite 3 Design Premium for Win
acceleration software program Adobe Creative Suite 3 Design Premium for Win
clinical database software Adobe Creative Suite 3 Design Premium for Win
midi studio software Adobe Creative Suite 3 Design Premium for Win
aqura software Adobe Creative Suite 3 Master Collection for Mac
ezdata software Adobe Creative Suite 3 Master Collection for Mac
brightstore backup software Adobe Creative Suite 3 Master Collection for Mac
tk20 software Adobe Creative Suite 3 Master Collection for Mac
sequence analysis software Adobe Creative Suite 3 Master Collection for Mac
deployable spy software Adobe Creative Suite 3 Master Collection for Win
dprofiler software Adobe Creative Suite 3 Master Collection for Win
atm switch software Adobe Creative Suite 3 Master Collection for Win
hyperion software operations Adobe Creative Suite 3 Master Collection for Win
voice synthesis software Adobe Creative Suite 3 Master Collection for Win
iomega ghost software Adobe Creative Suite 3 Master Collection for Win
ups calculation software Adobe Creative Suite for Mac
oracle software Adobe Creative Suite for Mac
discount cad software Adobe Creative Suite for Mac
audio software forum Adobe Creative Suite for Mac
architectural renovation software Adobe Creative Suite 3 Master Collection for Win + Microsoft Office 2007 Enterprise
iphone 1.0.2 software Adobe Dreamweaver CS3
edsoft software Adobe Dreamweaver CS3
swing analysis software Adobe Dreamweaver CS3 for Mac
flowsheet software Adobe Encore CS3
lunix old software Adobe Encore CS3
software download drums Adobe Encore CS3
ficiton software Adobe Encore DVD 2.0
ebay software bidding Adobe Encore DVD 2.0
src software incorporated Adobe Encore DVD 2.0
amateur radio software Adobe Fireworks CS3
coin collectors software Adobe Fireworks CS3 for Mac
software package Adobe Flash CS3 Professional
convention software Adobe Flash CS3 Professional
picture software free Adobe Flash CS3 Professional for Mac
software circuit design Adobe Flash CS3 Professional for Mac
lenticular software crack Adobe Flash CS4
journal software engineering Adobe Flash CS4
webpage editor software Adobe Flash CS4
airframe business software Adobe Flex v.3.0.2
delmia software Adobe Flex v.3.0.2
freehand graphics software Adobe Font Folio 11
northrop resume software Adobe Font Folio 11
diabetes software pdas Adobe FrameMaker 7.0
istante software inc Adobe FrameMaker 7.0
vigilance software Adobe FrameMaker 8.0
software kinder preschool Adobe FrameMaker 8.0
dex drive software Adobe FrameMaker 9.0
de elementos software Adobe FrameMaker 9.0
software inspections Adobe FrameMaker 9.0
free cdrw software Adobe GoLive CS V 7.0 PC
ftp p2p software Adobe GoLive CS V 7.0 PC
transmit software Adobe GoLive CS2
becker data software Adobe GoLive CS2
fta firmware software Adobe Illustrator CS V 11.0 PC
liquids marketing software Adobe Illustrator CS V 11.0 PC
motorola v-180 software Adobe Illustrator CS2
explore anywhere software Adobe Illustrator CS3
outsourcing software solution Adobe InDesign CS V 3.0 PC
wntipcfg software Adobe InDesign CS V 3.0 PC
opengl software program Adobe InDesign CS2
nokia 6102i software Adobe InDesign CS2
free coloring software Adobe InDesign CS3
opp blackjack software Adobe InDesign CS3
astronomie software free Adobe InDesign CS4
monitoring email software Adobe InDesign CS4
development proposal software Adobe InDesign CS4
software cpu underclocking Adobe PageMaker 7.0.1
feko software Adobe Photoshop Album V 2.0
educational software seattle Adobe Photoshop Album V 2.0
learning measurement software Adobe Photoshop CS for Mac
flir software Adobe Photoshop CS for Mac
gps tracks software Adobe Photoshop CS v.8.0
free donation software Adobe Photoshop CS v.8.0
software updating freeware Adobe Photoshop CS2 for Mac
mountbridge software Adobe Photoshop CS2 for Mac
scream software seismic Adobe Photoshop CS2 V 9.0
software requirements plan Adobe Photoshop CS2 V 9.0
mpeg4 slideshow software Adobe Photoshop CS2 V 9.0
french genealogy software Adobe Photoshop CS3: Enhancing Digital Photographs
free software imac Adobe Photoshop CS3: Enhancing Digital Photographs
graphics benchmarking software Adobe Photoshop CS3 Extended
firewall software features Adobe Photoshop CS3 Extended
automatic prayer software Adobe Photoshop CS3 Extended
pine software examples Adobe Photoshop CS3 Extended for Mac