Thursday, October 15, 2009

Section 5.5. Reflexive Associations








5.5. Reflexive Associations


It's also possible for objects and tables to have associations back to themselves. This supports persistent
recursive data structures like trees, in which nodes link to other nodes.
Tracing through a database table storing such relationships using a SQL
query interface is a major chore. Luckily, once it's mapped to Java
objects, the process is much more readable and natural.


One way we might use a reflexive link in our music database is to
allow alternate names for artists. This is useful more often than you
might expect, because it makes it very easy to let the user find either
"The Smiths" or "Smiths, The" depending on how they're thinking of the
group, with little code, and in a language-independent way.


NOTE


I mean human language here—English versus Spanish or something
else. Put the links in the data rather than trying to write tricky code
to guess when an artist name should be permuted.




5.5.1. How do I do that?


All you need to do is add another field to the
Artist mapping in Artist.hbm.xml, establishing a link back
to Artist. Example 5-14 shows
one option.


Example 5-14. Supporting a reflexive association in the Artist class



<many-to-one name="actualArtist" class="com.oreilly.hh.data.Artist">
<meta attribute="use-in-tostring">true</meta>
</many-to-one>




This gives us an actualArtist property that we can set to the id of the "definitive"
Artist record when we're setting up an alternate
name. For example, our "The Smiths" record might have id 5, and
its actualArtist field would
be null since it is definitive. Then
we can create an "alias" Artist record with the
name "Smiths, The" at any time, and set the actualArtist field in that record to point to
record 5.



This kind of reflexive link is one instance where a column
containing a foreign key can't be named the same as the key column to
which it is a link. We are associating a row in ARTIST with another row in ARTIST, and of course the table already has
a column named ARTIST_ID.




Why is this association set up as many-to-one? There might be
many alias records that point to one particular definitive
Artist. So, each nickname needs to store the
id of the actual artist record for
which it is an alternative name. This is, in the language of data
modeling, a many-to-one relationship.


Code that looks up artists just needs to check the actualArtist property
before returning. If it's null, all
is well. Otherwise, it should return the record indicated by actualArtist. Example 5-15 shows how
we could extend the getArtist⁠⁠(⁠ ⁠) method in
CreateTest to support this new feature (additions
are in bold). Notice that the Artist constructor
gets a new argument for setting actualArtist, which
means we had to update the other places that call it in
CreateTest too, even though we aren't showing
them here.


Example 5-15. Artist lookup method supporting resolution of alternate
names



public static Artist getArtist(String name, boolean create, Session session) {
Query query = session.getNamedQuery("com.oreilly.hh.artistByName");
query.setString("name", name);
Artist found = (Artist)query.uniqueResult();
if (found == null && create) {
found = new Artist(name, new HashSet(), null);
session.save(found);
}
if (found != null && found.getActualArtist() != null) {
return found.getActualArtist();
}

return found;
}





Hopefully this chapter has given you a feel for the rich and
powerful ways you can use associations and collections in Hibernate. As
should be obvious from the way you can nest and combine these
capabilities, there are far more variations than we can hope to cover in
a book like this.



The good news is that Hibernate seems well equipped to handle
almost any kind of relationship your application might need, and it can
even do the drudge work of building the data classes and database
schema for you. This works much more effectively and deeply than I
ever expected it would when I started
creating these examples.










Acknowledgments








 

 










Acknowledgments

After writing six Java books over the past five years, I've learned that it's crucial to have a good set of reviewers. For this book, I was fortunate enough to have the best set of reviewers an author could possibly have.



First, I'd like to thank Marty Hall, the author of Core Servlets and JSP and More Servlets and JSP for his thorough and insightful review of this book. Marty's review comments added considerably to the quality of this book.



Second, I'd like to thank Jan Luehe for providing excellent review comments that went way above and beyond the call of duty. Jan was one of the handful of developers that implemented the JSTL Reference Implementation, and he pointed out many inconsistencies and misunderstandings that I originally had about JSTL, especially the internationalization and database actions, which can be rather complicated to initialize and use. Like Marty, Jan considerably increased the quality of this book by his sage observations.



Many other people also provided excellent review comments that I relentlessly incorporated into the book. I was fortunate to have Pierre Delisle, who is the lead engineer for JSTL, agree to review this book. Pierre provided many review comments that only someone in his position could make. Norbert Lindenberg, who is an internationalization specialist at Sun provided numerous comments on the internationalization and formatting chapters. Ryan Lubke, who implemented the test kit for the JSTL also provided numerous pithy comments, along with Lance Anderson and Carole Mah, whom I recruited from the Jakarta Taglibs mailing list to review the database chapter. Scott Ferguson, the developer of the excellent Resin app server,was also gracious enough to review another of my books. Lars Garshol, who has worked on the Goldfarb XML series from Prentice Hall helped me out considerably with the XML chapter. Finally, my good friend and resident Java expert, Rob Gordon, also provided me with excellent review comments.












     

     


    Hack 25 Secure Your Event Logs











     < Day Day Up > 





    Hack 25 Secure Your Event Logs





    Keep your system's logs from

    being tampered with
    .





    Windows has some very powerful

    logging

    features. Unfortunately, by default the event logs are not protected

    against unauthorized access or modification. You may not realize that

    even though you have to view the logs through the Event Viewer, the

    event logs are simply regular files just like any other. To secure

    them, all we have to do is locate them and apply the proper

    ACLs.





    Unless their location has been changed through the registry, you

    should be able to find the logs in the

    %SystemRoot%\system32\config directory.





    The three files that correspond to the Application Log, Security Log,

    and System Log are AppEvent.Evt,

    SecEvent.Evt, and

    SysEvent.Evt, respectively. Now, apply ACLs to

    limit access to only Administrator accounts. You can do this by

    bringing up the Properties dialog for the files and clicking the

    Security tab. After you've done this, remove any

    users or groups other than Administrators and SYSTEM from the top

    pane.

















       < Day Day Up > 



      12.2 S/MIME Overview











       < Day Day Up > 





      12.2 S/MIME Overview



      The S/MIME standard offers a consistent way to send and receive secure MIME data. S/MIME provides the following cryptographic security services for electronic messaging applications: authentication; message integrity and nonrepudiation of origin, using digital signatures; and privacy and data security, using encryption.



      S/MIME can be used by traditional mail clients to add cryptographic services to mail that is sent and to interpret cryptographic services in mail that is received. However, S/MIME is not restricted to mail but can be used with any transport mechanism that transports MIME data, such as HTTP. As such, S/MIME takes advantage of the object-based features of MIME and allows secure messages to be exchanged in mixed-transport systems.



      Many of the difficulties early implementers faced with the S/MIME standard were caused by incomplete specifications. The S/MIME specifications, through several long iterations, have not been verified to be implementable and interoperable by many vendors. RSA has also created S/MIME compliance tests, along with an S/MIME seal that states that an implementation has passed S/MIME compliance testing.













         < Day Day Up > 



        Simplifying the Model with the Universal Delegator


        3 4



        Simplifying the Model with the Universal Delegator



        The biggest drawback of the fully reusable split identity solution you saw in the previous section is that it is not transparent to the object in the ring that previously held a direct reference to what becomes the creator of the back pointer object. Figure 9-5 shows that object B can no longer hold an interface pointer of a type supported by object A but must instead grapple with IBackPtr. When object B wants to talk to object A, it first needs to call IBackPtr::GetTarget to retrieve the interface pointer for object A that it is interested in before making any calls. This involves a separate step to which error handling must be applied. In many cases, this solution will be just fine. But if object B already has been developed and its source code perhaps is not under your control, things become a little more difficult. The same holds true if object B is an event source expecting to connect to a specific event sink interface. You could develop a version of CBackPtr specific to object A that
        implements the interface of object A that object B intends to hold onto, simply by forwarding all calls after calling GetTarget on itself. In the case of connectable objects, this specific back pointer then could issue the appropriate Advise call to object B. This will work, but it proliferates the back pointer implementation and introduces a dual point of maintenance for each back pointer creator and consumer pair with this need.



        Wouldn't it be nice if the split identity solution could work just like Visual Basic's solution for connectable objects? In our scenario, there are two identities, but the one handed to the event source or ring transparently supports all the methods that the holder of the ring object's reference supports—without having to write more than one single implementation of the back pointer class.



        What we need to achieve this is a second-level interceptor for access to the back pointer's creator. The back pointer itself should function as this interceptor. The interception service it provides is calling GetTarget prior to forwarding the intercepted call and releasing the interface pointer thus obtained after forwarding the call. But think back to our discussion of interception services in Chapter�4. The call to GetTarget definitely could fail if the back pointer's creator had self-destructed. Therefore, we will need to deal with all three of the classic problems of providing generic interception services: the language problem, the failure problem, and the post-processing problem. You're probably thinking it seems hopeless and just too big of a job.



        Well, I'd agree with you if it weren't for a piece of software Keith Brown has written and makes freely available:8 the Universal Delegator. The Universal Delegator solves all the problems of interception for you; it contains some assembly code for the Intel platform. It allows you to specify what it calls hooks, which you can use to perform your own preprocessing and postprocessing for each delegated call. That's where you would do the calling of GetTarget and the releasing of the interface pointer to the creator, respectively. By extending the split identity solution with this piece of software, you can shim a back pointer instance between any two objects in a reference cycle without having to modify the interface types the two can use and store in order to make calls to one another. And you will need only a single implementation of CBackPtr. No dual points of maintenance exist. This extended solution now will work transparently to break reference cycles among connectable objects where the event sink is a C++ COM+ object.



        The Universal Delegator won't work right out of the box to accomplish this purpose. Keith anticipated a reference cycle associated with common usage of just the Universal Delegator itself. Many developers like using the Universal Delegator to wrap services (such as security services) around their objects before they expose them to other objects. This would create a reference cycle between the Universal Delegator and the object to which it delegates. Keith has created his own split identity scheme to disarm this reference cycle. But unfortunately it works the wrong way for our purposes: The Universal Delegator's creator can hold onto a secondary identity exposed by it. But the Universal Delegator itself always maintains a reference-counted interface pointer to its delegation target.



        If you want to merge the CBackPtr implementation with that of the Universal Delegator, the strong reference it maintains to its delegation target is one of the hurdles you will have to overcome by altering Keith's source code a bit. I don't expect any major gotchas, but it might take a few hours' worth of work. However, I'm sure that the result will be worth the time spent. And who knows, perhaps someone will post his solution to the Web!



        Split identity of course is not a symmetric solution. In that regard, it differs greatly from how a garbage collector reclaims abandoned rings. With split identity, you must pick one of the ring's nodes for breaking the reference cycle. Because that particular object is then no longer kept alive by other objects in the ring, it better be the one that clients hold onto as long as they need the entire ring structure to carry out operations successfully. Normally, picking the right object is straightforward based on your ring or connectable object design. I will call that object the beginning of the ring and the one that holds a reference to its back pointer object the end, reinforcing the asymmetric nature of the solution. Because the end does not keep the beginning alive (whereas the beginning keeps the end and all intermediates alive), the end needs to be prepared for failure when trying to access the beginning. Such failure can ripple from near the beginning toward the end of the ring across several objects. You might not be able to shield the implementation of your ring objects from such failures.



        Not being able to control the scope during which the end keeps the beginning alive is the first of two weak points of using the Universal Delegator with split identity. Without the Universal Delegator, the end calls GetTarget on the beginning and holds onto the resulting interface pointer for as long as it needs to, possibly across multiple method invocations on the beginning. After GetTarget returns successfully but before the resulting interface pointer is released, the beginning's lifetime is guaranteed to the end. This could be quite important to the implementation of the object at the end of the ring, as well as to its clients inside and outside the ring. It also might simplify that implementation. But with the Universal Delegator, GetTarget is not called (by the end) and every call the end makes on the beginning could be its last, since the beginning could vanish at any moment. If this poses a problem but you still want to take advantage of the convenience of the Universal
        Delegator solution where applicable, you might opt for a hybrid solution. You could deploy the Universal Delegator to provide interception services at the level of the back pointer object but also call GetTarget when doing so simplifies things.



        The second weakness of the Universal Delegator is that its use is not portable across platforms. You get stuck with a piece of assembly language that you later might have to maintain and port. Of course, whether this is a problem for you greatly depends on the nature of your project. Nothing in this world is free, I suppose.



        Recipe 1.3 Understanding Your Workspace











         < Day Day Up > 







        Recipe 1.3 Understanding Your Workspace







        1.3.1 Problem





        What's meant by the

        term

        workspace? And what's a

        plug-in?









        1.3.2 Solution





        Although you might think of Eclipse as a Java IDE, it comprises a

        number of components that act together behind the scenes in

        Eclipse's workspace. A plug-in is a software tool

        that accomplishes a specific task in Eclipse, such as allowing you to

        edit an Ant file, compile a Java file, or drag and drop GUI elements.

        The workspace, along with the Eclipse workbench, the team component,

        and the help component, are all parts of the overall Eclipse

        platform, and serve as the foundation for plug-ins to interact with

        the Eclipse core software.









        1.3.3 Discussion





        The Java IDE you work with is the Java Development

        Toolkit
        , or JDT. The JDT is not an integral part of

        Eclipse; it's

        a plug-in. Eclipse

        is really composed of the Eclipse Platform, which provides support

        for other tools. These tools are implemented as plug-ins, allowing

        the platform itself to be a relatively small software package.





        Eclipse comes with a number of plug-ins, including the JDT. Another

        important plug-in is the

        Plug-in Development Environment (PDE), which

        enables you to develop your own plug-ins. If you want to develop in a

        language other than Java, you get the corresponding plug-in for that

        language, and many are available.







        Besides using different programming languages, you can change the

        human language that Eclipse uses as well. Different languages often

        are supported with what are called plug-in

        fragments
        . Plug-in fragments are available for numerous

        languages, including Japanese, Korean, German, French, Italian,

        Portuguese, Spanish, and even traditional and simplified Chinese.








        Knowing the parts of Eclipse is essential to working with it for

        anything but the most casual use. If you don't have

        at least an idea of what parts do what, you'll end

        up confused when you encounter the barriers between these components,

        which can make Eclipse's behavior seem inconsistent.

        For example, when you know that the JDT is different from other

        plug-ins, you won't be surprised when options

        available in the JDT aren't available in other

        plug-ins.





        The Eclipse Platform consists of several components: the platform

        kernel, the workspace, the workbench, the team component, and the

        help component. You can see an overview of these components in Figure 1-3. Plug-ins are loaded when Eclipse starts; the

        plug-ins also appear in Figure 1-3.







        Figure 1-3. Eclipse components and plug-ins









        1.3.3.1 The Eclipse platform kernel




        Everything starts with the platform

        kernel. The platform kernel is written in native code, and its job is

        to load the rest of Eclipse; the kernel warns you if it

        can't find a workable Java installation to run the

        rest of the application. The kernel also loads the Eclipse plug-ins.











        1.3.3.2 The workbench component




        The workbench is Eclipse

        at its most basic.

        The workbench window displays the menus and toolbars you saw in Figure 1-2 (the menu and toolbar items that are displayed

        are put there by the perspective you're currently

        viewing).





        Although you load different plug-ins, each with different windows and

        menu systems, the workbench is what displays them. The workbench is

        designed to look like a native application, targeted to your

        operating system. In Linux, it looks like a Linux application, in

        Windows, a Windows application, and so on.







        Targeting Eclipse's graphical user interface to the

        operating system is a somewhat controversial issue. The workbench

        is built using Eclipse's

        own Standard Widget Toolkit (SWT) and JFace packages (built on top of

        SWT), which use operating-system native components in their displays.

        Doing that in a Java application is still a contentious point, as

        you'll see when we discuss SWT and JFace later in

        Chapter 8, Chapter 9,

        and Chapter 10.














        1.3.3.3 The workspace component




        The workspace component in Eclipse

        manages your

        resources, including what you store on disk. Eclipse manages your

        resources

        in projects, and by default each project is

        managed by the workspace component

        in

        the Eclipse workspace

        directory. You'll learn more about

        projects later in this chapter in Recipe 1.5.







        Your project doesn't need to be in the workspace

        directory; you can use other directories, even networked directories.

        To select a different location, uncheck the "Use

        default" checkbox when you give the name of the

        project to create, and fill in the directory you want to use instead.








        The workspace component manages all the resources in a project,

        including your code. It also manages changes to your code and to

        other files, giving you access to a stored history of the changes and

        even enabling you to compare those changes graphically. The workspace

        also communicates with plug-ins such as the JDT, making history and

        file information accessible.











        1.3.3.4 The team component




        The team component gives you version control for your code, and it

        supports file sharing. If you've developed software

        in a corporate environment, you might already have worked with source

        code control and repositories. Code is stored in a repository and

        checked in or out as needed, which means the changes to the software

        can be tracked.





        Coordinating changes that teams make to the code means you can avoid

        the kind of random overlapping changes that will

        cause utter chaos otherwise. Eclipse

        integrates well with the Concurrent Versions System (CVS), the de

        facto standard for version control (except perhaps in Microsoft

        shops, where Visual SourceSafe still reigns supreme). In fact, the

        team component can act as a CVS client, which interacts with a CVS

        server that maintains the code repository from which team members can

        retrieve code. We're going to take a look at how

        this works in Chapter 6.











        1.3.3.5 The help component




        The help component is Eclipse's documentation

        system for

        providing help. It's an extensible help system;

        plug-ins can provide their own help, in XML-formatted form, to tell

        the help system how to navigate their documentation.











        1.3.3.6 Plug-ins




        Eclipse is extendible via plug-ins. Plug-ins

        can set up their own perspectives,

        editors, views, wizards, and more. For example, the JDT is a plug-in

        that adds its functionality to what the workbench already provides.

        Besides using some of the more than 450 plug-ins available for

        Eclipse, we're also going to build our own starting

        in Chapter 12.





















           < Day Day Up > 



          Chapter 26.&nbsp; OSGi Essentials










          Chapter 26. OSGi Essentials


          In Chapter 2, "Eclipse RCP Concepts," we outlined the basic Eclipse concepts of plug-ins, the Runtime, applications, products, and the extension registry. Further chapters provided additional detail in the context of particular problems or scenarios related to Hyperbola, our omnipresent chat client example. This chapter digs into the OSGi concepts and constructs that underlie the Eclipse Runtime.


          You should think of this chapter as reference material and use it as needed. We cover many advanced topics and explain exactly what your application does from start to finishthe kind of information you need when you have problems and are up late at night troubleshooting. Of course, you are free to read through the chapter and pick up various background information and helpful tips and tricks that can be applied everyday.


          The material here is by no means a complete treatment of OSGi and its use in Eclipse; that would take another book! It is, however, useful for people who are:


          • curious about the how plug-ins relate to OSGi constructs such as bundles

          • troubleshooting their application, for example, tracking down ClassNotFoundExceptions

          • designing a set of plug-ins and fragments

          • looking to understand more about how Eclipse starts, runs, and stops


          It is worth pointing out here that the OSGi framework specification is just that, a specification for a framework. The framework is intended to be implemented and run on a wide range of platforms and environments. As such, it does not say anything about, for example, how bundles are installed, how they are started, how they are laid out on disk, or even if they are laid out on disk. It is up to implementations to define these characteristics.


          The bulk of this chapter is devoted to mapping the OSGi specification onto the Eclipse use case. Readers are encouraged to read the OSGi Framework Specification Release 4 from http://osgi.org and treat this chapter as a guide to the Eclipse implementation and use of that specification.