Author: markt
Date: Wed Feb 10 21:26:46 2016
New Revision: 1729742
URL: http://svn.apache.org/viewvc?rev=1729742&view=rev
Log:
Next stage of JASPIC implementation (excluding the changes to AuthenticatorBase
to integrate JASPIC support).
With the necessary integration, this code passes the javaee7-samples JASPIC
unit tests as far as the lifecycle tests (which currently all fail).
Added:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
(with props)
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
(with props)
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
(with props)
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java
(with props)
Modified:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestPersistentProviderRegistrations.java
tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java
Added:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java?rev=1729742&view=auto
==============================================================================
---
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
(added)
+++
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
Wed Feb 10 21:26:46 2016
@@ -0,0 +1,298 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.catalina.authenticator.jaspic;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.security.auth.message.config.AuthConfigFactory;
+import javax.security.auth.message.config.AuthConfigProvider;
+import javax.security.auth.message.config.RegistrationListener;
+
+import org.apache.catalina.Globals;
+import
org.apache.catalina.authenticator.jaspic.PersistentProviderRegistrations.Provider;
+import
org.apache.catalina.authenticator.jaspic.PersistentProviderRegistrations.Providers;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
+
+public class AuthConfigFactoryImpl extends AuthConfigFactory {
+
+ private static final Log log =
LogFactory.getLog(AuthConfigFactoryImpl.class);
+ private static final StringManager sm =
StringManager.getManager(AuthConfigFactoryImpl.class);
+
+ private static final String CONFIG_PATH = "conf/jaspic-providers.xml";
+ private static final File CONFIG_FILE =
+ new File(System.getProperty(Globals.CATALINA_BASE_PROP),
CONFIG_PATH);
+ private static final Object CONFIG_FILE_LOCK = new Object();
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ private final Map<String,RegistrationContextImpl> registrations = new
ConcurrentHashMap<>();
+
+
+ // TODO: Handle parallel deployment. Can this be done if web application is
+ // not aware it is being deployed in parallel?
+ public AuthConfigFactoryImpl() {
+ loadPersistentRegistrations();
+ }
+
+
+ @Override
+ public AuthConfigProvider getConfigProvider(String layer, String
appContext,
+ RegistrationListener listener) {
+ String registrationID = getRegistrarionID(layer, appContext);
+ RegistrationContextImpl registrationContext =
registrations.get(registrationID);
+ if (registrationContext != null) {
+ registrationContext.addListener(null);
+ return registrationContext.getProvider();
+ }
+ return null;
+ }
+
+
+ @Override
+ public String registerConfigProvider(String className,
+ @SuppressWarnings("rawtypes") Map properties, String layer, String
appContext,
+ String description) {
+ String registrationID =
+ doRegisterConfigProvider(className, properties, layer,
appContext, description);
+ savePersistentRegistrations();
+ return registrationID;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private String doRegisterConfigProvider(String className,
+ @SuppressWarnings("rawtypes") Map properties, String layer, String
appContext,
+ String description) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("authConfigFactoryImpl.registerClass",
+ className, layer, appContext));
+ }
+ Class<?> clazz;
+ AuthConfigProvider provider = null;
+ try {
+ clazz = Class.forName(className, true,
Thread.currentThread().getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ // Ignore so the re-try below can proceed
+ }
+ try {
+ clazz = Class.forName(className);
+ Constructor<?> constructor = clazz.getConstructor(Map.class,
AuthConfigFactory.class);
+ provider = (AuthConfigProvider)
constructor.newInstance(properties, this);
+ } catch (ClassNotFoundException | NoSuchMethodException |
InstantiationException |
+ IllegalAccessException | IllegalArgumentException |
InvocationTargetException e) {
+ throw new SecurityException(e);
+ }
+
+ String registrationID = getRegistrarionID(layer, appContext);
+ registrations.put(registrationID,
+ new RegistrationContextImpl(layer, appContext, description,
true, provider, properties));
+ return registrationID;
+ }
+
+
+ @Override
+ public String registerConfigProvider(AuthConfigProvider provider, String
layer,
+ String appContext, String description) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("authConfigFactoryImpl.registerInstance",
+ provider.getClass().getName(), layer, appContext));
+ }
+ String registrationID = getRegistrarionID(layer, appContext);
+ registrations.put(registrationID,
+ new RegistrationContextImpl(layer, appContext, description,
false, provider, null));
+ return registrationID;
+ }
+
+
+ @Override
+ public boolean removeRegistration(String registrationID) {
+ return registrations.remove(registrationID) != null;
+ }
+
+
+ @Override
+ public String[] detachListener(RegistrationListener listener, String
layer, String appContext) {
+ String registrationID = getRegistrarionID(layer, appContext);
+ RegistrationContextImpl registrationContext =
registrations.get(registrationID);
+ if (registrationContext.removeListener(listener)) {
+ return new String[] { registrationID };
+ }
+ return EMPTY_STRING_ARRAY;
+ }
+
+
+ @Override
+ public String[] getRegistrationIDs(AuthConfigProvider provider) {
+ if (provider == null) {
+ return registrations.keySet().toArray(EMPTY_STRING_ARRAY);
+ } else {
+ List<String> results = new ArrayList<>();
+ for (Entry<String,RegistrationContextImpl> entry :
registrations.entrySet()) {
+ if (provider.equals(entry.getValue().getProvider())) {
+ results.add(entry.getKey());
+ }
+ }
+ return results.toArray(EMPTY_STRING_ARRAY);
+ }
+ }
+
+
+ @Override
+ public RegistrationContext getRegistrationContext(String registrationID) {
+ return registrations.get(registrationID);
+ }
+
+
+ @Override
+ public void refresh() {
+ loadPersistentRegistrations();
+ }
+
+
+ private String getRegistrarionID(String layer, String appContext) {
+ return layer + ":" + appContext;
+ }
+
+
+ private void loadPersistentRegistrations() {
+ synchronized (CONFIG_FILE_LOCK) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("authConfigFactoryImpl.load",
+ CONFIG_FILE.getAbsolutePath()));
+ }
+ if (!CONFIG_FILE.isFile()) {
+ return;
+ }
+ Providers providers =
PersistentProviderRegistrations.loadProviders(CONFIG_FILE);
+ for (Provider provider : providers.getProviders()) {
+ doRegisterConfigProvider(provider.getClassName(),
provider.getProperties(),
+ provider.getLayer(), provider.getAppContext(),
provider.getDescription());
+ }
+ }
+ }
+
+
+ private void savePersistentRegistrations() {
+ synchronized (CONFIG_FILE_LOCK) {
+ Providers providers = new Providers();
+ for (Entry<String,RegistrationContextImpl> entry :
registrations.entrySet()) {
+ if (entry.getValue().isPersistent()) {
+ Provider provider = new Provider();
+ provider.setAppContext(entry.getValue().getAppContext());
+
provider.setClassName(entry.getValue().getProvider().getClass().getName());
+ provider.setDescription(entry.getValue().getDescription());
+ provider.setLayer(entry.getValue().getMessageLayer());
+ for (Entry<String,String> property :
entry.getValue().getProperties().entrySet()) {
+ provider.addProperty(property.getKey(),
property.getValue());
+ }
+ providers.addProvider(provider);
+ }
+ }
+ PersistentProviderRegistrations.writeProviders(providers,
CONFIG_FILE);
+ }
+ }
+
+
+ private static class RegistrationContextImpl implements
RegistrationContext {
+
+ private RegistrationContextImpl(String messageLayer, String
appContext, String description,
+ boolean persistent, AuthConfigProvider provider,
Map<String,String> properties) {
+ this.messageLayer = messageLayer;
+ this.appContext = appContext;
+ this.description = description;
+ this.persistent = persistent;
+ this.provider = provider;
+ Map<String,String> propertiesCopy = new HashMap<>();
+ if (properties != null) {
+ propertiesCopy.putAll(properties);
+ }
+ this.properties = Collections.unmodifiableMap(propertiesCopy);
+ }
+
+ private final String messageLayer;
+ private final String appContext;
+ private final String description;
+ private final boolean persistent;
+ private final AuthConfigProvider provider;
+ private final Map<String,String> properties;
+ private final List<RegistrationListener> listeners = new
CopyOnWriteArrayList<>();
+
+ @Override
+ public String getMessageLayer() {
+ return messageLayer;
+ }
+
+
+ @Override
+ public String getAppContext() {
+ return appContext;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+
+ @Override
+ public boolean isPersistent() {
+ return persistent;
+ }
+
+
+ private AuthConfigProvider getProvider() {
+ return provider;
+ }
+
+
+ private void addListener(RegistrationListener listener) {
+ if (listener != null) {
+ listeners.add(listener);
+ }
+ }
+
+
+ private Map<String,String> getProperties() {
+ return properties;
+ }
+
+
+ private boolean removeListener(RegistrationListener listener) {
+ boolean result = false;
+ Iterator<RegistrationListener> iter = listeners.iterator();
+ while (iter.hasNext()) {
+ if (iter.next().equals(listener)) {
+ iter.remove();
+ }
+ }
+ return result;
+ }
+ }
+}
Propchange:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java?rev=1729742&view=auto
==============================================================================
---
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
(added)
+++
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
Wed Feb 10 21:26:46 2016
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.catalina.authenticator.jaspic;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
+
+public class CallbackHandlerImpl implements CallbackHandler {
+
+ private static final Log log =
LogFactory.getLog(CallbackHandlerImpl.class);
+ private static final StringManager sm =
StringManager.getManager(CallbackHandlerImpl.class);
+
+ private Request request;
+ private String name;
+ private Principal principal;
+ private Subject subject;
+ private String[] groups;
+
+
+ public CallbackHandlerImpl(Request request) {
+ this.request = request;
+ }
+
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
+ if (callbacks != null) {
+ // Need to combine data from multiple callbacks so use this to hold
+ // the data
+ // Process the callbacks
+ for (Callback callback : callbacks) {
+ if (callback instanceof CallerPrincipalCallback) {
+ CallerPrincipalCallback cpc = (CallerPrincipalCallback)
callback;
+ name = cpc.getName();
+ principal = cpc.getPrincipal();
+ subject = cpc.getSubject();
+ } else if (callback instanceof GroupPrincipalCallback) {
+ GroupPrincipalCallback gpc = (GroupPrincipalCallback)
callback;
+ groups = gpc.getGroups();
+ } else {
+
log.error(sm.getString("callbackHandlerImpl.jaspicCallbackMissing",
+ callback.getClass().getName()));
+ }
+ }
+
+ // Create the GenericPrincipal
+ GenericPrincipal gp = getGenericPrincipal();
+ if (gp != null) {
+ request.setUserPrincipal(gp);
+
+ if (subject != null) {
+ subject.getPrivateCredentials().add(gp);
+ }
+ }
+ }
+ }
+
+
+ public GenericPrincipal getGenericPrincipal() {
+ String name = this.name;
+ if (name == null && principal != null) {
+ name = principal.getName();
+ }
+ if (name == null) {
+ return null;
+ }
+ List<String> roles;
+ if (groups == null || groups.length == 0) {
+ roles = Collections.emptyList();
+ } else {
+ roles = Arrays.asList(groups);
+ }
+
+ return new GenericPrincipal(name, null, roles, principal);
+ }
+}
Propchange:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties?rev=1729742&view=auto
==============================================================================
---
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
(added)
+++
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
Wed Feb 10 21:26:46 2016
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+authConfigFactoryImpl.load=Loading persistent provider registrations from [{0}]
+authConfigFactoryImpl.registerClass=Registering class [{0}] for layer [{1}]
and application context [{2}]
+authConfigFactoryImpl.registerInstance=Registering instance of type[{0}] for
layer [{1}] and application context [{2}]
+
+callbackHandlerImpl.jaspicCallbackMissing=Unsupported JASPIC callback of type
[{0}] received which was ignored
+
+jaspicAuthenticator.authenticate=Authenticating request for [{0}] via JASPIC
+
+persistentProviderRegistrations.deleteFail=The temporary file [{0}] cannot be
deleted
+persistentProviderRegistrations.existsDeleteFail=The temporary file [{0}]
already exists and cannot be deleted
+persistentProviderRegistrations.moveFail=Failed to move [{0}] to [{1}]
\ No newline at end of file
Propchange:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
------------------------------------------------------------------------------
svn:eol-style = native
Added:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java?rev=1729742&view=auto
==============================================================================
---
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java
(added)
+++
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java
Wed Feb 10 21:26:46 2016
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.catalina.authenticator.jaspic;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.message.MessageInfo;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.catalina.connector.Request;
+import org.apache.tomcat.util.res.StringManager;
+
+public class MessageInfoImpl implements MessageInfo {
+ protected static final StringManager sm =
StringManager.getManager(MessageInfoImpl.class);
+
+ public static final String IS_MANDATORY =
"javax.security.auth.message.MessagePolicy.isMandatory";
+
+ private final Map<String, Object> map = new HashMap<>();
+ private Request request;
+ private HttpServletResponse response;
+
+ public MessageInfoImpl() {
+ }
+
+ public MessageInfoImpl(Request request, HttpServletResponse response,
boolean authMandatory) {
+ this.request = request;
+ this.response = response;
+ map.put(IS_MANDATORY, Boolean.toString(authMandatory));
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ // JASPIC uses raw types
+ public Map getMap() {
+ return map;
+ }
+
+ @Override
+ public Object getRequestMessage() {
+ return request;
+ }
+
+ @Override
+ public Object getResponseMessage() {
+ return response;
+ }
+
+ @Override
+ public void setRequestMessage(Object request) {
+ if (!(request instanceof Request)) {
+ throw new
IllegalArgumentException(sm.getString("authenticator.jaspic.badRequestType",
+ request.getClass().getName()));
+ }
+ this.request = (Request) request;
+ }
+
+ @Override
+ public void setResponseMessage(Object response) {
+ if (!(response instanceof HttpServletResponse)) {
+ throw new
IllegalArgumentException(sm.getString("authenticator.jaspic.badResponseType",
+ response.getClass().getName()));
+ }
+ this.response = (HttpServletResponse) response;
+ }
+}
\ No newline at end of file
Propchange:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java?rev=1729742&r1=1729741&r2=1729742&view=diff
==============================================================================
---
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
(original)
+++
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
Wed Feb 10 21:26:46 2016
@@ -18,32 +18,50 @@ package org.apache.catalina.authenticato
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.digester.Digester;
+import org.apache.tomcat.util.res.StringManager;
import org.xml.sax.SAXException;
+/**
+ * Utility class for the loading and saving of JASPIC persistent provider
+ * registrations.
+ */
final class PersistentProviderRegistrations {
+ private static final Log log =
LogFactory.getLog(PersistentProviderRegistrations.class);
+ private static final StringManager sm =
+ StringManager.getManager(PersistentProviderRegistrations.class);
+
+
private PersistentProviderRegistrations() {
// Utility class. Hide default constructor
}
- static Providers getProviders(File configFile) {
+ static Providers loadProviders(File configFile) {
try (InputStream is = new FileInputStream(configFile)) {
// Construct a digester to read the XML input file
Digester digester = new Digester();
try {
digester.setFeature("http://apache.org/xml/features/allow-java-encodings",
true);
- // TODO: Configure the digester to validate the input against
- // the XSD
+ digester.setValidating(true);
+ digester.setNamespaceAware(true);
} catch (Exception e) {
throw new SecurityException(e);
}
@@ -72,6 +90,85 @@ final class PersistentProviderRegistrati
}
+ static void writeProviders(Providers providers, File configFile) {
+ File configFileOld = new File(configFile.getAbsolutePath() + ".old");
+ File configFileNew = new File(configFile.getAbsolutePath() + ".new");
+
+ // Remove left over temporary files if present
+ if (configFileOld.exists()) {
+ if (configFileOld.delete()) {
+ throw new SecurityException(sm.getString(
+ "persistentProviderRegistrations.existsDeleteFail",
+ configFileOld.getAbsolutePath()));
+ }
+ }
+ if (configFileNew.exists()) {
+ if (configFileNew.delete()) {
+ throw new SecurityException(sm.getString(
+ "persistentProviderRegistrations.existsDeleteFail",
+ configFileNew.getAbsolutePath()));
+ }
+ }
+
+ // Write out the providers to the temporary new file
+ try (OutputStream fos = new FileOutputStream(configFileNew);
+ Writer writer = new OutputStreamWriter(fos,
StandardCharsets.UTF_8)) {
+ writer.write(
+ "<?xml version='1.0' encoding='utf-8'?>\n" +
+ "<jaspic-providers\n" +
+ " xmlns=\"http://tomcat.apache.org/xml\"\n" +
+ "
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
+ " xsi:schemaLocation=\"http://tomcat.apache.org/xml
jaspic-providers.xsd\"\n" +
+ " version=\"1.0\">\n");
+ for (Provider provider : providers.providers) {
+ writer.write(" <provider className=\"");
+ writer.write(provider.getClassName());
+ writer.write("\" layer=\"");
+ writer.write(provider.getLayer());
+ writer.write("\" appContext=\"");
+ writer.write(provider.getAppContext());
+ if (provider.getDescription() != null) {
+ writer.write("\" description=\"");
+ writer.write(provider.getDescription());
+ }
+ writer.write("\">\n");
+ for (Entry<String,String> entry :
provider.getProperties().entrySet()) {
+ writer.write(" <property name=\"");
+ writer.write(entry.getKey());
+ writer.write("\" value=\"");
+ writer.write(entry.getValue());
+ writer.write("\"/>\n");
+ }
+ writer.write(" </provider>\n");
+ }
+ writer.write("</jaspic-providers>\n");
+ } catch (IOException e) {
+ configFileNew.delete();
+ throw new SecurityException(e);
+ }
+
+ // Move the current file out of the way
+ if (configFile.isFile()) {
+ if (!configFile.renameTo(configFileOld)) {
+ throw new
SecurityException(sm.getString("persistentProviderRegistrations.moveFail",
+ configFile.getAbsolutePath(),
configFileOld.getAbsolutePath()));
+ }
+ }
+
+ // Move the new file into place
+ if (!configFileNew.renameTo(configFile)) {
+ throw new
SecurityException(sm.getString("persistentProviderRegistrations.moveFail",
+ configFileNew.getAbsolutePath(),
configFile.getAbsolutePath()));
+ }
+
+ // Remove the old file
+ if (configFileOld.exists() && !configFileOld.delete()) {
+ log.warn(sm.getString("persistentProviderRegistrations.deleteFail",
+ configFileOld.getAbsolutePath()));
+ }
+ }
+
+
public static class Providers {
private final List<Provider> providers = new ArrayList<>();
@@ -128,6 +225,9 @@ final class PersistentProviderRegistrati
public void addProperty(Property property) {
properties.put(property.getName(), property.getValue());
}
+ void addProperty(String name, String value) {
+ properties.put(name, value);
+ }
public Map<String,String> getProperties() {
return properties;
}
Modified:
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestPersistentProviderRegistrations.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestPersistentProviderRegistrations.java?rev=1729742&r1=1729741&r2=1729742&view=diff
==============================================================================
---
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestPersistentProviderRegistrations.java
(original)
+++
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestPersistentProviderRegistrations.java
Wed Feb 10 21:26:46 2016
@@ -29,7 +29,7 @@ public class TestPersistentProviderRegis
@Test
public void testLoadEmpty() {
File f = new File("test/conf/jaspic-test-01.xml");
- Providers result = PersistentProviderRegistrations.getProviders(f);
+ Providers result = PersistentProviderRegistrations.loadProviders(f);
Assert.assertEquals(0, result.getProviders().size());
}
@@ -37,9 +37,14 @@ public class TestPersistentProviderRegis
@Test
public void testLoadSimple() {
File f = new File("test/conf/jaspic-test-02.xml");
- Providers result = PersistentProviderRegistrations.getProviders(f);
- Assert.assertEquals(1, result.getProviders().size());
- Provider p = result.getProviders().get(0);
+ Providers result = PersistentProviderRegistrations.loadProviders(f);
+ validateSimple(result);
+ }
+
+
+ private void validateSimple(Providers providers) {
+ Assert.assertEquals(1, providers.getProviders().size());
+ Provider p = providers.getProviders().get(0);
Assert.assertEquals("a", p.getClassName());
Assert.assertEquals("b", p.getLayer());
Assert.assertEquals("c", p.getAppContext());
@@ -49,4 +54,34 @@ public class TestPersistentProviderRegis
Assert.assertEquals("f", p.getProperties().get("e"));
Assert.assertEquals("h", p.getProperties().get("g"));
}
+
+
+ @Test
+ public void testSaveSimple() {
+ File f = new File("test/conf/jaspic-test-03.xml");
+ if (f.exists()) {
+ Assert.assertTrue(f.delete());
+ }
+
+ // Create a config and write it out
+ Providers start = new Providers();
+ Provider p = new Provider();
+ p.setClassName("a");
+ p.setLayer("b");
+ p.setAppContext("c");
+ p.setDescription("d");
+ p.addProperty("e", "f");
+ p.addProperty("g", "h");
+ start.addProvider(p);
+ PersistentProviderRegistrations.writeProviders(start, f);
+
+ // Read it back
+ Providers end = PersistentProviderRegistrations.loadProviders(f);
+
+ validateSimple(end);
+
+ if (f.exists()) {
+ f.delete();
+ }
+ }
}
Modified: tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java?rev=1729742&r1=1729741&r2=1729742&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java
(original)
+++ tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java Wed
Feb 10 21:26:46 2016
@@ -34,6 +34,7 @@ import org.junit.Test;
import org.apache.catalina.Context;
import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.core.StandardHost;
import org.apache.tomcat.util.buf.ByteChunk;
public class TestContextConfig extends TomcatBaseTest {
@@ -201,4 +202,24 @@ public class TestContextConfig extends T
Assert.assertTrue(result, result.indexOf(expectedBody) > -1);
}
}
+
+
+ @Test
+ public void testUser01() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+ StandardHost host = (StandardHost) tomcat.getHost();
+ host.setUnpackWARs(true);
+ host.setAutoDeploy(true);
+ tomcat.start();
+
+
+ StandardContext ctx = new StandardContext();
+ ctx.setDocBase("D://test1");
+ ctx.setPath("/test1");
+ ctx.addLifecycleListener(new ContextConfig());
+
+ host.addChild(ctx);
+
+ System.out.println("done");
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]