/*
 * Copyright 2016-2017 Steinar Bang
 *
 * 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 no.priv.bang.ukelonn.impl;

import javax.servlet.Filter;
import javax.servlet.ServletException;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.config.Ini;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.web.config.IniFilterChainResolverFactory;
import org.apache.shiro.web.config.WebIniSecurityManagerFactory;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;

import no.priv.bang.ukelonn.UkelonnDatabase;

/**
 * This is an OSGi DS component that provides a {@link Filter} service.  This filter service will
 * be put in front of the servlet provided by the {@link UkelonnServletProvider}, and
 * will handle authentication and authorization from the servlet.
 *
 * @author Steinar Bang
 *
 */
@Component(
    property= {
        HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN+"=/ukelonn/*",
        "servletNames=ukelonn"},
    service=Filter.class,
    immediate=true
)
public class UkelonnShiroFilter extends AbstractShiroFilter {

    private static final Ini INI_FILE = new Ini();
    static {
        // Can't use the Ini.fromResourcePath(String) method because it can't find "shiro.ini" on the classpath in an OSGi context
        INI_FILE.load(UkelonnShiroFilter.class.getClassLoader().getResourceAsStream("shiro.ini"));
    }
    private static UkelonnShiroFilter instance;
    private UkelonnDatabase database;

    public UkelonnShiroFilter() {
        instance = this;
    }

    @Activate
    public void activate() throws ServletException {
        WebIniSecurityManagerFactory securityManagerFactory = new WebIniSecurityManagerFactory(INI_FILE);
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) securityManagerFactory.createInstance();
        setSecurityManager(securityManager);
        UkelonnRealm realm = createRealmProgramaticallyBecauseOfShiroIniClassCastException();
        securityManager.setRealm(realm);

        IniFilterChainResolverFactory filterChainResolverFactory = new IniFilterChainResolverFactory(INI_FILE);
        FilterChainResolver resolver = filterChainResolverFactory.createInstance();
        if (resolver != null) {
            setFilterChainResolver(resolver);
        }
    }

    @Reference
    public void setUkelonnDatabase(UkelonnDatabase database) {
        this.database = database;
    }

    public UkelonnDatabase getDatabase() {
        return database;
    }

    public static UkelonnShiroFilter getInstance() {
        return instance;
    }

    /**
     * Creating the {@link UkelonnRealm} was moved out of shiro.ini and into
     * code, because the code interpreting the shiro.ini was unable to
     * cast {@link UkelonnRealm} to {@link Realm}.
     *
     * @return The realm that is used to authenticate and authorize ukelonn users
     */
    private UkelonnRealm createRealmProgramaticallyBecauseOfShiroIniClassCastException() {
        UkelonnRealm realm = new UkelonnRealm();
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("SHA-256");
        credentialsMatcher.setStoredCredentialsHexEncoded(false); // base64 encoding, not hex
        credentialsMatcher.setHashIterations(1024);
        realm.setCredentialsMatcher(credentialsMatcher);
        return realm;
    }

}

@@ -661,48 +661,8 @@
 er;%0A
-import javax.servlet.ServletException;%0A%0A
 impo
@@ -2420,32 +2420,8 @@
 te()
- throws ServletException
  %7B%0A 

Remove declaration of exception that is no longer thrown from UkelonnShiroFilter.activate().