@Override
    public IQ handleIQ(IQ packet) throws UnauthorizedException, PacketException {
        IQ replyPacket = IQ.createResultIQ(packet);

        Element child = packet.getChildElement();
        Element dataElement = child.elementIterator().next();

        if ( !UserManager.getInstance().isRegisteredUser( packet.getFrom(), false ) ) {
            Log.trace("Responding with 'service-unavailable': service unavailable to non-local, unregistered users: {}", packet);
            replyPacket.setChildElement(packet.getChildElement().createCopy());
            replyPacket.setError(PacketError.Condition.service_unavailable);
            replyPacket.getError().setText( "Service available only to locally registered users." );
            return replyPacket;
        }

        if (dataElement != null) {
            if (IQ.Type.get.equals(packet.getType())) {
                Element dataStored = privateStorage.get(packet.getFrom().getNode(), dataElement);
                dataStored.setParent(null);

                child.remove(dataElement);
                child.setParent(null);
                replyPacket.setChildElement(child);
                child.add(dataStored);
            }
            else {
                if (privateStorage.isEnabled()) {
                    privateStorage.add(packet.getFrom().getNode(), dataElement);
                } else {
                    Log.trace("Responding with 'service-unavailable': private storage is not enabled: {}", packet);
                    replyPacket.setChildElement(packet.getChildElement().createCopy());
                    replyPacket.setError(PacketError.Condition.service_unavailable);
                }
            }
        }
        else {
            replyPacket.setChildElement("query", "jabber:iq:private");
        }
        return replyPacket;
    }
Implements the TYPE_IQ jabber:iq:private protocol. Clients
use this protocol to store and retrieve arbitrary application
configuration information. Using the server for setting storage
allows client configurations to follow users where ever they go.
<p>
A 'get' query retrieves any stored data.
A 'set' query stores new data.
</p>
<p>
Currently an empty implementation to allow usage with normal
clients. Future implementation needed.
</p>
<h2>Assumptions</h2>
This handler assumes that the request is addressed to the server.
An appropriate TYPE_IQ tag matcher should be placed in front of this
one to route TYPE_IQ requests not addressed to the server to
another channel (probably for direct delivery to the recipient).
<h2>Warning</h2>
There should be a way of determining whether a session has
authorization to access this feature. I'm not sure it is a good
idea to do authorization in each handler. It would be nice if
the framework could assert authorization policies across channels.

@author Iain Shigeoka
xmppserver/src/main/java/org/jivesoftware/openfire/handler/IQPrivateHandler.java