/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.behaviors;

import java.io.File;

import org.apache.wicket.Component;
import org.apache.wicket.behavior.AbstractAjaxBehavior;
import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
import org.apache.wicket.request.resource.ContentDisposition;
import org.apache.wicket.util.resource.FileResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.efaps.ui.wicket.EFapsSession;
import org.efaps.ui.wicket.util.DojoClasses;
import org.efaps.ui.wicket.util.DojoWrapper;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class AjaxDownloadBehavior
    extends AbstractAjaxBehavior
{
    /**
     *  Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Add the anticache tags or not.
     */
    private final boolean addAntiCache;

    /**
     * Add the script to the page.
     */
    private boolean addScript2Page = false;

    /**
     * Constructor using antichache.
     */
    public AjaxDownloadBehavior()
    {
        this(true);
    }

    /**
     * @param _addAntiCache use anticache tags
     */
    public AjaxDownloadBehavior(final boolean _addAntiCache)
    {
        super();
        this.addAntiCache = _addAntiCache;
    }

    /**
     * Call this method to initiate the download.
     * @param _target Ajaxtarget
     */
    public void initiate(final IPartialPageRequestHandler _target)
    {
        final String url = getCallBackURL();
        if (url != null) {
            _target.prependJavaScript(getCallBackScript(url));
        }
    }

    /**
     * @return the callback url, null if no
     */
    protected String getCallBackURL()
    {
        String ret = null;
        final File file = ((EFapsSession) getComponent().getSession()).getFile();
        if (file != null && file.exists()) {
            String url = getCallbackUrl().toString();
            if (this.addAntiCache) {
                url = url + (url.contains("?") ? "&" : "?");
                url = url + "antiCache=" + System.currentTimeMillis();
            }
            //since version 6.15 there might be a .. add the beginning that must be
            //removed if the link comes from the main page
            if (url.startsWith("..")) {
                url = url.substring(1);
            }
            ret = url;
        }
        return ret;
    }

    /**
     * Initiate the download.
     */
    public void initiate()
    {
        this.addScript2Page = true;
    }

    /**
     * On request, respond with a ResourcStream.
     */
    @Override
    public void onRequest()
    {
        final String fileName = getFileName();
        final IResourceStream stream = getResourceStream();
        final ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(stream, fileName);
        handler.setContentDisposition(ContentDisposition.ATTACHMENT);
        getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
    }

    /**
     * Override this method for a file name which will let the browser prompt
     * with a save/open dialog.
     *
     * @see ResourceStreamRequestTarget#getFileName()
     * @return filename
     */
    protected String getFileName()
    {
        final File file = EFapsSession.get().getFile();
        return file.getName();
    }

    /**
     * Hook method providing the actual resource stream.
     * @return stream
     */
    protected IResourceStream getResourceStream()
    {
        final File file = EFapsSession.get().getFile();
        final FileResourceStream ret = new FileResourceStream(file);
        EFapsSession.get().setFile(null);
        return ret;
    }

    @Override
    public void renderHead(final Component _component,
                           final IHeaderResponse _response)
    {
        super.renderHead(_component, _response);
        if (this.addScript2Page) {
            final String url = getCallBackURL();
            if (url != null) {
                _response.render(JavaScriptHeaderItem.forScript(getCallBackScript(url),
                                AjaxDownloadBehavior.class.getName()));
            }
            this.addScript2Page = false;
        }
    }

    /**
     * Script that searches for an existing iframe to use it for the download of the frame.
     * If it does not exist it will be created.
     *
     * @param _url the url
     * @return the callback script
     */
    protected CharSequence getCallBackScript(final String _url)
    {
        final StringBuilder js = new StringBuilder()
            .append("baseWindow.withDoc(top.dojo.doc, function () {\n")
            .append("var node = dom.byId('downloadFrame');\n")
            .append("if (node == null) {\n")
            .append("node = domConstruct.place('<iframe id=\"downloadFrame\" src=\"about:blank\" ")
                .append("style=\"position: absolute; left: 1px; top: 1px; height: 1px; width: 1px; ")
                .append("visibility: hidden\">', win.body());\n")
            .append("}\n")
            .append("node.src='").append(_url).append("';")
            .append("});\n");
        return DojoWrapper.require(js, DojoClasses.baseWindow, DojoClasses.dom, DojoClasses.domConstruct);
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.efaps.ui.wicket.models.field.factories;

import java.text.DecimalFormat;
import java.text.NumberFormat;

import org.apache.wicket.Component;
import org.apache.wicket.model.Model;
import org.efaps.admin.datamodel.ui.RateUI;
import org.efaps.admin.datamodel.ui.RateUI.Value;
import org.efaps.db.Context;
import org.efaps.ui.wicket.components.values.HiddenRateField;
import org.efaps.ui.wicket.components.values.RateField;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.util.EFapsException;

/**
 * A factory for creating RateUI objects.
 */
@SuppressWarnings("checkstyle:abstractclassname")
public final class RateUIFactory
    extends AbstractUIFactory
{

    /**
     * Factory Instance.
     */
    private static RateUIFactory FACTORY;

    /**
     * Singelton.
     */
    private RateUIFactory()
    {
    }

    @Override
    public Component getEditable(final String _wicketId,
                                 final AbstractUIField _uiField)
        throws EFapsException
    {
        Component ret = null;
        if (applies(_uiField)) {
            final RateUI.Value value = (Value) _uiField.getValue().getEditValue(_uiField.getParent().getMode());
            _uiField.getFieldConfiguration().evalLabel(_uiField.getValue(), _uiField.getInstance());
            ret = new RateField(_wicketId, Model.of(_uiField), _uiField.getFieldConfiguration(), value);
        }
        return ret;
    }

    @Override
    public Component getHidden(final String _wicketId,
                               final AbstractUIField _uiField)
        throws EFapsException
    {
        Component ret = null;
        if (applies(_uiField)) {
            final RateUI.Value value = (Value) _uiField.getValue().getHiddenValue(_uiField.getParent().getMode());
            ret = new HiddenRateField(_wicketId, Model.of(_uiField), _uiField.getFieldConfiguration(), value);
        }
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean applies(final AbstractUIField _uiField)
        throws EFapsException
    {
        return _uiField.getValue().getUIProvider() instanceof RateUI;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getReadOnlyValue(final AbstractUIField _abstractUIField)
        throws EFapsException
    {
        String strValue = "";
        final Object valueTmp = _abstractUIField.getValue()
                        .getReadOnlyValue(_abstractUIField.getParent().getMode());
        if (valueTmp instanceof Number) {
            final DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Context.getThreadContext()
                            .getLocale());
            strValue = formatter.format(valueTmp);
        } else if (valueTmp instanceof RateUI.Value) {
            final DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Context.getThreadContext()
                            .getLocale());
            if (_abstractUIField.getValue().getAttribute() != null) {
                formatter.setMaximumFractionDigits(_abstractUIField.getValue().getAttribute().getScale());
            }
            strValue = formatter.format(((RateUI.Value) valueTmp).getRate());
        }
        return strValue;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getKey()
    {
        return RateUIFactory.class.getName();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getPickListValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return getReadOnlyValue(_uiField);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Comparable<?> getCompareValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return (Comparable<?>) _uiField.getValue().getReadOnlyValue(_uiField.getParent().getMode());
    }

    /**
     * @return IComponentFactory instance
     */
    public static IComponentFactory get()
    {
        if (RateUIFactory.FACTORY == null) {
            RateUIFactory.FACTORY = new RateUIFactory();
        }
        return RateUIFactory.FACTORY;
    }
}


/*
 * Copyright 2015-2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.hod.client.api.textindex.query.parametric;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.hp.autonomy.hod.client.api.authentication.EntityType;
import com.hp.autonomy.hod.client.api.authentication.TokenType;
import com.hp.autonomy.hod.client.api.resource.ResourceName;
import com.hp.autonomy.hod.client.config.HodServiceConfig;
import com.hp.autonomy.hod.client.config.Requester;
import com.hp.autonomy.hod.client.error.HodErrorException;
import com.hp.autonomy.hod.client.token.TokenProxy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Default implementation of GetParametricValuesService
 */
public class GetParametricValuesServiceImpl implements GetParametricValuesService {
    private final GetParametricValuesBackend getParametricValuesBackend;
    private final Requester<?, TokenType.Simple> requester;
    private final ObjectMapper objectMapper;

    /**
     * Creates a new GetParametricValuesServiceImpl with the given configuration
     *
     * @param hodServiceConfig The configuration to use
     */
    public GetParametricValuesServiceImpl(final HodServiceConfig<?, TokenType.Simple> hodServiceConfig) {
        getParametricValuesBackend = hodServiceConfig.getRestAdapter().create(GetParametricValuesBackend.class);
        requester = hodServiceConfig.getRequester();
        objectMapper = hodServiceConfig.getObjectMapper();
    }

    @Override
    public List<FieldValues> getParametricValues(
            final Collection<String> fieldNames,
            final Collection<ResourceName> indexes,
            final GetParametricValuesRequestBuilder params
    ) throws HodErrorException {
        final JsonNode response = requester.makeRequest(JsonNode.class, getBackendCaller(fieldNames, indexes, params));
        return parseResponse(response);
    }

    @Override
    public List<FieldValues> getParametricValues(
            final TokenProxy<?, TokenType.Simple> tokenProxy,
            final Collection<String> fieldNames,
            final Collection<ResourceName> indexes,
            final GetParametricValuesRequestBuilder params
    ) throws HodErrorException {
        final JsonNode response = requester.makeRequest(tokenProxy, JsonNode.class, getBackendCaller(fieldNames, indexes, params));
        return parseResponse(response);
    }

    /*
     * HOD has a bug (HOD-5731) where, if a query profile is provided, GetParametricValues returns an object with number
      * keys rather than an array. This parses a JSON node of either type.
     */
    private List<FieldValues> parseResponse(final JsonNode response) {
        if (response == null || response.get("fields") == null) {
            throw new RuntimeException("Failed to parse JSON");
        }

        final JsonNode fieldsNode = response.get("fields");

        if (fieldsNode.getNodeType() == JsonNodeType.OBJECT || fieldsNode.getNodeType() == JsonNodeType.ARRAY) {
            final List<FieldValues> output = new ArrayList<>();

            for (final JsonNode node : fieldsNode) {
                try {
                    final FieldValues fieldValues = objectMapper.treeToValue(node, FieldValues.class);
                    output.add(fieldValues);
                } catch (final JsonProcessingException e) {
                    throw new RuntimeException("Failed to parse JSON", e);
                }
            }

            return output;
        } else {
            throw new RuntimeException("Failed to parse JSON");
        }
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getBackendCaller(
            final Collection<String> fieldNames,
            final Collection<ResourceName> indexes,
            final GetParametricValuesRequestBuilder params
    ) {
        return authenticationToken -> getParametricValuesBackend.getParametricValues(authenticationToken, fieldNames, indexes, params.build());
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.efaps.ui.wicket.components.search;

import org.apache.commons.lang.BooleanUtils;
import org.apache.wicket.ajax.attributes.AjaxCallListener;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.HiddenField;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.efaps.json.index.result.DimValue;
import org.efaps.ui.wicket.components.search.IndexSearch.DimTreeNode;
import org.efaps.ui.wicket.util.DojoClasses;
import org.efaps.ui.wicket.util.DojoWrapper;

/**
 * The Class DimValuePanel.
 *
 * @author The eFaps Team
 */
public class DimValuePanel
    extends GenericPanel<DimTreeNode>
{

    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = 1L;

    /**
     * Instantiates a new dim value panel.
     *
     * @param _id the id
     * @param _model the model
     */
    public DimValuePanel(final String _id,
                         final IModel<DimTreeNode> _model)
    {
        super(_id, _model);
        final WebMarkupContainer cont = new WebMarkupContainer("triStateDiv");
        cont.setOutputMarkupId(true);

        if (_model.getObject().getStatus() != null) {
            cont.add(new AttributeAppender("class", _model.getObject().getStatus() ? "on" : "off", " "));
        }

        add(cont);

        final AjaxButton btn = new AjaxButton("triStateBtn")
        {
            /** The Constant serialVersionUID. */
            private static final long serialVersionUID = 1L;

            @Override
            protected void updateAjaxAttributes(final AjaxRequestAttributes _attributes)
            {
                super.updateAjaxAttributes(_attributes);
                final AjaxCallListener lstnr = new AjaxCallListener();
                lstnr.onBefore(getJavaScript());
                _attributes.getAjaxCallListeners().add(lstnr);
            }
        };
        cont.add(btn);

        cont.add(new Label("label", _model.getObject().getLabel()));
        cont.add(new Label("value", String.valueOf(((DimValue) _model.getObject().getValue()).getValue())));

        cont.add(new HiddenField<Boolean>("triStateValue", PropertyModel.of(_model.getObject(), "status")) {

            /** The Constant serialVersionUID. */
            private static final long serialVersionUID = 1L;

            @Override
            public boolean isInputNullable()
            {
                return true;
            };

            @Override
            protected String getModelValue()
            {
                final Boolean val = (Boolean) getDefaultModelObject();
                final String ret;
                if (BooleanUtils.isFalse(val)) {
                    ret = "off";
                } else if (BooleanUtils.isTrue(val)) {
                    ret = "on";
                } else {
                    ret = "";
                }
                return ret;
            };

        } .setOutputMarkupId(true));
    }

    /**
     * Gets the java script.
     *
     * @return the java script
     */
    private CharSequence getJavaScript()
    {

        final String divId = get("triStateDiv").getMarkupId(true);
        get("triStateDiv:triStateBtn").getMarkupId(true);
        final String valId = get("triStateDiv:triStateValue").getMarkupId(true);

        final StringBuilder ret = new StringBuilder()
                .append("switch (dom.byId('").append(valId).append("').value)")
                .append("{")
                .append("case 'on':")
                .append("dom.byId('").append(valId).append("').value = 'off';")
                .append("domClass.replace('").append(divId).append("', 'off', 'on');")
                .append("break;")
                .append("case 'off':")
                .append("dom.byId('").append(valId).append("').value = '';")
                .append("domClass.remove('").append(divId).append("', 'off');")
                .append("break;")
                .append("default:")
                .append("dom.byId('").append(valId).append("').value = 'on';")
                .append("domClass.add('").append(divId).append("', 'on');")
                .append("}");
        return  DojoWrapper.require(ret, DojoClasses.domClass, DojoClasses.dom, DojoClasses.on,
                        DojoClasses.query, DojoClasses.NodeListTraverse, DojoClasses.domReady);
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.wicket.Application;
import org.apache.wicket.MetaDataKey;
import org.apache.wicket.Session;
import org.apache.wicket.protocol.ws.WebSocketSettings;
import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
import org.apache.wicket.protocol.ws.api.registry.IKey;
import org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.http.WebRequest;
import org.apache.wicket.util.collections.ConcurrentHashSet;
import org.apache.wicket.util.lang.Generics;
import org.efaps.admin.program.esjp.EFapsClassLoader;
import org.efaps.db.Context;
import org.efaps.ui.wicket.behaviors.KeepAliveBehavior;
import org.efaps.ui.wicket.util.Configuration;
import org.efaps.ui.wicket.util.Configuration.ConfigAttribute;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class ConnectionRegistry
{

    /**
     * Logger for this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(ConnectionRegistry.class);

    /**
     * MetaDataKey for User to Session Mapping.
     */
    private static final MetaDataKey<ConcurrentMap<String, ConcurrentHashSet<String>>> USER2SESSION =
                    new MetaDataKey<ConcurrentMap<String, ConcurrentHashSet<String>>>()
            {
                private static final long serialVersionUID = 1L;
            };

    /**
     * MetaDataKey for Session to Page Mapping.
     */
    private static final MetaDataKey<ConcurrentMap<String, IKey>> SESSION2KEY =
                    new MetaDataKey<ConcurrentMap<String, IKey>>()
            {
                private static final long serialVersionUID = 1L;
            };

    /**
     * MetaDataKey for Session that must be invalidated on next request.
     */
    private static final MetaDataKey<ConcurrentHashSet<String>> INVALIDATED =
                    new MetaDataKey<ConcurrentHashSet<String>>()
            {
                private static final long serialVersionUID = 1L;
            };

    /**
     * MetaDataKey for the last Request Time of a Session.
     */
    private static final MetaDataKey<ConcurrentMap<String, Long>> LASTACTIVE =
                    new MetaDataKey<ConcurrentMap<String, Long>>()
            {
                private static final long serialVersionUID = 1L;
            };

    /**
     * MetaDataKey for the last Request Time of a Session.
     */
    private static final MetaDataKey<ConcurrentMap<String, Long>> KEEPALIVE =
                    new MetaDataKey<ConcurrentMap<String, Long>>()
            {
                private static final long serialVersionUID = 1L;
            };

    /**
     * Used to store if the KeepAlive threat was started.
     */
    private boolean keepAlive = false;

    /**
     * @param _sessionID sessionId to be check for invalid
     * @return true if valid, else false
     */
    public boolean sessionValid(final String _sessionID)
    {
        ConcurrentHashSet<String> invalidated = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.INVALIDATED);

        if (invalidated == null) {
            synchronized (ConnectionRegistry.INVALIDATED) {
                invalidated = Session.get().getApplication().getMetaData(ConnectionRegistry.INVALIDATED);
                if (invalidated == null) {
                    invalidated = new ConcurrentHashSet<>();
                    Session.get().getApplication().setMetaData(ConnectionRegistry.INVALIDATED, invalidated);
                }
            }
        }
        return !invalidated.contains(_sessionID);
    }

    /**
     * @param _sessionID sessionId the Activit will be registered for
     * @param _date date of the activity
     */
    public void registerSessionActivity(final String _sessionID,
                                        final Date _date)
    {
        ConcurrentMap<String, Long> lastactive = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.LASTACTIVE);

        if (lastactive == null) {
            synchronized (ConnectionRegistry.LASTACTIVE) {
                lastactive = Session.get().getApplication().getMetaData(ConnectionRegistry.LASTACTIVE);
                if (lastactive == null) {
                    lastactive = Generics.<String, Long>newConcurrentHashMap();
                    Session.get().getApplication().setMetaData(ConnectionRegistry.LASTACTIVE, lastactive);
                }
            }
        }
        lastactive.put(_sessionID, _date.getTime());
        ConnectionRegistry.LOG.debug("Register Activity for Session: {}", _sessionID);
    }

    /**
     * @param _sessionID    id of the session the keep alive belongs to
     * @param _date         time to register
     */
    public void registerKeepAlive(final String _sessionID,
                                  final Date _date)
    {
        ConcurrentMap<String, Long> keepalive = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.KEEPALIVE);

        if (keepalive == null) {
            synchronized (ConnectionRegistry.KEEPALIVE) {
                keepalive = Session.get().getApplication().getMetaData(ConnectionRegistry.KEEPALIVE);
                if (keepalive == null) {
                    keepalive = Generics.<String, Long>newConcurrentHashMap();
                    Session.get().getApplication().setMetaData(ConnectionRegistry.KEEPALIVE, keepalive);
                }
            }
        }
        keepalive.put(_sessionID, _date.getTime());
        ConnectionRegistry.LOG.debug("Register KeepAlive for Session: {}", _sessionID);
    }

    /**
     * @param _sessionID session to marked as invalid
     */
    public void markSessionAsInvalid(final String _sessionID)
    {
        ConcurrentHashSet<String> invalidated = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.INVALIDATED);

        if (invalidated == null) {
            synchronized (ConnectionRegistry.INVALIDATED) {
                invalidated = Session.get().getApplication().getMetaData(ConnectionRegistry.INVALIDATED);
                if (invalidated == null) {
                    invalidated = new ConcurrentHashSet<>();
                    Session.get().getApplication().setMetaData(ConnectionRegistry.INVALIDATED, invalidated);
                }
            }
        }
        invalidated.add(_sessionID);
        ConnectionRegistry.LOG.debug("Marked Session: {} as invalid", _sessionID);
    }

    /**
     * @param _userName userName
     * @param _sessionId sessionid
     */
    private void registerLogin4History(final String _userName,
                                       final String _sessionId)
    {
        try {
            final WebRequest req = (WebRequest) RequestCycle.get().getRequest();
            final HttpServletRequest httpReq = (HttpServletRequest) req.getContainerRequest();
            String ipAddress = httpReq.getHeader("X-FORWARDED-FOR");
            if (ipAddress == null) {
                ipAddress = httpReq.getRemoteAddr();
            }

            final Class<?> clazz = Class.forName("org.efaps.esjp.common.history.LoginHistory", true,
                            EFapsClassLoader.getInstance());
            final Object obj = clazz.newInstance();
            final Method method = clazz.getMethod("register", String.class, String.class, String.class);
            method.invoke(obj, _userName, _sessionId, ipAddress);
        } catch (final ClassNotFoundException e) {
            ConnectionRegistry.LOG.error("Error on registering Login", e);
        } catch (final NoSuchMethodException e) {
            ConnectionRegistry.LOG.error("Error on registering Login", e);
        } catch (final SecurityException e) {
            ConnectionRegistry.LOG.error("Error on registering Login", e);
        } catch (final IllegalAccessException e) {
            ConnectionRegistry.LOG.error("Error on registering Login", e);
        } catch (final IllegalArgumentException e) {
            ConnectionRegistry.LOG.error("Error on registering Login", e);
        } catch (final InvocationTargetException e) {
            ConnectionRegistry.LOG.error("Error on registering Login", e);
        } catch (final InstantiationException e) {
            ConnectionRegistry.LOG.error("Error on registering Login", e);
        }
    }

    /**
     * @param _userName userName
     * @param _sessionId sessionid
     */
    private void registerLogout4History(final String _userName,
                                        final String _sessionId)
    {
        boolean contextOpened = false;
        try {
            if (!Context.isThreadActive()) {
                Context.begin(_userName);
                contextOpened = true;
            }
            final Class<?> clazz = Class.forName("org.efaps.esjp.common.history.LogoutHistory", true,
                            EFapsClassLoader.getInstance());
            final Object obj = clazz.newInstance();
            final Method method = clazz.getMethod("register", String.class, String.class, String.class);
            method.invoke(obj, _userName, _sessionId, "N.A.");
        } catch (final ClassNotFoundException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } catch (final NoSuchMethodException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } catch (final SecurityException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } catch (final IllegalAccessException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } catch (final IllegalArgumentException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } catch (final InvocationTargetException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } catch (final InstantiationException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } catch (final EFapsException e) {
            ConnectionRegistry.LOG.error("Error on registering Logout", e);
        } finally {
            if (contextOpened && Context.isThreadActive()) {
                try {
                    Context.commit();
                } catch (final EFapsException e) {
                    ConnectionRegistry.LOG.error("Error on registering Logout", e);
                }
            }
        }
    }

    /**
     * @param _userName login of the user
     * @param _sessionID    SessionId assigned
     */
    protected void setUser(final String _userName,
                           final String _sessionID)
    {
        ConnectionRegistry.LOG.debug("register user: '{}', session: '{}'", _userName, _sessionID);
        ConcurrentMap<String, ConcurrentHashSet<String>> user2session = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.USER2SESSION);

        if (user2session == null) {

            synchronized (ConnectionRegistry.USER2SESSION) {
                user2session = Session.get().getApplication().getMetaData(ConnectionRegistry.USER2SESSION);
                if (user2session == null) {
                    user2session = Generics.<String, ConcurrentHashSet<String>>newConcurrentHashMap();
                    Session.get().getApplication().setMetaData(ConnectionRegistry.USER2SESSION, user2session);
                }
            }
        }
        ConcurrentHashSet<String> sessions = user2session.get(_userName);
        if (sessions == null) {
            synchronized (ConnectionRegistry.USER2SESSION) {
                sessions = user2session.get(_userName);
                if (sessions == null) {
                    sessions = new ConcurrentHashSet<>();
                    user2session.put(_userName, sessions);
                }
            }
        }
        sessions.add(_sessionID);
        ConnectionRegistry.LOG.debug("Added User '{}' for Session: {}", _userName, _sessionID);
        registerLogin4History(_userName, _sessionID);
    }

    /**
     * @param _sessionID    Sessionid the message belongs to
     * @param _key          key the message belongs to
     */
    public void addMsgConnection(final String _sessionID,
                                 final IKey _key)
    {
        initKeepAlive();
        ConcurrentMap<String, IKey> session2key = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.SESSION2KEY);
        if (session2key == null) {
            synchronized (ConnectionRegistry.SESSION2KEY) {
                session2key = Session.get().getApplication().getMetaData(ConnectionRegistry.SESSION2KEY);
                if (session2key == null) {
                    session2key = Generics.<String, IKey>newConcurrentHashMap();
                    Session.get().getApplication().setMetaData(ConnectionRegistry.SESSION2KEY, session2key);
                }
            }
        }
        session2key.put(_sessionID, _key);
        ConnectionRegistry.LOG.debug("Added Message Connection for Session: {}", _sessionID);
    }

    /**
     * @param _login        login of the user to be remved for the registry
     * @param _sessionId    id to be removed
     */
    protected void removeUser(final String _login,
                              final String _sessionId)
    {
        removeUser(_login, _sessionId, Session.get().getApplication());
    }

    /**
     * @param _login        login of the user to be removed for the registry
     * @param _sessionID    id to be removed
     * @param _application  Application that contains the mapping
     */
    protected void removeUser(final String _login,
                              final String _sessionID,
                              final Application _application)
    {
        if (_login != null) {
            ConnectionRegistry.LOG.debug("remove user: '{}', session: '{}'", _login, _sessionID);
            ConcurrentMap<String, ConcurrentHashSet<String>> user2session = _application.getMetaData(
                            ConnectionRegistry.USER2SESSION);
            synchronized (ConnectionRegistry.USER2SESSION) {
                user2session = _application.getMetaData(ConnectionRegistry.USER2SESSION);
                if (user2session != null) {
                    final ConcurrentHashSet<String> sessions = user2session.get(_login);
                    sessions.remove(_sessionID);
                    if (sessions.isEmpty()) {
                        user2session.remove(_login);
                    }
                }
            }
            synchronized (ConnectionRegistry.KEEPALIVE) {
                final ConcurrentMap<String, Long> keepalive = _application.getMetaData(ConnectionRegistry.KEEPALIVE);
                if (keepalive != null) {
                    keepalive.remove(_sessionID);
                }
            }
            ConnectionRegistry.LOG.debug("Removed User '{}' for Session: {}", _login, _sessionID);
            registerLogout4History(_login, _sessionID);
        }
    }

    /**
     * @param _login login of the user the session is wanted for
     * @return Connections for the user, empty list if not found
     */
    public List<IWebSocketConnection> getConnections4User(final String _login)
    {
        final List<IWebSocketConnection> ret = new ArrayList<>();
        final ConcurrentMap<String, ConcurrentHashSet<String>> user2session = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.USER2SESSION);
        final ConcurrentMap<String, IKey> sessionId2pageId = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.SESSION2KEY);
        final ConcurrentHashSet<String> sessionIds = user2session.get(_login);

        if (sessionIds != null && !sessionIds.isEmpty()) {
            final Iterator<String> iter = sessionIds.iterator();
            while (iter.hasNext()) {
                final String sessionId = iter.next();
                final IKey key = sessionId2pageId.get(sessionId);
                if (key != null) {
                    final IWebSocketConnectionRegistry registry = WebSocketSettings.Holder.get(EFapsApplication.get())
                                    .getConnectionRegistry();
                    final IWebSocketConnection conn = registry.getConnection(EFapsApplication.get(), sessionId, key);
                    if (conn != null) {
                        ret.add(conn);
                    }
                }
            }
        }
        return ret;
    }

    /**
     * @param _login login of the user the session is wanted for
     * @param _sessionId sessionid the connection is wanted for
     * @return Connection for the user, null if not found
     */
    public IWebSocketConnection getConnection4UserSession(final String _login,
                                                          final String _sessionId)
    {
        IWebSocketConnection ret = null;
        final ConcurrentMap<String, ConcurrentHashSet<String>> user2session = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.USER2SESSION);
        final ConcurrentMap<String, IKey> sessionId2key = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.SESSION2KEY);
        final ConcurrentHashSet<String> sessionIds = user2session.get(_login);

        if (sessionIds.contains(_sessionId)) {
            final IKey key = sessionId2key.get(_sessionId);
            if (key != null) {
                final IWebSocketConnectionRegistry registry = WebSocketSettings.Holder.get(EFapsApplication.get())
                                .getConnectionRegistry();
                ret = registry.getConnection(EFapsApplication.get(), _sessionId, key);
            }
        }
        return ret;
    }

    /**
     * @param _userName login of the user
     * @return list of sessionIds for the given user
     */
    public List<String> getSession4User(final String _userName)
    {
        List<String> ret = new ArrayList<>();
        final ConcurrentMap<String, ConcurrentHashSet<String>> user2session = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.USER2SESSION);
        if (user2session != null) {
            final ConcurrentHashSet<String> sessions = user2session.get(_userName);
            ret = new ArrayList<>(sessions);
        }
        return ret;
    }

    /**
     * @return list of all registered Users
     */
    public List<String> getUsers()
    {
        List<String> ret = new ArrayList<>();
        final ConcurrentMap<String, ConcurrentHashSet<String>> user2session = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.USER2SESSION);
        if (user2session != null) {
            ret = new ArrayList<>(user2session.keySet());
        }
        return ret;
    }

    /**
     * @return the map of Session currently active
     */
    public Map<String, Set<String>> getSessions4Users()
    {
        final ConcurrentMap<String, ConcurrentHashSet<String>> user2session = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.USER2SESSION);
        final Map<String, Set<String>> tmpmap = new TreeMap<>();
        if (user2session != null) {
            for (final Entry<String, ConcurrentHashSet<String>> entry : user2session.entrySet()) {
                tmpmap.put(entry.getKey(), Collections.unmodifiableSet(entry.getValue()));
            }
        }
        return Collections.unmodifiableMap(tmpmap);
    }

    /**
     * @return the map of Session with its last registered activity.
     */
    public Map<String, Long> getSessionsActivity()
    {
        final ConcurrentMap<String, Long> lastactive = Session.get().getApplication()
                        .getMetaData(ConnectionRegistry.LASTACTIVE);
        final Map<String, Long> ret;
        if (lastactive == null) {
            ret = Collections.unmodifiableMap(Collections.<String, Long>emptyMap());
        } else {
            ret = Collections.unmodifiableMap(lastactive);
        }
        return ret;
    }

    /**
     * Send the KeepAlive.
     * @param _application Application the KeepAlive will be send for
     */
    public void sendKeepAlive(final Application _application)
    {
        final long reference = new Date().getTime();
        final ConcurrentMap<String, IKey> sessionId2key = _application.getMetaData(ConnectionRegistry.SESSION2KEY);
        final ConcurrentMap<String, Long> keepalive = _application.getMetaData(ConnectionRegistry.KEEPALIVE);
        if (keepalive != null) {
            for (final Entry<String, Long> entry : keepalive.entrySet()) {
                if (reference - entry.getValue()
                                > Configuration.getAttributeAsInteger(ConfigAttribute.WEBSOCKET_KATH) * 1000) {
                    final IKey key = sessionId2key.get(entry.getKey());
                    if (key != null) {
                        final IWebSocketConnectionRegistry registry = WebSocketSettings.Holder.get(
                                        _application).getConnectionRegistry();
                        final IWebSocketConnection conn = registry.getConnection(_application, entry.getKey(), key);
                        if (conn != null) {
                            try {
                                conn.sendMessage(KeepAliveBehavior.MSG);
                                ConnectionRegistry.LOG.debug("Send KeepAlive for Session: {}", entry.getKey());
                            } catch (final IOException e) {
                                ConnectionRegistry.LOG.error("Catched error", e);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Init the KeepAlive mechanism.
     */
    private void initKeepAlive()
    {
        if (!this.keepAlive) {
            this.keepAlive = true;
            final KeepAliveTask keepAliveTask = new KeepAliveTask(EFapsApplication.get().getApplicationKey());
            final Timer timer = new Timer(true);
            // every two minutes
            timer.scheduleAtFixedRate(keepAliveTask, 0 * 1000,
                            Configuration.getAttributeAsInteger(ConfigAttribute.WEBSOCKET_KASP) * 1000);
        }
    }

    /**
     * task to send the keep alive messages.
     */
    private class KeepAliveTask
        extends TimerTask
    {
        /**
         * Key to the application this task belong to.
         */
        private final String applicationKey;

        /**
         * @param _applicationKey key to the application this task belong to
         */
        KeepAliveTask(final String _applicationKey)
        {
            this.applicationKey = _applicationKey;
        }

        @Override
        public void run()
        {
            final EFapsApplication app = (EFapsApplication) Application.get(this.applicationKey);

        }
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.models.objects;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage;
import org.efaps.ui.wicket.connectionregistry.RegistryManager;
import org.efaps.ui.wicket.connectionregistry.UserSession;
import org.joda.time.DateTime;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class UIUserSession
    extends UIUser implements IWebSocketPushMessage
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * SessionId for the user.
     */
    private String sessionId;

    /**
     * last Activity as date long.
     */
    private final long lastActivity;

    /**
     * @param _userName username
     * @param _sessionId    sessionid
     * @param _lastActivity last registered activity
     */
    public UIUserSession(final String _userName,
                         final String _sessionId,
                         final Long _lastActivity)
    {
        super(_userName);
        this.sessionId = _sessionId;
        this.lastActivity = _lastActivity == null ? 100 : _lastActivity;
    }

    /**
     * Getter method for the instance variable {@link #sessionId}.
     *
     * @return value of instance variable {@link #sessionId}
     */
    public String getSessionId()
    {
        return this.sessionId;
    }

    /**
     * Setter method for instance variable {@link #sessionId}.
     *
     * @param _sessionId value for instance variable {@link #sessionId}
     */
    public void setSessionId(final String _sessionId)
    {
        this.sessionId = _sessionId;
    }

    /**
     * Getter method for the instance variable {@link #lastActivity}.
     *
     * @return value of instance variable {@link #lastActivity}
     */
    public DateTime getLastActivity()
    {
        return new DateTime(this.lastActivity);
    }

    @Override
    public String toString()
    {
        return ToStringBuilder.reflectionToString(this);
    }

    /**
     * Gets the UI user sessions.
     *
     * @return list of currently registered Users
     */
    public static List<UIUserSession> getUIUserSessions()
    {
        final List<UIUserSession> ret = new ArrayList<>();
        final Collection<UserSession> userSessions = RegistryManager.getUserSessions();
        for (final UserSession userSession : userSessions) {
            ret.add(new UIUserSession(userSession.getUserName(), userSession.getSessionId(), userSession
                            .getLastActivity()));
        }
        return ret;
    }
}


/*
 * Copyright 2003 - 2015 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.components;

import java.util.List;
import java.util.Map.Entry;

import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.IMarkupFragment;
import org.apache.wicket.markup.MarkupException;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.value.IValueMap;
import org.efaps.api.ui.IUserInterface;

/**
 * This class is a Label for webform and webtable. It is needed to replace
 * the eFapsTempTag and add the events.
 *
 * @author The eFaps Team
 * @version $Id:LabelComponent.java 1510 2007-10-18 14:35:40Z jmox $
 */
public class LabelComponent
    extends WebComponent
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Constructor that makes a model from the value to use the standard
     * constructor.
     *
     * @param _wicketId wicketId of this Component
     * @param _value value of this Component
     */
    public LabelComponent(final String _wicketId,
                          final String _value)
    {
        this(_wicketId, new Model<String>(_value));
    }

    /**
     * Standard constructor.
     *
     * @param _wicketId wicketId of this Component
     * @param _model model of this Component
     */
    public LabelComponent(final String _wicketId,
                          final IModel<?> _model)
    {
        super(_wicketId, _model);
        setRenderBodyOnly(true);
    }

    /**
     * Must be overwritten so that no replacing of html tags is done.
     *
     * @see org.apache.wicket.Component#onComponentTagBody(org.apache.wicket.markup.MarkupStream,
     *      org.apache.wicket.markup.ComponentTag)
     *
     * @param _markupStream MarkupStream
     * @param _openTag Tag
     */
    @Override
    public void onComponentTagBody(final MarkupStream _markupStream,
                                      final ComponentTag _openTag)
    {
        setEscapeModelStrings(false);
        String value = getDefaultModelObjectAsString(getDefaultModelObject());
        // if the value contains the EFAPSTMPTAG all tags from this component
        // will be moved to the subcomponent
        if (value != null && value.contains(IUserInterface.EFAPSTMPTAG)) {
            final StringBuilder tagBldr = new StringBuilder();
            final List<? extends Behavior> behaviors = getBehaviors();
            final ComponentTag tmpTag = new ComponentTag(_openTag);
            for (final Behavior behavior : behaviors) {
                behavior.onComponentTag(this, tmpTag);
            }
            final IValueMap map = tmpTag.getAttributes();
            for (final Entry<String, Object> entry : map.entrySet()) {
                final String key = entry.getKey();
                if (!"wicket:id".equals(key)) {
                    tagBldr.append(" ").append(key).append("=\"").append(entry.getValue()).append("\" ");
                }
            }
            // if no id is given add the id here
            if (!map.containsKey("id")) {
                tagBldr.append(" id=\"").append(getMarkupId()).append("\" ");
            }
            value = value.replace(IUserInterface.EFAPSTMPTAG, tagBldr);
        }
        super.replaceComponentTagBody(_markupStream, _openTag, value);
    }

    /**
     * Method is overwritten to prevent the annoing warnings from Component to come up.
     * The warning come up due to the reason that this component moves the tags from parent
     * element to its child.
     */
    @Override
    protected void onRender()
    {
        final IMarkupFragment markup = getMarkup();
        if (markup == null) {
            throw new MarkupException("Markup not found. Component: " + toString());
        }

        final MarkupStream markupStream = new MarkupStream(markup);

        // Get mutable copy of next tag
        final ComponentTag openTag = markupStream.getTag();
        final ComponentTag tag = openTag.mutable();

        // Call any tag handler
        onComponentTag(tag);

        // If we're an openclose tag
        if (!tag.isOpenClose() && !tag.isOpen()) {
            // We were something other than <tag> or <tag/>
            markupStream.throwMarkupException("Method renderComponent called on bad markup element: " + tag);
        }

        if (tag.isOpenClose() && openTag.isOpen()) {
            markupStream.throwMarkupException("You can not modify a open tag to open-close: " + tag);
        }

        markupStream.next();

        getMarkupSourcingStrategy().onComponentTagBody(this, markupStream, tag);
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.models;

import java.io.Serializable;
import java.util.Formatter;

import org.efaps.util.RandomUtil;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class EmbeddedLink
    implements Serializable
{

    /**
     * The Parameter Key if used for with Jasper Element Handler.
     */
    public static final String JASPER_PARAMETERKEY = EmbeddedLink.class + ".Key";

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Predefined tag elements that can be used for rendering.
     */
    enum TAG
    {

        /** The dashboard. */
        DASHBOARD(""),
        /** The jasper. */
        JASPER("");

        /** The html. */
        private String html;

        /**
         * Instantiates a new tag.
         *
         * @param _html the html
         */
        TAG(final String _html)
        {
            this.html = _html;
        }

        /**
         * Gets the html.
         *
         * @return the html
         */
        public String getHtml()
        {
            return this.html;
        }
    }

    /**
     * The instance key for the link.
     */
    private String instanceKey;

    /** The identifier. */
    private String identifier;

    /**
     * The id of this embedded link.
     */
    private final String id = RandomUtil.randomAlphanumeric(8);

    /**
     * The html tag to be used.
     */
    private String tag;

    /**
     * @param _instanceKey instanc key
     */
    public EmbeddedLink(final String _instanceKey)
    {
        this.instanceKey = _instanceKey;
    }

    /**
     * Getter method for the instance variable {@link #instanceKey}.
     *
     * @return value of instance variable {@link #instanceKey}
     */
    public String getInstanceKey()
    {
        return this.instanceKey;
    }

    /**
     * Setter method for instance variable {@link #instanceKey}.
     *
     * @param _instanceKey value for instance variable {@link #instanceKey}
     */
    public void setInstanceKey(final String _instanceKey)
    {
        this.instanceKey = _instanceKey;
    }

    /**
     * Getter method for the instance variable {@link #id}.
     *
     * @return value of instance variable {@link #id}
     */
    public String getId()
    {
        return this.id;
    }

    /**
     * Getter method for the instance variable {@link #tag}.
     *
     * @return value of instance variable {@link #tag}
     */
    public String getTag()
    {
        String ret = this.tag;
        final Formatter formatter = new Formatter();
        formatter.format(ret, getId());
        ret = formatter.toString();
        formatter.close();
        return ret;
    }

    /**
     * Setter method for instance variable {@link #tag}.
     *
     * @param _tag value for instance variable {@link #tag}
     */
    public void setTagHtml(final String _tag)
    {
        this.tag = _tag;
    }

    /**
     * Gets the identifier.
     *
     * @return the identifier
     */
    public String getIdentifier()
    {
        return this.identifier;
    }

    /**
     * Sets the identifier.
     *
     * @param _identifier the new identifier
     */
    public void setIdentifier(final String _identifier)
    {
        this.identifier = _identifier;
    }

    /**
     * @param _instanceKey instance key the link is wanted for
     * @return new Embeded Link
     */
    public static EmbeddedLink getJasperLink(final String _instanceKey)
    {
        final EmbeddedLink ret = new EmbeddedLink(_instanceKey);
        ret.setTagHtml(TAG.JASPER.getHtml());
        return ret;
    }

    /**
     * Gets the dashboard link.
     *
     * @param _instanceKey instance key the link is wanted for
     * @param _identifier the identifier
     * @return new Embeded Link
     */
    public static EmbeddedLink getDashboardLink(final String _instanceKey,
                                                final String _identifier)
    {
        final EmbeddedLink ret = new EmbeddedLink(_instanceKey);
        ret.setTagHtml(TAG.DASHBOARD.getHtml());
        ret.setIdentifier(_identifier);
        return ret;
    }
}


/*
 * Copyright 2015-2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.hod.client.config;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hp.autonomy.hod.client.api.authentication.AuthenticationToken;
import com.hp.autonomy.hod.client.api.authentication.EntityType;
import com.hp.autonomy.hod.client.api.authentication.TokenType;
import com.hp.autonomy.hod.client.token.TokenProxy;
import com.hp.autonomy.hod.client.token.TokenRepository;
import com.hp.autonomy.hod.client.token.TokenRepositoryException;
import retrofit.client.Header;
import retrofit.client.Response;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * Parses a response from HP Haven OnDemand. If a token is refreshed, this will update the token repository.
 */
class ResponseParser {

    private static final String TOKEN_HEADER_NAME = "refresh_token";

    private final TokenRepository tokenRepository;
    private final ObjectMapper objectMapper;

    /**
     * Create a new ResponseParser
     * @param tokenRepository The token repository to update if required
     * @param objectMapper The object mapper to use to convert the token and the response body
     */
    ResponseParser(final TokenRepository tokenRepository, final ObjectMapper objectMapper) {
        this.tokenRepository = tokenRepository;
        this.objectMapper = objectMapper;
    }

    /**
     * Parse the response into a type represented by the Class object. Checks for a refreshed token and updates the token
     * repository accordingly.
     * @param <T> The desired type of the response body
     * @param tokenProxy The token proxy to update in the token repository if required
     * @param clazz A class object representing the desired type of the response body
     * @param response The response to parse
     * @return An object representing the result from HP Haven OnDemand
     */
    <T> T parseResponse(final TokenProxy<?, ?> tokenProxy, final Class<T> clazz, final Response response) {
        return unsafeParseResponse(tokenProxy, objectMapper.constructType(clazz), response);
    }

    /**
     * Parse the response into a type represented by the TypeReference object. Checks for a refreshed token and updates
     * the token repository accordingly.
     * @param <T> The desired type of the response body
     * @param tokenProxy The token proxy to update in the token repository if required
     * @param typeReference A type reference object representing the desired type of the response body
     * @param response The response to parse
     * @return An object representing the result from HP Haven OnDemand
     */
    <T> T parseResponse(final TokenProxy<?, ?> tokenProxy, final TypeReference<T> typeReference, final Response response) {
        return unsafeParseResponse(tokenProxy, objectMapper.getTypeFactory().constructType(typeReference), response);
    }

    /**
     * Parse the response into a type represented by the JavaType object. Checks for a refreshed token and updates
     * the token repository accordingly. This method does not guarantee that the type parameter T represents the given
     * JavaType. If possible, use one of the safe parseResponse methods instead.
     * @param <T> The desired type of the response body
     * @param tokenProxy The token proxy to update in the token repository if required
     * @param type A JavaType representing the desired type of the response body
     * @param response The response to parse
     * @return An object representing the result from HP Haven OnDemand
     */
    <T> T unsafeParseResponse(final TokenProxy<?, ?> tokenProxy, final JavaType type, final Response response) {
        checkRefresh(tokenProxy, response);

        try {
            return objectMapper.readValue(response.getBody().in(), type);
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Checks the response headers for a refreshed authentication token then returns the response body as an input stream.
     * @param tokenProxy The token proxy to update in the token repository if required
     * @param response The response to read
     * @return The response body as an input stream
     */
    InputStream parseResponse(final TokenProxy<?, ?> tokenProxy, final Response response) {
        checkRefresh(tokenProxy, response);

        try {
            return response.getBody().in();
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    private <E extends EntityType, T extends TokenType> void checkRefresh(final TokenProxy<E, T> tokenProxy, final Response response) {
        final List<Header> headers = response.getHeaders();

        for(final Header header : headers) {
            if(TOKEN_HEADER_NAME.equals(header.getName())) {
                try {
                    final AuthenticationToken.Json parsedHeader = objectMapper.readValue(header.getValue(), AuthenticationToken.Json.class);
                    final AuthenticationToken<E, T> token = parsedHeader.buildToken(tokenProxy.getEntityType(), tokenProxy.getTokenType());
                    tokenRepository.update(tokenProxy, token);
                } catch (final IOException e) {
                    throw new TokenRepositoryException(e);
                }

                break;
            }
        }
    }

}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.models.objects;

import java.util.List;
import java.util.UUID;

import org.efaps.admin.event.EventDefinition;
import org.efaps.admin.event.EventType;
import org.efaps.admin.event.Parameter.ParameterValues;
import org.efaps.admin.event.Return;
import org.efaps.admin.event.Return.ReturnValues;
import org.efaps.admin.ui.AbstractCommand.SortDirection;
import org.efaps.admin.ui.AbstractUserInterfaceObject.TargetMode;
import org.efaps.admin.ui.field.Field;
import org.efaps.admin.ui.field.Field.Display;
import org.efaps.admin.ui.field.FieldTable;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author The eFasp Team
 * @version $Id$
 */
public class UIFieldTable
    extends UITable
    implements IFormElement
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(UIFieldTable.class);

    /**
     * Id of the FieldTable.
     */
    private final long fieldId;

    /**
     * Name of the FieldTable.
     */
    private final String name;

    /**
     * Stores if the table is the first table inside a form. because the first table adds some things to the page that
     * works for all tables inside the same page.
     */
    private boolean firstTable = true;

    /**
     * @param _commanduuid uuid of the command
     * @param _instanceKey key to the instance
     * @param _fieldTable fieltable
     * @throws EFapsException on error
     */
    public UIFieldTable(final UUID _commanduuid,
                        final String _instanceKey,
                        final FieldTable _fieldTable)
        throws EFapsException
    {
        super(_commanduuid, _instanceKey);
        setTableUUID(_fieldTable.getTargetTable().getUUID());
        this.fieldId = _fieldTable.getId();
        this.name = _fieldTable.getName();
        setShowCheckBoxes(_fieldTable.isTargetShowCheckBoxes());
        setDnD(!"true".equalsIgnoreCase(_fieldTable.getProperty("TargetDeactivateDnD")));
        setEnforceSorted("true".equalsIgnoreCase(_fieldTable.getProperty("TargetEnforceSorted")));
        try {
            if (Context.getThreadContext().containsUserAttribute(getCacheKey(UserCacheKey.SORTKEY))) {
                setSortKey(Context.getThreadContext().getUserAttribute(getCacheKey(UserCacheKey.SORTKEY)));
            }
            if (Context.getThreadContext().containsUserAttribute(getCacheKey(UserCacheKey.SORTDIRECTION))) {
                setSortDirection(SortDirection.getEnum(Context.getThreadContext()
                                .getUserAttribute(getCacheKey(UserCacheKey.SORTDIRECTION))));
            }
        } catch (final EFapsException e) {
            // we don't throw an error because this are only Usersettings
            UIFieldTable.LOG.error("error during the retrieve of UserAttributes", e);
        }
    }

    /**
     * Getter method for instance variable {@link #firstTable}.
     *
     * @return value of instance variable {@link #firstTable}
     */
    public boolean isFirstTable()
    {
        return this.firstTable;
    }

    /**
     * Setter method for instance variable {@link #firstTable}.
     *
     * @param _firstTable value for instance variable {@link #firstTable}
     */
    public void setFirstTable(final boolean _firstTable)
    {
        this.firstTable = _firstTable;
    }

    /**
     * Getter method for instance variable {@link #name}.
     *
     * @return value of instance variable {@link #name}
     */
    public String getName()
    {
        return this.name;
    }

    /**
     * @return true if the check boxes must be shown, other false
     *         is returned.
     * @see #showCheckBoxes
     */
    @Override
    public boolean isShowCheckBoxes()
    {
        return getShowCheckBoxes();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @SuppressWarnings("unchecked")
    protected List<Instance> getInstanceList()
        throws EFapsException
    {
        final List<Return> ret = FieldTable.get(this.fieldId).executeEvents(EventType.UI_TABLE_EVALUATE,
                        ParameterValues.INSTANCE, getInstance());
        final List<Instance> lists = (List<Instance>) ret.get(0).get(ReturnValues.VALUES);
        return lists;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getCacheKey(final UserCacheKey _key)
    {
        return super.getCommandUUID() + "-" + this.name + "-" + _key.getValue();
    }

    /**
     * Method to get the events that are related to this UITable.
     *
     * @param _eventType eventype to get
     * @return List of events
     */
    @Override
    protected List<EventDefinition> getEvents(final EventType _eventType)
    {
        return Field.get(this.fieldId).getEvents(_eventType);
    }

    /**
     * Get the Display of the Field this StructurBrowser is bedded in.
     * @param _mode target mode the display will be evaluate for
     * @return Display
     */
    public Display getFieldDisplay(final TargetMode _mode)
    {
        return FieldTable.get(this.fieldId).getDisplay(_mode);
    }

    /**
     * In create or edit mode this FieldTable is editable,
     * if the Field this StructurBroeser is bedded in is editable also.
     *
     * @return is this StructurBrowser editable.
     */
    @Override
    public boolean isEditable()
    {
        return getFieldDisplay(getMode()).equals(Display.EDITABLE) && (isCreateMode() || isEditMode());
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.servlet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.efaps.admin.program.bundle.BundleInterface;
import org.efaps.admin.program.bundle.BundleMaker;
import org.efaps.ci.CIAdminProgram;
import org.efaps.db.Checkout;
import org.efaps.db.MultiPrintQuery;
import org.efaps.db.QueryBuilder;
import org.efaps.db.SelectBuilder;
import org.efaps.ui.wicket.util.Configuration;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheObjectInterface;
import org.efaps.util.cache.CacheReloadException;
import org.efaps.util.cache.InfinispanCache;
import org.infinispan.Cache;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Servlet that serves the static content for the WebApp.
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class StaticContentServlet
    extends HttpServlet
{
    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(StaticContentServlet.class);

    /**
     * Name of the Cache.
     */
    private static final String CACHENAME = StaticContentServlet.class.getName() + ".Cache";

    /**
     * Used as null for caching purpose.
     */
    private static ContentMapper NULL = new ContentMapper(null, null, null, Long.valueOf(0), Long.valueOf(0));

    /**
     * The method checks the image from the user interface image object out and
     * returns them in a output stream to the web client. The name of the user
     * interface image object must given as name at the end of the path.
     *
     * @param _req request variable
     * @param _res response variable
     * @throws ServletException on error
     *
     */
    @Override
    protected void doGet(final HttpServletRequest _req,
                         final HttpServletResponse _res)
        throws ServletException
    {
        String contentName = _req.getRequestURI();
        contentName = contentName.substring(contentName.lastIndexOf('/') + 1);
        try {
            final Cache<String, ContentMapper> cache = InfinispanCache.get().<String, ContentMapper>getCache(
                            StaticContentServlet.CACHENAME);
            final int cacheDuration = Configuration.getAttributeAsInteger(Configuration.ConfigAttribute.CACHE_DURATION);

            if (!cache.containsKey(contentName)) {
                final QueryBuilder queryBldr = new QueryBuilder(CIAdminProgram.StaticCompiled);
                queryBldr.addWhereAttrEqValue(CIAdminProgram.StaticCompiled.Name, contentName);
                final MultiPrintQuery multi = queryBldr.getPrint();
                final SelectBuilder selLabel = new SelectBuilder().file().label();
                final SelectBuilder selLength = new SelectBuilder().file().length();
                multi.addSelect(selLabel, selLength);
                multi.addAttribute(CIAdminProgram.StaticCompiled.Name,
                                CIAdminProgram.StaticCompiled.OID,
                                CIAdminProgram.StaticCompiled.Modified);
                multi.executeWithoutAccessCheck();
                if (multi.next()) {
                    final String name = multi.<String>getAttribute(CIAdminProgram.StaticCompiled.Name);
                    final String file = multi.<String>getSelect(selLabel);
                    final Long filelength = multi.<Long>getSelect(selLength);
                    final DateTime datetime = multi.<DateTime>getAttribute(CIAdminProgram.StaticCompiled.Modified);

                    final ContentMapper mapper = new ContentMapper(name, file, multi.getCurrentInstance().getOid(),
                                    filelength, datetime.getMillis());
                    cache.put(contentName, mapper);
                } else {
                    cache.put(contentName, StaticContentServlet.NULL);
                }
            }
            final ContentMapper contentMapper = cache.get(contentName);
            if (contentMapper != null && !contentMapper.equals(StaticContentServlet.NULL)) {
                final Checkout checkout = new Checkout(contentMapper.oid);

                _res.setContentType(getServletContext().getMimeType(contentMapper.file));
                _res.setDateHeader("Last-Modified", contentMapper.time);
                _res.setDateHeader("Expires", System.currentTimeMillis()
                                + (cacheDuration * 1000));
                _res.setHeader("Cache-Control", "max-age=" + cacheDuration);

                if (supportsCompression(_req)) {
                    _res.setHeader("Content-Encoding", "gzip");

                    final ByteArrayOutputStream bytearray = new ByteArrayOutputStream();
                    final GZIPOutputStream zout = new GZIPOutputStream(bytearray);
                    checkout.execute(zout);
                    zout.close();
                    final byte[] b = bytearray.toByteArray();
                    bytearray.close();
                    _res.getOutputStream().write(b);
                    checkout.close();
                } else {
                    _res.setContentLength((int) contentMapper.filelength);
                    checkout.execute(_res.getOutputStream());
                }
            } else if (BundleMaker.containsKey(contentName)) {
                final BundleInterface bundle = BundleMaker.getBundle(contentName);

                _res.setContentType(bundle.getContentType());
                _res.setDateHeader("Last-Modified", bundle.getCreationTime());
                _res.setDateHeader("Expires", System.currentTimeMillis()
                                + (cacheDuration * 1000));
                _res.setHeader("Cache-Control", "max-age=" + cacheDuration);
                _res.setHeader("Content-Encoding", "gzip");

                int bytesRead;
                final byte[] buffer = new byte[2048];

                final InputStream in = bundle.getInputStream(supportsCompression(_req));
                while ((bytesRead = in.read(buffer)) != -1) {
                    _res.getOutputStream().write(buffer, 0, bytesRead);
                }
            }
        } catch (final IOException e) {
            StaticContentServlet.LOG.error("while reading Static Content", e);
            throw new ServletException(e);
        } catch (final CacheReloadException e) {
            StaticContentServlet.LOG.error("while reading Static Content", e);
            throw new ServletException(e);
        } catch (final EFapsException e) {
            StaticContentServlet.LOG.error("while reading Static Content", e);
            throw new ServletException(e);
        }
    }

    /**
     * @param _req request to be analysed
     * @return true  if compression is supported else false
     */
    private boolean supportsCompression(final HttpServletRequest _req)
    {
        boolean ret = false;
        final String accencoding = _req.getHeader("Accept-Encoding");
        if (accencoding != null) {
            ret = accencoding.indexOf("gzip") >= 0;
        }
        return ret;
    }

    /**
     * The class is used to map from the administrational image name
     * to the image file name and image object id.
     */
    private static final class ContentMapper
        implements CacheObjectInterface
    {
        /**
         * The instance variable stores the administational name of the image.
         */
        private final String name;

        /**
         * The instance variable stores the file name of the image.
         */
        private final String file;

        /**
         * The instance variable stores the object id of the image.
         */
        private final String oid;

        /**
         * Length of the file.
         */
        private final long filelength;

        /**
         * Current time.
         */
        private final Long time;

        /**
         * @param _name administrational name of the image
         * @param _file file name of the image
         * @param _oid object id of the image
         * @param _filelength length of the file
         * @param _time current time
         */
        private ContentMapper(final String _name,
                              final String _file,
                              final String _oid,
                              final Long _filelength,
                              final Long _time)
        {
            this.name = _name;
            this.oid = _oid;
            this.file = _file;
            this.filelength = _filelength;
            this.time = _time;
        }

        /**
         * This is the getter method for instance variable {@link #name}.
         *
         * @return value of instance variable {@link #name}
         * @see #name
         */
        public String getName()
        {
            return this.name;
        }

        /**
         * The method is not needed in this cache implementation,
         * but to implemente interface {@link CacheInterface} the
         * method is required.
         *
         * @return always null
         */
        public UUID getUUID()
        {
            return null;
        }

        /**
         * The method is not needed in this cache implementation,
         * but to implemente interface {@link CacheInterface} the
         * method is required.
         *
         * @return always 0
         */
        public long getId()
        {
            return 0;
        }
    }
}


/*
 * Copyright 2003 - 2017 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.efaps.ui.wicket.components.links;

import org.apache.wicket.Page;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.form.ILabelProvider;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.efaps.admin.ui.AbstractCommand;
import org.efaps.admin.ui.Menu;
import org.efaps.db.Instance;
import org.efaps.ui.wicket.components.menutree.CallUpdateTreeMenuBehavior;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.field.FieldConfiguration;
import org.efaps.ui.wicket.models.objects.PagePosition;
import org.efaps.ui.wicket.models.objects.UIForm;
import org.efaps.ui.wicket.models.objects.UIStructurBrowser;
import org.efaps.ui.wicket.models.objects.UITable;
import org.efaps.ui.wicket.pages.content.form.FormPage;
import org.efaps.ui.wicket.pages.content.structurbrowser.StructurBrowserPage;
import org.efaps.ui.wicket.pages.content.table.TablePage;
import org.efaps.ui.wicket.pages.error.ErrorPage;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class extends a Link to work inside a content container. Used also by the
 * StructurBrowserTable. Updates the menu and the page itself.
 *
 * @author The eFaps Team
 */
public class MenuContentLink
    extends Link<AbstractUIField>
    implements ILabelProvider<String>
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(MenuContentLink.class);

    /**
     * Content for this link.
     */
    private final String content;

    /**
     * Constructor.
     *
     * @param _wicketId wicket id of this component
     * @param _model model for thid component
     * @param _content the content
     */
    public MenuContentLink(final String _wicketId,
                           final IModel<AbstractUIField> _model,
                           final String _content)
    {
        super(_wicketId, _model);
        this.content = _content;
    }

    /**
     * Getter method for the instance variable {@link #config}.
     *
     * @return value of instance variable {@link #config}
     */
    protected FieldConfiguration getConfig()
    {
        return ((AbstractUIField) getDefaultModelObject()).getFieldConfiguration();
    }

    /**
     * Getter method for the instance variable {@link #content}.
     *
     * @return value of instance variable {@link #content}
     */
    protected String getContent()
    {
        return this.content;
    }

    @Override
    public IModel<String> getLabel()
    {
        String ret = "NONE";
        try {
            ret = ((AbstractUIField) getDefaultModelObject()).getLabel();
        } catch (final EFapsException e) {
            MenuContentLink.LOG.error("Catched error on evaluating label: {}", this);
        }
        return Model.of(ret);
    }

    /**
     * The tag must be overwritten.
     *
     * @param _tag tag to write.
     */
    @Override
    protected void onComponentTag(final ComponentTag _tag)
    {
        super.onComponentTag(_tag);
        _tag.setName("a");
        _tag.put("href", "#");
        onComponentTagInternal(_tag);
    }

    /**
     * Add to the tag.
     * @param _tag tag to write
     */
    protected void onComponentTagInternal(final ComponentTag _tag)
    {
        _tag.put("name", getConfig().getName());
        _tag.append("style", "text-align:" + getConfig().getAlign(), ";");
    }

    @Override
    public void onComponentTagBody(final MarkupStream _markupStream,
                                   final ComponentTag _openTag)
    {
        Object ret = null;
        try {
            if (this.content == null) {
                final AbstractUIField uiField = (AbstractUIField) getDefaultModelObject();
                ret = uiField.getValue().getReadOnlyValue(uiField.getParent().getMode());
            } else {
                ret = this.content;
            }
        } catch (final EFapsException e) {
            MenuContentLink.LOG.error("Catched error on setting tag body for: {}", this);
        }
        replaceComponentTagBody(_markupStream, _openTag, ret == null ? "" : String.valueOf(ret));
    }

    @Override
    public void onClick()
    {
        final AbstractUIField uiField = (AbstractUIField) getDefaultModelObject();
        Instance instance = null;
        if (uiField.getInstanceKey() != null) {
            AbstractCommand menu = null;
            try {
                instance = uiField.getInstance();
                menu = Menu.getTypeTreeMenu(instance.getType());
                // CHECKSTYLE:OFF
            } catch (final Exception e) {
                throw new RestartResponseException(new ErrorPage(e));
            } // CHECKSTYLE:ON
            if (menu == null) {
                final Exception ex = new Exception("no tree menu defined for type " + instance.getType().getName());
                throw new RestartResponseException(new ErrorPage(ex));
            }

            for (final AbstractCommand childcmd : ((Menu) menu).getCommands()) {
                if (childcmd.isDefaultSelected()) {
                    menu = childcmd;
                    break;
                }
            }

            Page page;
            try {
                if (menu.getTargetTable() != null) {
                    if (menu.getTargetStructurBrowserField() == null) {
                        final UITable uiTable = new UITable(menu.getUUID(), uiField.getInstanceKey()).setPagePosition(
                                        PagePosition.TREE);
                        page = new TablePage(Model.of(uiTable), getPage().getPageReference());
                    } else {
                        final UIStructurBrowser uiStructurBrowser = new UIStructurBrowser(menu.getUUID(), uiField
                                        .getInstanceKey()).setPagePosition(PagePosition.TREE);
                        page = new StructurBrowserPage(Model.of(uiStructurBrowser), getPage().getPageReference());
                    }
                } else {
                    final UIForm uiForm = new UIForm(menu.getUUID(), uiField.getInstanceKey()).setPagePosition(
                                    PagePosition.TREE);
                    page = new FormPage(Model.of(uiForm));
                }
            } catch (final EFapsException e) {
                page = new ErrorPage(e);
            }
            page.add(new CallUpdateTreeMenuBehavior(instance));
            getRequestCycle().setResponsePage(page);
        }
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.models.field.set;

import org.efaps.admin.datamodel.ui.UIValue;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.field.FieldConfiguration;
import org.efaps.ui.wicket.models.field.FieldSetConfiguration;
import org.efaps.ui.wicket.models.field.ISortable;
import org.efaps.ui.wicket.models.objects.AbstractUIObject;
import org.efaps.util.EFapsException;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class UIFieldSetValue
    extends AbstractUIField
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Set the value belongs to.
     */
    private final UIFieldSet cellSet;

    /**
     * @param _instanceKey key of the instacne
     * @param _parent parent object
     * @param _set set
     * @param _value value
     * @throws EFapsException on error
     */
    public UIFieldSetValue(final AbstractUIObject _parent,
                           final String _instanceKey,
                           final UIFieldSet _set,
                           final UIValue _value)
        throws EFapsException
    {
        super(_parent, _instanceKey, _value);
        this.cellSet = _set;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected FieldConfiguration getNewFieldConfiguration()
        throws EFapsException
    {
        final FieldConfiguration ret;
        if (getValue().getAttribute() == null) {
            ret = super.getNewFieldConfiguration();
        } else {
            ret = new FieldSetConfiguration(getValue().getField().getId(), getValue().getAttribute().getId());
        }
        return ret;
    }

    /**
     * Getter method for the instance variable {@link #cellSet}.
     *
     * @return value of instance variable {@link #cellSet}
     */
    public UIFieldSet getCellSet()
    {
        return this.cellSet;
    }

    @Override
    public Comparable<?> getCompareValue()
    {
        return null;
    }

    @Override
    public int compareTo(final ISortable _o)
    {
        return 0;
    }
}


/*
 * Copyright 2015-2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.hod.client.job;

import com.hp.autonomy.hod.client.api.authentication.TokenType;
import com.hp.autonomy.hod.client.error.HodError;
import com.hp.autonomy.hod.client.error.HodErrorCode;
import com.hp.autonomy.hod.client.error.HodErrorException;
import com.hp.autonomy.hod.client.token.TokenProxy;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.Duration;
import org.joda.time.LocalDateTime;

import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Runnable which will poll the HP Haven OnDemand job status API until the job has finished or failed
 * @param <T> The type that will be returned if the job complete successfully
 */
@Slf4j
public class PollingJobStatusRunnable<T> implements Runnable {

    private static final int MAX_TRIES = 3;
    private static final int WAIT_SECONDS = 2;

    private final Set<HodErrorCode> DO_NOT_RETRY_CODES = EnumSet.of(
            HodErrorCode.API_KEY_REQUIRED,
            HodErrorCode.INVALID_API_KEY,
            HodErrorCode.UNKNOWN_API_KEY,
            HodErrorCode.UNAUTHORIZED_API_KEY,
            HodErrorCode.USER_ACCOUNT_DISABLED,
            HodErrorCode.INVALID_JOB_ID
    );

    private final TokenProxy<?, TokenType.Simple> tokenProxy;
    private final JobId jobId;
    private final HodJobCallback<T> callback;
    private final ScheduledExecutorService executorService;
    private final JobService<? extends JobStatus<T>> jobService;
    private final LocalDateTime timeout;

    private final AtomicInteger tries = new AtomicInteger(0);

    /**
     * Creates a new PollingJobStatusRunnable using a token provided by a {@link com.hp.autonomy.hod.client.token.TokenProxyService}
     * @param jobId The ID of the job
     * @param callback The callback that will be called with the result
     * @param executorService The executor service responsible for running the runnable
     */
    public PollingJobStatusRunnable(final Duration timeout, final JobId jobId, final HodJobCallback<T> callback, final ScheduledExecutorService executorService, final JobService<? extends JobStatus<T>> jobService) {
        this(null, timeout, jobId, callback, executorService, jobService);
    }

    /**
     * Creates a new PollingJobStatusRunnable using the given token proxy
     * @param tokenProxy The token proxy used to submit the job
     * @param jobId The ID of the job
     * @param callback The callback that will be called with the result
     * @param executorService The executor service responsible for running the runnable
     */
    public PollingJobStatusRunnable(final TokenProxy<?, TokenType.Simple> tokenProxy, final Duration timeout, final JobId jobId, final HodJobCallback<T> callback, final ScheduledExecutorService executorService, final JobService<? extends JobStatus<T>> jobService) {
        this.tokenProxy = tokenProxy;
        this.jobId = jobId;
        this.callback = callback;
        this.executorService = executorService;
        this.jobService = jobService;
        this.timeout = timeout != null ? LocalDateTime.now().plus(timeout) : null;
    }

    /**
     * Checks the status of the job. If the job has not finished, the runnable will schedule itself to run again after a
     * short wait
     */
    @Override
    public void run() {
        try {
            log.debug("About to check status for jobId {}", jobId);

            final JobStatus<T> jobStatus;

            if (tokenProxy != null) {
                jobStatus = jobService.getJobStatus(tokenProxy, jobId);
            }
            else {
                jobStatus = jobService.getJobStatus(jobId);
            }

            final Status jobStatusStatus = jobStatus.getStatus();

            if (jobStatusStatus == Status.FINISHED || jobStatusStatus == Status.FAILED) {
                for (final Action<T> action : jobStatus.getActions()) {
                    final Status status = action.getStatus();

                    if (status == Status.FINISHED) {
                        log.debug("Found a finished action, calling callback");

                        callback.success(action.getResult());
                    }
                    else if (status == Status.FAILED) {
                        log.debug("Found a failed action, calling callback");

                        for (final HodError error : action.getErrors()) {
                            log.debug("Error callback called with: {}", error);

                            callback.error(error.getErrorCode());
                        }
                    }
                }
            }
            else if (timeout != null && timeout.isBefore(LocalDateTime.now())) {
                callback.timeout();
                log.debug("Timeout callback called");
            }
            else {
                log.debug("Not finished or failed, retrying");

                // we got a status successfully, so reset the counter
                tries.set(0);

                executorService.schedule(this, WAIT_SECONDS, TimeUnit.SECONDS);
            }
        } catch (final HodErrorException e) {
            log.error("Error retrieving job status for jobId: {}", jobId);
            log.error("Cause:", e);

            if (DO_NOT_RETRY_CODES.contains(e.getErrorCode())) {
                log.error("Unrecoverable error, will not retry");

                callback.error(e.getErrorCode());
            }
            else if (tries.get() >= MAX_TRIES) {
                log.error("Max retries reached, will not retry");

                callback.error(e.getErrorCode());
            }
            else {
                log.error("Retrying");

                tries.incrementAndGet();

                executorService.schedule(this, WAIT_SECONDS, TimeUnit.SECONDS);
            }
        } catch (final RuntimeException e) {
            log.error("Error retrieving job status for jobId: {}", jobId);
            log.error("Cause:", e);

            callback.handleException(e);
        }
    }
}


/*
 * Copyright 2003 - 2017 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.util.string.StringValue;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public final class ParameterUtil
{
    /**
     * Instantiates a new parameter util.
     */
    private ParameterUtil()
    {
    }

    /**
     * Get an array for the StringValues.
     *
     * @param _parameters IRequestParameters
     * @return always StringArray, if parameter does not exist an empty
     *         StringArray
     */
    public static Map<String, String[]> parameter2Map(final IRequestParameters _parameters)
    {
        final Map<String, String[]> ret = new HashMap<>();
        for (final String name : _parameters.getParameterNames()) {
            ret.put(name, ParameterUtil.parameter2Array(_parameters, name));
        }
        return ret;
    }

    /**
     * Get an array for the StringValues.
     *
     * @param _parameters IRequestParameters
     * @param _parameterName name of the Paramaters
     * @return always StringArray, if parameter does not exist an empty
     *         StringArray
     */
    public static String[] parameter2Array(final IRequestParameters _parameters,
                                           final String _parameterName)
    {
        final List<StringValue> values = _parameters.getParameterValues(_parameterName);
        return ParameterUtil.stringValues2Array(values);
    }

    /**
     * Get an array for the StringValues.
     *
     * @param _values the values
     * @return always StringArray, if parameter does not exist an empty
     *         StringArray
     */
    public static String[] stringValues2Array(final List<StringValue> _values)
    {
        final String[] ret;
        if (_values != null) {
            ret = new String[_values.size()];
            int i = 0;
            for (final StringValue value : _values) {
                ret[i] = value.toString();
                i++;
            }
        } else {
            ret = new String[0];
        }
        return ret;
    }
}