class IQPrivateHandler extends IQHandler implements ServerFeaturesProvider {

    private static final Logger Log = LoggerFactory.getLogger(IQPrivacyHandler.class);

    public static final String NAMESPACE = "jabber:iq:private";

    private IQHandlerInfo info;
    private PrivateStorage privateStorage = null;

    public IQPrivateHandler() {
        super("XMPP Private Storage Handler");
        info = new IQHandlerInfo("query", NAMESPACE);
    }

    @Override
    public IQ handleIQ(IQ packet) throws UnauthorizedException, PacketException {<FILL_FUNCTION_BODY>}

    @Override
    public void initialize(XMPPServer server) {
        super.initialize(server);
        privateStorage = server.getPrivateStorage();
    }

    @Override
    public IQHandlerInfo getInfo() {
        return info;
    }

    @Override
    public Iterator<String> getFeatures() {
        return Arrays.asList(
            "jabber:iq:private",
            "urn:xmpp:bookmarks-conversion:0"
        ).iterator();
    }
}

        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;
    
<methods>public void <init>(java.lang.String) ,public abstract org.jivesoftware.openfire.IQHandlerInfo getInfo() ,public abstract IQ handleIQ(IQ) throws org.jivesoftware.openfire.auth.UnauthorizedException,public void initialize(org.jivesoftware.openfire.XMPPServer) ,public boolean performNoSuchUserCheck() ,public void process(Packet) throws org.jivesoftware.openfire.PacketException<variables>private static final Logger Log,protected org.jivesoftware.openfire.PacketDeliverer deliverer,protected org.jivesoftware.openfire.SessionManager sessionManager