001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.nuxeo.runtime.api.login; 017 018import java.util.concurrent.atomic.AtomicInteger; 019 020import javax.security.auth.login.AppConfigurationEntry; 021import javax.security.auth.login.Configuration; 022 023import org.apache.commons.logging.LogFactory; 024 025public class LoginConfiguration extends Configuration { 026 027 public static final LoginConfiguration INSTANCE = new LoginConfiguration(); 028 029 protected final AtomicInteger counter = new AtomicInteger(0); 030 031 public interface Provider { 032 033 public AppConfigurationEntry[] getAppConfigurationEntry(String name); 034 035 } 036 037 protected final InheritableThreadLocal<Provider> holder = new InheritableThreadLocal<Provider>() { 038 @Override 039 protected Provider initialValue() { 040 return context.provider; 041 }; 042 }; 043 044 @Override 045 public AppConfigurationEntry[] getAppConfigurationEntry(String name) { 046 AppConfigurationEntry[] appConfigurationEntry = holder.get().getAppConfigurationEntry(name); 047 if (appConfigurationEntry == null) { 048 appConfigurationEntry = context.parent.getAppConfigurationEntry(name); 049 } 050 return appConfigurationEntry; 051 052 } 053 054 @Override 055 public void refresh() { 056 context.parent.refresh(); 057 } 058 059 protected class InstallContext { 060 protected final Configuration parent = Configuration.getConfiguration(); 061 062 protected final Provider provider; 063 064 protected final Thread thread = Thread.currentThread(); 065 066 protected final Throwable stacktrace = new Throwable(); 067 068 protected InstallContext(Provider provider) { 069 this.provider = provider; 070 } 071 072 @Override 073 public String toString() { 074 return "Login Installation Context [parent=" + parent + ", thread=" + thread + "]"; 075 } 076 077 } 078 079 protected InstallContext context; 080 081 public void install(Provider provider) { 082 holder.set(provider); 083 int count = counter.incrementAndGet(); 084 if (count == 1) { 085 context = new InstallContext(provider); 086 Configuration.setConfiguration(this); 087 LogFactory.getLog(LoginConfiguration.class).trace("installed login configuration", context.stacktrace); 088 } 089 } 090 091 public void uninstall() { 092 holder.remove(); 093 int count = counter.decrementAndGet(); 094 if (count == 0) { 095 LogFactory.getLog(LoginConfiguration.class).trace("uninstalled login configuration " + context.thread, 096 context.stacktrace); 097 Configuration.setConfiguration(context.parent); 098 context = null; 099 } 100 } 101 102 /** 103 * @since 5.9.5 104 */ 105 public void cleanupThisThread() { 106 holder.remove(); 107 } 108 109}