This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
/*
* 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;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
/**
* Intended for use by a {@link Valve} to indicate that the {@link Valve}
* provides access logging. It is used by the Tomcat internals to identify a
* Valve that logs access requests so requests that are rejected
* earlier in the processing chain can still be added to the access log.
* Implementations of this interface should be robust against the provided
* {@link Request} and {@link Response} objects being null, having null
* attributes or any other 'oddness' that may result from attempting to log
* a request that was almost certainly rejected because it was mal-formed.
*/
public interface AccessLog {
/**
* Name of request attribute used to override the remote address recorded by
* the AccessLog.
*/
public static final String REMOTE_ADDR_ATTRIBUTE =
"org.apache.catalina.AccessLog.RemoteAddr";
/**
* Name of request attribute used to override remote host name recorded by
* the AccessLog.
*/
public static final String REMOTE_HOST_ATTRIBUTE =
"org.apache.catalina.AccessLog.RemoteHost";
/**
* Name of request attribute used to override the protocol recorded by the
* AccessLog.
*/
public static final String PROTOCOL_ATTRIBUTE =
"org.apache.catalina.AccessLog.Protocol";
/**
* Name of request attribute used to override the server name recorded by
* the AccessLog.
*/
public static final String SERVER_NAME_ATTRIBUTE =
"org.apache.catalina.AccessLog.ServerName";
/**
* Name of request attribute used to override the server port recorded by
* the AccessLog.
*/
public static final String SERVER_PORT_ATTRIBUTE =
"org.apache.catalina.AccessLog.ServerPort";
/**
* Add the request/response to the access log using the specified processing
* time.
*
* @param request Request (associated with the response) to log
* @param response Response (associated with the request) to log
* @param time Time taken to process the request/response in
* milliseconds (use 0 if not known)
*/
public void log(Request request, Response response, long time);
/**
* Should this valve use request attributes for IP address, hostname,
* protocol and port used for the request?
*
* The attributes used are:
* <ul>
* <li>org.apache.catalina.RemoteAddr</li>
* <li>org.apache.catalina.RemoteHost</li>
* <li>org.apache.catalina.Protocol</li>
* <li>org.apache.catalina.ServerName</li>
* <li>org.apache.catalina.ServerPost</li>
* </ul>
*
* @param requestAttributesEnabled <code>true</code> causes the attributes
* to be used, <code>false</code> causes
* the original values to be used.
*/
public void setRequestAttributesEnabled(boolean requestAttributesEnabled);
/**
* @see #setRequestAttributesEnabled(boolean)
* @return <code>true</code> if the attributes will be logged, otherwise
* <code>false</code>
*/
public boolean getRequestAttributesEnabled();
}

View File

@@ -0,0 +1,39 @@
/*
* 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;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface AsyncDispatcher {
/**
* Perform an asynchronous dispatch. The method does not check if the
* request is in an appropriate state for this; it is the caller's
* responsibility to check this.
* @param request The request object to pass to the dispatch target
* @param response The response object to pass to the dispatch target
* @throws ServletException if thrown by the dispatch target
* @throws IOException if an I/O error occurs while processing the
* dispatch
*/
public void dispatch(ServletRequest request, ServletResponse response)
throws ServletException, IOException;
}

View File

@@ -0,0 +1,57 @@
/*
* 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;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.connector.Request;
/**
* An <b>Authenticator</b> is a component (usually a Valve or Container) that
* provides some sort of authentication service.
*
* @author Craig R. McClanahan
*/
public interface Authenticator {
/**
* Authenticate the user making this request, based on the login
* configuration of the {@link Context} with which this Authenticator is
* associated.
*
* @param request Request we are processing
* @param response Response we are populating
*
* @return <code>true</code> if any specified constraints have been
* satisfied, or <code>false</code> if one more constraints were not
* satisfied (in which case an authentication challenge will have
* been written to the response).
*
* @exception IOException if an input/output error occurs
*/
public boolean authenticate(Request request, HttpServletResponse response)
throws IOException;
public void login(String userName, String password, Request request)
throws ServletException;
public void logout(Request request);
}

View File

@@ -0,0 +1,104 @@
/*
* 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;
/**
* A <b>Cluster</b> works as a Cluster client/server for the local host
* Different Cluster implementations can be used to support different
* ways to communicate within the Cluster. A Cluster implementation is
* responsible for setting up a way to communicate within the Cluster
* and also supply "ClientApplications" with <code>ClusterSender</code>
* used when sending information in the Cluster and
* <code>ClusterInfo</code> used for receiving information in the Cluster.
*
* @author Bip Thelin
* @author Remy Maucherat
*/
public interface Cluster {
// ------------------------------------------------------------- Properties
/**
* Return the name of the cluster that this Server is currently
* configured to operate within.
*
* @return The name of the cluster associated with this server
*/
public String getClusterName();
/**
* Set the name of the cluster to join, if no cluster with
* this name is present create one.
*
* @param clusterName The clustername to join
*/
public void setClusterName(String clusterName);
/**
* Set the Container associated with our Cluster
*
* @param container The Container to use
*/
public void setContainer(Container container);
/**
* Get the Container associated with our Cluster
*
* @return The Container associated with our Cluster
*/
public Container getContainer();
// --------------------------------------------------------- Public Methods
/**
* Create a new manager which will use this cluster to replicate its
* sessions.
*
* @param name Name (key) of the application with which the manager is
* associated
*
* @return The newly created Manager instance
*/
public Manager createManager(String name);
/**
* Register a manager with the cluster. If the cluster is not responsible
* for creating a manager, then the container will at least notify the
* cluster that this manager is participating in the cluster.
* @param manager Manager
*/
public void registerManager(Manager manager);
/**
* Removes a manager from the cluster
* @param manager Manager
*/
public void removeManager(Manager manager);
// --------------------------------------------------------- Cluster Wide Deployments
/**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
*/
public void backgroundProcess();
}

View File

@@ -0,0 +1,45 @@
/*
* 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;
/**
* <p>Decoupling interface which specifies that an implementing class is
* associated with at most one <strong>Container</strong> instance.</p>
*
* @author Craig R. McClanahan
* @author Peter Donald
*/
public interface Contained {
/**
* Get the {@link Container} with which this instance is associated.
*
* @return The Container with which this instance is associated or
* <code>null</code> if not associated with a Container
*/
Container getContainer();
/**
* Set the <code>Container</code> with which this instance is associated.
*
* @param container The Container instance with which this instance is to
* be associated, or <code>null</code> to disassociate this instance
* from any Container
*/
void setContainer(Container container);
}

View File

@@ -0,0 +1,474 @@
/*
* 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;
import java.beans.PropertyChangeListener;
import java.io.File;
import javax.management.ObjectName;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.juli.logging.Log;
/**
* A <b>Container</b> is an object that can execute requests received from
* a client, and return responses based on those requests. A Container may
* optionally support a pipeline of Valves that process the request in an
* order configured at runtime, by implementing the <b>Pipeline</b> interface
* as well.
* <p>
* Containers will exist at several conceptual levels within Catalina. The
* following examples represent common cases:
* <ul>
* <li><b>Engine</b> - Representation of the entire Catalina servlet engine,
* most likely containing one or more subcontainers that are either Host
* or Context implementations, or other custom groups.
* <li><b>Host</b> - Representation of a virtual host containing a number
* of Contexts.
* <li><b>Context</b> - Representation of a single ServletContext, which will
* typically contain one or more Wrappers for the supported servlets.
* <li><b>Wrapper</b> - Representation of an individual servlet definition
* (which may support multiple servlet instances if the servlet itself
* implements SingleThreadModel).
* </ul>
* A given deployment of Catalina need not include Containers at all of the
* levels described above. For example, an administration application
* embedded within a network device (such as a router) might only contain
* a single Context and a few Wrappers, or even a single Wrapper if the
* application is relatively small. Therefore, Container implementations
* need to be designed so that they will operate correctly in the absence
* of parent Containers in a given deployment.
* <p>
* A Container may also be associated with a number of support components
* that provide functionality which might be shared (by attaching it to a
* parent Container) or individually customized. The following support
* components are currently recognized:
* <ul>
* <li><b>Loader</b> - Class loader to use for integrating new Java classes
* for this Container into the JVM in which Catalina is running.
* <li><b>Logger</b> - Implementation of the <code>log()</code> method
* signatures of the <code>ServletContext</code> interface.
* <li><b>Manager</b> - Manager for the pool of Sessions associated with
* this Container.
* <li><b>Realm</b> - Read-only interface to a security domain, for
* authenticating user identities and their corresponding roles.
* <li><b>Resources</b> - JNDI directory context enabling access to static
* resources, enabling custom linkages to existing server components when
* Catalina is embedded in a larger server.
* </ul>
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
public interface Container extends Lifecycle {
// ----------------------------------------------------- Manifest Constants
/**
* The ContainerEvent event type sent when a child container is added
* by <code>addChild()</code>.
*/
public static final String ADD_CHILD_EVENT = "addChild";
/**
* The ContainerEvent event type sent when a valve is added
* by <code>addValve()</code>, if this Container supports pipelines.
*/
public static final String ADD_VALVE_EVENT = "addValve";
/**
* The ContainerEvent event type sent when a child container is removed
* by <code>removeChild()</code>.
*/
public static final String REMOVE_CHILD_EVENT = "removeChild";
/**
* The ContainerEvent event type sent when a valve is removed
* by <code>removeValve()</code>, if this Container supports pipelines.
*/
public static final String REMOVE_VALVE_EVENT = "removeValve";
// ------------------------------------------------------------- Properties
/**
* Obtain the log to which events for this container should be logged.
*
* @return The Logger with which this Container is associated. If there is
* no associated Logger, return the Logger associated with the
* parent Container (if any); otherwise return <code>null</code>.
*/
public Log getLogger();
/**
* Return the logger name that the container will use.
* @return the abbreviated name of this container for logging messages
*/
public String getLogName();
/**
* Obtain the JMX name for this container.
*
* @return the JMX name associated with this container.
*/
public ObjectName getObjectName();
/**
* Obtain the JMX domain under which this container will be / has been
* registered.
*
* @return The JMX domain name
*/
public String getDomain();
/**
* Calculate the key properties string to be added to an object's
* {@link ObjectName} to indicate that it is associated with this container.
*
* @return A string suitable for appending to the ObjectName
*
*/
public String getMBeanKeyProperties();
/**
* Return the Pipeline object that manages the Valves associated with
* this Container.
*
* @return The Pipeline
*/
public Pipeline getPipeline();
/**
* Get the Cluster for this container.
*
* @return The Cluster with which this Container is associated. If there is
* no associated Cluster, return the Cluster associated with our
* parent Container (if any); otherwise return <code>null</code>.
*/
public Cluster getCluster();
/**
* Set the Cluster with which this Container is associated.
*
* @param cluster the Cluster with which this Container is associated.
*/
public void setCluster(Cluster cluster);
/**
* Get the delay between the invocation of the backgroundProcess method on
* this container and its children. Child containers will not be invoked if
* their delay value is positive (which would mean they are using their own
* thread). Setting this to a positive value will cause a thread to be
* spawned. After waiting the specified amount of time, the thread will
* invoke the {@link #backgroundProcess()} method on this container and all
* children with non-positive delay values.
*
* @return The delay between the invocation of the backgroundProcess method
* on this container and its children. A non-positive value
* indicates that background processing will be managed by the
* parent.
*/
public int getBackgroundProcessorDelay();
/**
* Set the delay between the invocation of the execute method on this
* container and its children.
*
* @param delay The delay in seconds between the invocation of
* backgroundProcess methods
*/
public void setBackgroundProcessorDelay(int delay);
/**
* Return a name string (suitable for use by humans) that describes this
* Container. Within the set of child containers belonging to a particular
* parent, Container names must be unique.
*
* @return The human readable name of this container.
*/
public String getName();
/**
* Set a name string (suitable for use by humans) that describes this
* Container. Within the set of child containers belonging to a particular
* parent, Container names must be unique.
*
* @param name New name of this container
*
* @exception IllegalStateException if this Container has already been
* added to the children of a parent Container (after which the name
* may not be changed)
*/
public void setName(String name);
/**
* Get the parent container.
*
* @return Return the Container for which this Container is a child, if
* there is one. If there is no defined parent, return
* <code>null</code>.
*/
public Container getParent();
/**
* Set the parent Container to which this Container is being added as a
* child. This Container may refuse to become attached to the specified
* Container by throwing an exception.
*
* @param container Container to which this Container is being added
* as a child
*
* @exception IllegalArgumentException if this Container refuses to become
* attached to the specified Container
*/
public void setParent(Container container);
/**
* Get the parent class loader.
*
* @return the parent class loader for this component. If not set, return
* {@link #getParent()}.{@link #getParentClassLoader()}. If no
* parent has been set, return the system class loader.
*/
public ClassLoader getParentClassLoader();
/**
* Set the parent class loader for this component. For {@link Context}s
* this call is meaningful only <strong>before</strong> a Loader has
* been configured, and the specified value (if non-null) should be
* passed as an argument to the class loader constructor.
*
* @param parent The new parent class loader
*/
public void setParentClassLoader(ClassLoader parent);
/**
* Obtain the Realm with which this Container is associated.
*
* @return The associated Realm; if there is no associated Realm, the
* Realm associated with the parent Container (if any); otherwise
* return <code>null</code>.
*/
public Realm getRealm();
/**
* Set the Realm with which this Container is associated.
*
* @param realm The newly associated Realm
*/
public void setRealm(Realm realm);
// --------------------------------------------------------- Public Methods
/**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
*/
public void backgroundProcess();
/**
* Add a new child Container to those associated with this Container,
* if supported. Prior to adding this Container to the set of children,
* the child's <code>setParent()</code> method must be called, with this
* Container as an argument. This method may thrown an
* <code>IllegalArgumentException</code> if this Container chooses not
* to be attached to the specified Container, in which case it is not added
*
* @param child New child Container to be added
*
* @exception IllegalArgumentException if this exception is thrown by
* the <code>setParent()</code> method of the child Container
* @exception IllegalArgumentException if the new child does not have
* a name unique from that of existing children of this Container
* @exception IllegalStateException if this Container does not support
* child Containers
*/
public void addChild(Container child);
/**
* Add a container event listener to this component.
*
* @param listener The listener to add
*/
public void addContainerListener(ContainerListener listener);
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Obtain a child Container by name.
*
* @param name Name of the child Container to be retrieved
*
* @return The child Container with the given name or <code>null</code> if
* no such child exists.
*/
public Container findChild(String name);
/**
* Obtain the child Containers associated with this Container.
*
* @return An array containing all children of this container. If this
* Container has no children, a zero-length array is returned.
*/
public Container[] findChildren();
/**
* Obtain the container listeners associated with this Container.
*
* @return An array containing the container listeners associated with this
* Container. If this Container has no registered container
* listeners, a zero-length array is returned.
*/
public ContainerListener[] findContainerListeners();
/**
* Remove an existing child Container from association with this parent
* Container.
*
* @param child Existing child Container to be removed
*/
public void removeChild(Container child);
/**
* Remove a container event listener from this component.
*
* @param listener The listener to remove
*/
public void removeContainerListener(ContainerListener listener);
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
/**
* Notify all container event listeners that a particular event has
* occurred for this Container. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/
public void fireContainerEvent(String type, Object data);
/**
* Log a request/response that was destined for this container but has been
* handled earlier in the processing chain so that the request/response
* still appears in the correct access logs.
* @param request Request (associated with the response) to log
* @param response Response (associated with the request) to log
* @param time Time taken to process the request/response in
* milliseconds (use 0 if not known)
* @param useDefault Flag that indicates that the request/response should
* be logged in the engine's default access log
*/
public void logAccess(Request request, Response response, long time,
boolean useDefault);
/**
* Obtain the AccessLog to use to log a request/response that is destined
* for this container. This is typically used when the request/response was
* handled (and rejected) earlier in the processing chain so that the
* request/response still appears in the correct access logs.
*
* @return The AccessLog to use for a request/response destined for this
* container
*/
public AccessLog getAccessLog();
/**
* Obtain the number of threads available for starting and stopping any
* children associated with this container. This allows start/stop calls to
* children to be processed in parallel.
*
* @return The currently configured number of threads used to start/stop
* children associated with this container
*/
public int getStartStopThreads();
/**
* Sets the number of threads available for starting and stopping any
* children associated with this container. This allows start/stop calls to
* children to be processed in parallel.
* @param startStopThreads The new number of threads to be used
*/
public void setStartStopThreads(int startStopThreads);
/**
* Obtain the location of CATALINA_BASE.
*
* @return The location of CATALINA_BASE.
*/
public File getCatalinaBase();
/**
* Obtain the location of CATALINA_HOME.
*
* @return The location of CATALINA_HOME.
*/
public File getCatalinaHome();
}

View File

@@ -0,0 +1,96 @@
/*
* 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;
import java.util.EventObject;
/**
* General event for notifying listeners of significant changes on a Container.
*
* @author Craig R. McClanahan
*/
public final class ContainerEvent extends EventObject {
private static final long serialVersionUID = 1L;
/**
* The event data associated with this event.
*/
private final Object data;
/**
* The event type this instance represents.
*/
private final String type;
/**
* Construct a new ContainerEvent with the specified parameters.
*
* @param container Container on which this event occurred
* @param type Event type
* @param data Event data
*/
public ContainerEvent(Container container, String type, Object data) {
super(container);
this.type = type;
this.data = data;
}
/**
* Return the event data of this event.
*
* @return The data, if any, associated with this event.
*/
public Object getData() {
return this.data;
}
/**
* Return the Container on which this event occurred.
*
* @return The Container on which this event occurred.
*/
public Container getContainer() {
return (Container) getSource();
}
/**
* Return the event type of this event.
*
* @return The event type of this event. Although this is a String, it is
* safe to rely on the value returned by this method remaining
* consistent between point releases.
*/
public String getType() {
return this.type;
}
/**
* Return a string representation of this event.
*/
@Override
public String toString() {
return "ContainerEvent['" + getContainer() + "','" +
getType() + "','" + getData() + "']";
}
}

View File

@@ -0,0 +1,40 @@
/*
* 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;
/**
* Interface defining a listener for significant Container generated events.
* Note that "container start" and "container stop" events are normally
* LifecycleEvents, not ContainerEvents.
*
* @author Craig R. McClanahan
*/
public interface ContainerListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event ContainerEvent that has occurred
*/
public void containerEvent(ContainerEvent event);
}

View File

@@ -0,0 +1,44 @@
/*
* 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;
/**
* A <b>ContainerServlet</b> is a servlet that has access to Catalina
* internal functionality, and is loaded from the Catalina class loader
* instead of the web application class loader. The property setter
* methods must be called by the container whenever a new instance of
* this servlet is put into service.
*
* @author Craig R. McClanahan
*/
public interface ContainerServlet {
/**
* Obtain the Wrapper with which this Servlet is associated.
*
* @return The Wrapper with which this Servlet is associated.
*/
public Wrapper getWrapper();
/**
* Set the Wrapper with which this Servlet is associated.
*
* @param wrapper The new associated Wrapper
*/
public void setWrapper(Wrapper wrapper);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
* 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;
/**
* This interface is used by the {@link Realm} to compare the user provided
* credentials with the credentials stored in the {@link Realm} for that user.
*/
public interface CredentialHandler {
/**
* Checks to see if the input credentials match the stored credentials
*
* @param inputCredentials User provided credentials
* @param storedCredentials Credentials stored in the {@link Realm}
*
* @return <code>true</code> if the inputCredentials match the
* storedCredentials, otherwise <code>false</code>
*/
boolean matches(String inputCredentials, String storedCredentials);
/**
* Generates the equivalent stored credentials for the given input
* credentials.
*
* @param inputCredentials User provided credentials
*
* @return The equivalent stored credentials for the given input
* credentials
*/
String mutate(String inputCredentials);
}

View File

@@ -0,0 +1,51 @@
/*
* 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;
import java.util.Set;
/**
* Interface implemented by session managers that do not keep a complete copy
* of all sessions in memory but do know where every session is. The
* BackupManager is an example of such a Manager as are implementations of the
* StoreManager interface.
* <p>
* With the BackupManager, sessions can be primary (master copy on this node),
* backup (backup copy on this node) or proxy (only the session ID on this
* node). The identity of the primary and backup nodes are known for all
* sessions, including proxy sessions.
* <p>
* With StoreManager implementations, sessions can be primary (session is in
* memory) or proxy (session is in the Store).
*/
public interface DistributedManager {
/**
* Returns the total session count for primary, backup and proxy.
*
* @return The total session count across the cluster.
*/
public int getActiveSessionsFull();
/**
* Returns the list of all sessions IDS (primary, backup and proxy).
*
* @return The complete set of sessions IDs across the cluster.
*/
public Set<String> getSessionIdsFull();
}

View File

@@ -0,0 +1,86 @@
/*
* 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;
/**
* An <b>Engine</b> is a Container that represents the entire Catalina servlet
* engine. It is useful in the following types of scenarios:
* <ul>
* <li>You wish to use Interceptors that see every single request processed
* by the entire engine.
* <li>You wish to run Catalina in with a standalone HTTP connector, but still
* want support for multiple virtual hosts.
* </ul>
* In general, you would not use an Engine when deploying Catalina connected
* to a web server (such as Apache), because the Connector will have
* utilized the web server's facilities to determine which Context (or
* perhaps even which Wrapper) should be utilized to process this request.
* <p>
* The child containers attached to an Engine are generally implementations
* of Host (representing a virtual host) or Context (representing individual
* an individual servlet context), depending upon the Engine implementation.
* <p>
* If used, an Engine is always the top level Container in a Catalina
* hierarchy. Therefore, the implementation's <code>setParent()</code> method
* should throw <code>IllegalArgumentException</code>.
*
* @author Craig R. McClanahan
*/
public interface Engine extends Container {
/**
* @return the default host name for this Engine.
*/
public String getDefaultHost();
/**
* Set the default hostname for this Engine.
*
* @param defaultHost The new default host
*/
public void setDefaultHost(String defaultHost);
/**
* @return the JvmRouteId for this engine.
*/
public String getJvmRoute();
/**
* Set the JvmRouteId for this engine.
*
* @param jvmRouteId the (new) JVM Route ID. Each Engine within a cluster
* must have a unique JVM Route ID.
*/
public void setJvmRoute(String jvmRouteId);
/**
* @return the <code>Service</code> with which we are associated (if any).
*/
public Service getService();
/**
* Set the <code>Service</code> with which we are associated (if any).
*
* @param service The service that owns this Engine
*/
public void setService(Service service);
}

View File

@@ -0,0 +1,42 @@
/*
* 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;
import java.util.concurrent.TimeUnit;
public interface Executor extends java.util.concurrent.Executor, Lifecycle {
public String getName();
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the <code>Executor</code> implementation.
* If no threads are available, it will be added to the work queue.
* If the work queue is full, the system will wait for the specified
* time until it throws a RejectedExecutionException
*
* @param command the runnable task
* @param timeout the length of time to wait for the task to complete
* @param unit the units in which timeout is expressed
*
* @throws java.util.concurrent.RejectedExecutionException if this task
* cannot be accepted for execution - the queue is full
* @throws NullPointerException if command or unit is null
*/
void execute(Runnable command, long timeout, TimeUnit unit);
}

View File

@@ -0,0 +1,45 @@
/*
* 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;
import java.security.Principal;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSName;
/**
* A <b>GSSRealm</b> is a specialized realm for GSS-based principals.
*
* @deprecated This will be removed in Tomcat 9 and integrated into {@link Realm}.
*/
@Deprecated
public interface GSSRealm extends Realm {
// --------------------------------------------------------- Public Methods
/**
* Try to authenticate using a {@link GSSName}
*
* @param gssName The {@link GSSName} of the principal to look up
* @param gssCredential The {@link GSSCredential} of the principal, may be
* {@code null}
* @return the associated principal, or {@code null} if there is none
*/
public Principal authenticate(GSSName gssName, GSSCredential gssCredential);
}

View File

@@ -0,0 +1,295 @@
/*
* 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;
/**
* Global constants that are applicable to multiple packages within Catalina.
*
* @author Craig R. McClanahan
*/
public final class Globals {
/**
* The servlet context attribute under which we store the alternate
* deployment descriptor for this web application
*/
public static final String ALT_DD_ATTR =
"org.apache.catalina.deploy.alt_dd";
/**
* The request attribute under which we store the array of X509Certificate
* objects representing the certificate chain presented by our client,
* if any.
*/
public static final String CERTIFICATES_ATTR =
"javax.servlet.request.X509Certificate";
/**
* The request attribute under which we store the name of the cipher suite
* being used on an SSL connection (as an object of type
* java.lang.String).
*/
public static final String CIPHER_SUITE_ATTR =
"javax.servlet.request.cipher_suite";
/**
* Request dispatcher state.
*/
public static final String DISPATCHER_TYPE_ATTR =
"org.apache.catalina.core.DISPATCHER_TYPE";
/**
* Request dispatcher path.
*/
public static final String DISPATCHER_REQUEST_PATH_ATTR =
"org.apache.catalina.core.DISPATCHER_REQUEST_PATH";
/**
* The WebResourceRoot which is associated with the context. This can be
* used to manipulate static files.
*/
public static final String RESOURCES_ATTR =
"org.apache.catalina.resources";
/**
* The servlet context attribute under which we store the class path
* for our application class loader (as an object of type String),
* delimited with the appropriate path delimiter for this platform.
*/
public static final String CLASS_PATH_ATTR =
"org.apache.catalina.jsp_classpath";
/**
* The request attribute under which we store the key size being used for
* this SSL connection (as an object of type java.lang.Integer).
*/
public static final String KEY_SIZE_ATTR =
"javax.servlet.request.key_size";
/**
* The request attribute under which we store the session id being used
* for this SSL connection (as an object of type java.lang.String).
*/
public static final String SSL_SESSION_ID_ATTR =
"javax.servlet.request.ssl_session_id";
/**
* The request attribute key for the session manager.
* This one is a Tomcat extension to the Servlet spec.
*/
public static final String SSL_SESSION_MGR_ATTR =
"javax.servlet.request.ssl_session_mgr";
/**
* The request attribute under which we store the servlet name on a
* named dispatcher request.
*/
public static final String NAMED_DISPATCHER_ATTR =
"org.apache.catalina.NAMED";
/**
* The servlet context attribute under which we store a flag used
* to mark this request as having been processed by the SSIServlet.
* We do this because of the pathInfo mangling happening when using
* the CGIServlet in conjunction with the SSI servlet. (value stored
* as an object of type String)
*
* @deprecated Unused. This is no longer used as the CGIO servlet now has
* generic handling for when it is used as an include.
* This will be removed in Tomcat 10
*/
@Deprecated
public static final String SSI_FLAG_ATTR = "org.apache.catalina.ssi.SSIServlet";
/**
* The subject under which the AccessControlContext is running.
*/
public static final String SUBJECT_ATTR =
"javax.security.auth.subject";
public static final String GSS_CREDENTIAL_ATTR =
"org.apache.catalina.realm.GSS_CREDENTIAL";
/**
* The request attribute that is set to the value of {@code Boolean.TRUE}
* if connector processing this request supports use of sendfile.
*
* Duplicated here for neater code in the catalina packages.
*/
public static final String SENDFILE_SUPPORTED_ATTR =
org.apache.coyote.Constants.SENDFILE_SUPPORTED_ATTR;
/**
* The request attribute that can be used by a servlet to pass
* to the connector the name of the file that is to be served
* by sendfile. The value should be {@code java.lang.String}
* that is {@code File.getCanonicalPath()} of the file to be served.
*
* Duplicated here for neater code in the catalina packages.
*/
public static final String SENDFILE_FILENAME_ATTR =
org.apache.coyote.Constants.SENDFILE_FILENAME_ATTR;
/**
* The request attribute that can be used by a servlet to pass
* to the connector the start offset of the part of a file
* that is to be served by sendfile. The value should be
* {@code java.lang.Long}. To serve complete file
* the value should be {@code Long.valueOf(0)}.
*
* Duplicated here for neater code in the catalina packages.
*/
public static final String SENDFILE_FILE_START_ATTR =
org.apache.coyote.Constants.SENDFILE_FILE_START_ATTR;
/**
* The request attribute that can be used by a servlet to pass
* to the connector the end offset (not including) of the part
* of a file that is to be served by sendfile. The value should be
* {@code java.lang.Long}. To serve complete file
* the value should be equal to the length of the file.
*
* Duplicated here for neater code in the catalina packages.
*/
public static final String SENDFILE_FILE_END_ATTR =
org.apache.coyote.Constants.SENDFILE_FILE_END_ATTR;
/**
* The request attribute set by the RemoteIpFilter, RemoteIpValve (and may
* be set by other similar components) that identifies for the connector the
* remote IP address claimed to be associated with this request when a
* request is received via one or more proxies. It is typically provided via
* the X-Forwarded-For HTTP header.
*
* Duplicated here for neater code in the catalina packages.
*/
public static final String REMOTE_ADDR_ATTRIBUTE =
org.apache.coyote.Constants.REMOTE_ADDR_ATTRIBUTE;
/**
* The request attribute that is set to the value of {@code Boolean.TRUE}
* by the RemoteIpFilter, RemoteIpValve (and other similar components) that identifies
* a request which been forwarded via one or more proxies.
*/
public static final String REQUEST_FORWARDED_ATTRIBUTE =
"org.apache.tomcat.request.forwarded";
public static final String ASYNC_SUPPORTED_ATTR =
"org.apache.catalina.ASYNC_SUPPORTED";
/**
* The request attribute that is set to {@code Boolean.TRUE} if some request
* parameters have been ignored during request parameters parsing. It can
* happen, for example, if there is a limit on the total count of parseable
* parameters, or if parameter cannot be decoded, or any other error
* happened during parameter parsing.
*/
public static final String PARAMETER_PARSE_FAILED_ATTR =
"org.apache.catalina.parameter_parse_failed";
/**
* The reason that the parameter parsing failed.
*/
public static final String PARAMETER_PARSE_FAILED_REASON_ATTR =
"org.apache.catalina.parameter_parse_failed_reason";
/**
* The master flag which controls strict servlet specification
* compliance.
*/
public static final boolean STRICT_SERVLET_COMPLIANCE =
Boolean.parseBoolean(System.getProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE", "false"));
/**
* Has security been turned on?
*/
public static final boolean IS_SECURITY_ENABLED =
(System.getSecurityManager() != null);
/**
* Default domain for MBeans if none can be determined
*/
public static final String DEFAULT_MBEAN_DOMAIN = "Catalina";
/**
* Name of the system property containing
* the tomcat product installation path
*/
public static final String CATALINA_HOME_PROP = "catalina.home";
/**
* Name of the system property containing
* the tomcat instance installation path
*/
public static final String CATALINA_BASE_PROP = "catalina.base";
/**
* Name of the ServletContext init-param that determines if the JSP engine
* should validate *.tld files when parsing them.
* <p>
* This must be kept in sync with org.apache.jasper.Constants
*/
public static final String JASPER_XML_VALIDATION_TLD_INIT_PARAM =
"org.apache.jasper.XML_VALIDATE_TLD";
/**
* Name of the ServletContext init-param that determines if the JSP engine
* will block external entities from being used in *.tld, *.jspx, *.tagx and
* tagplugin.xml files.
* <p>
* This must be kept in sync with org.apache.jasper.Constants
*/
public static final String JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM =
"org.apache.jasper.XML_BLOCK_EXTERNAL";
/**
* Name of the ServletContext attribute under which we store the context
* Realm's CredentialHandler (if both the Realm and the CredentialHandler
* exist).
*/
public static final String CREDENTIAL_HANDLER
= "org.apache.catalina.CredentialHandler";
}

View File

@@ -0,0 +1,117 @@
/*
* 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;
import java.security.Principal;
import java.util.Iterator;
/**
* <p>Abstract representation of a group of {@link User}s in a
* {@link UserDatabase}. Each user that is a member of this group
* inherits the {@link Role}s assigned to the group.</p>
*
* @author Craig R. McClanahan
* @since 4.1
*/
public interface Group extends Principal {
// ------------------------------------------------------------- Properties
/**
* @return the description of this group.
*/
public String getDescription();
/**
* Set the description of this group.
*
* @param description The new description
*/
public void setDescription(String description);
/**
* @return the group name of this group, which must be unique
* within the scope of a {@link UserDatabase}.
*/
public String getGroupname();
/**
* Set the group name of this group, which must be unique
* within the scope of a {@link UserDatabase}.
*
* @param groupname The new group name
*/
public void setGroupname(String groupname);
/**
* @return the set of {@link Role}s assigned specifically to this group.
*/
public Iterator<Role> getRoles();
/**
* @return the {@link UserDatabase} within which this Group is defined.
*/
public UserDatabase getUserDatabase();
/**
* @return the set of {@link User}s that are members of this group.
*/
public Iterator<User> getUsers();
// --------------------------------------------------------- Public Methods
/**
* Add a new {@link Role} to those assigned specifically to this group.
*
* @param role The new role
*/
public void addRole(Role role);
/**
* Is this group specifically assigned the specified {@link Role}?
*
* @param role The role to check
*
* @return <code>true</code> if the group is assigned to the specified role
* otherwise <code>false</code>
*/
public boolean isInRole(Role role);
/**
* Remove a {@link Role} from those assigned to this group.
*
* @param role The old role
*/
public void removeRole(Role role);
/**
* Remove all {@link Role}s from those assigned to this group.
*/
public void removeRoles();
}

View File

@@ -0,0 +1,256 @@
/*
* 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;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
/**
* A <b>Host</b> is a Container that represents a virtual host in the
* Catalina servlet engine. It is useful in the following types of scenarios:
* <ul>
* <li>You wish to use Interceptors that see every single request processed
* by this particular virtual host.
* <li>You wish to run Catalina in with a standalone HTTP connector, but still
* want support for multiple virtual hosts.
* </ul>
* In general, you would not use a Host when deploying Catalina connected
* to a web server (such as Apache), because the Connector will have
* utilized the web server's facilities to determine which Context (or
* perhaps even which Wrapper) should be utilized to process this request.
* <p>
* The parent Container attached to a Host is generally an Engine, but may
* be some other implementation, or may be omitted if it is not necessary.
* <p>
* The child containers attached to a Host are generally implementations
* of Context (representing an individual servlet context).
*
* @author Craig R. McClanahan
*/
public interface Host extends Container {
// ----------------------------------------------------- Manifest Constants
/**
* The ContainerEvent event type sent when a new alias is added
* by <code>addAlias()</code>.
*/
public static final String ADD_ALIAS_EVENT = "addAlias";
/**
* The ContainerEvent event type sent when an old alias is removed
* by <code>removeAlias()</code>.
*/
public static final String REMOVE_ALIAS_EVENT = "removeAlias";
// ------------------------------------------------------------- Properties
/**
* @return the XML root for this Host. This can be an absolute
* pathname, a relative pathname, or a URL.
* If null, the base path defaults to
* ${catalina.base}/conf/&lt;engine name&gt;/&lt;host name&gt; directory
*/
public String getXmlBase();
/**
* Set the Xml root for this Host. This can be an absolute
* pathname, a relative pathname, or a URL.
* If null, the base path defaults to
* ${catalina.base}/conf/&lt;engine name&gt;/&lt;host name&gt; directory
* @param xmlBase The new XML root
*/
public void setXmlBase(String xmlBase);
/**
* @return a default configuration path of this Host. The file will be
* canonical if possible.
*/
public File getConfigBaseFile();
/**
* @return the application root for this Host. This can be an absolute
* pathname, a relative pathname, or a URL.
*/
public String getAppBase();
/**
* @return an absolute {@link File} for the appBase of this Host. The file
* will be canonical if possible. There is no guarantee that that the
* appBase exists.
*/
public File getAppBaseFile();
/**
* Set the application root for this Host. This can be an absolute
* pathname, a relative pathname, or a URL.
*
* @param appBase The new application root
*/
public void setAppBase(String appBase);
/**
* @return the value of the auto deploy flag. If true, it indicates that
* this host's child webapps should be discovered and automatically
* deployed dynamically.
*/
public boolean getAutoDeploy();
/**
* Set the auto deploy flag value for this host.
*
* @param autoDeploy The new auto deploy flag
*/
public void setAutoDeploy(boolean autoDeploy);
/**
* @return the Java class name of the context configuration class
* for new web applications.
*/
public String getConfigClass();
/**
* Set the Java class name of the context configuration class
* for new web applications.
*
* @param configClass The new context configuration class
*/
public void setConfigClass(String configClass);
/**
* @return the value of the deploy on startup flag. If true, it indicates
* that this host's child webapps should be discovered and automatically
* deployed.
*/
public boolean getDeployOnStartup();
/**
* Set the deploy on startup flag value for this host.
*
* @param deployOnStartup The new deploy on startup flag
*/
public void setDeployOnStartup(boolean deployOnStartup);
/**
* @return the regular expression that defines the files and directories in
* the host's appBase that will be ignored by the automatic deployment
* process.
*/
public String getDeployIgnore();
/**
* @return the compiled regular expression that defines the files and
* directories in the host's appBase that will be ignored by the automatic
* deployment process.
*/
public Pattern getDeployIgnorePattern();
/**
* Set the regular expression that defines the files and directories in
* the host's appBase that will be ignored by the automatic deployment
* process.
*
* @param deployIgnore A regular expression matching file names
*/
public void setDeployIgnore(String deployIgnore);
/**
* @return the executor that is used for starting and stopping contexts. This
* is primarily for use by components deploying contexts that want to do
* this in a multi-threaded manner.
*/
public ExecutorService getStartStopExecutor();
/**
* Returns <code>true</code> if the Host will attempt to create directories for appBase and xmlBase
* unless they already exist.
* @return true if the Host will attempt to create directories
*/
public boolean getCreateDirs();
/**
* Should the Host attempt to create directories for xmlBase and appBase
* upon startup.
*
* @param createDirs The new value for this flag
*/
public void setCreateDirs(boolean createDirs);
/**
* @return <code>true</code> of the Host is configured to automatically undeploy old
* versions of applications deployed using parallel deployment. This only
* takes effect is {@link #getAutoDeploy()} also returns <code>true</code>.
*/
public boolean getUndeployOldVersions();
/**
* Set to <code>true</code> if the Host should automatically undeploy old versions of
* applications deployed using parallel deployment. This only takes effect
* if {@link #getAutoDeploy()} returns <code>true</code>.
*
* @param undeployOldVersions The new value for this flag
*/
public void setUndeployOldVersions(boolean undeployOldVersions);
// --------------------------------------------------------- Public Methods
/**
* Add an alias name that should be mapped to this same Host.
*
* @param alias The alias to be added
*/
public void addAlias(String alias);
/**
* @return the set of alias names for this Host. If none are defined,
* a zero length array is returned.
*/
public String[] findAliases();
/**
* Remove the specified alias name from the aliases for this Host.
*
* @param alias Alias name to be removed
*/
public void removeAlias(String alias);
}

View File

@@ -0,0 +1,52 @@
/*
* 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;
import javax.management.MBeanRegistration;
import javax.management.ObjectName;
/**
* This interface is implemented by components that will be registered with an
* MBean server when they are created and unregistered when they are destroyed.
* It is primarily intended to be implemented by components that implement
* {@link Lifecycle} but is not exclusively for them.
*/
public interface JmxEnabled extends MBeanRegistration {
/**
* @return the domain under which this component will be / has been
* registered.
*/
String getDomain();
/**
* Specify the domain under which this component should be registered. Used
* with components that cannot (easily) navigate the component hierarchy to
* determine the correct domain to use.
*
* @param domain The name of the domain under which this component should be
* registered
*/
void setDomain(String domain);
/**
* @return the name under which this component has been registered with JMX.
*/
ObjectName getObjectName();
}

View File

@@ -0,0 +1,319 @@
/*
* 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;
/**
* Common interface for component life cycle methods. Catalina components
* may implement this interface (as well as the appropriate interface(s) for
* the functionality they support) in order to provide a consistent mechanism
* to start and stop the component.
* <br>
* The valid state transitions for components that support {@link Lifecycle}
* are:
* <pre>
* start()
* -----------------------------
* | |
* | init() |
* NEW -»-- INITIALIZING |
* | | | | ------------------«-----------------------
* | | |auto | | |
* | | \|/ start() \|/ \|/ auto auto stop() |
* | | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- |
* | | | | |
* | |destroy()| | |
* | --»-----«-- ------------------------«-------------------------------- ^
* | | | |
* | | \|/ auto auto start() |
* | | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
* | \|/ ^ | ^
* | | stop() | | |
* | | -------------------------- | |
* | | | | |
* | | | destroy() destroy() | |
* | | FAILED ----»------ DESTROYING ---«----------------- |
* | | ^ | |
* | | destroy() | |auto |
* | --------»----------------- \|/ |
* | DESTROYED |
* | |
* | stop() |
* ----»-----------------------------»------------------------------
*
* Any state can transition to FAILED.
*
* Calling start() while a component is in states STARTING_PREP, STARTING or
* STARTED has no effect.
*
* Calling start() while a component is in state NEW will cause init() to be
* called immediately after the start() method is entered.
*
* Calling stop() while a component is in states STOPPING_PREP, STOPPING or
* STOPPED has no effect.
*
* Calling stop() while a component is in state NEW transitions the component
* to STOPPED. This is typically encountered when a component fails to start and
* does not start all its sub-components. When the component is stopped, it will
* try to stop all sub-components - even those it didn't start.
*
* Attempting any other transition will throw {@link LifecycleException}.
*
* </pre>
* The {@link LifecycleEvent}s fired during state changes are defined in the
* methods that trigger the changed. No {@link LifecycleEvent}s are fired if the
* attempted transition is not valid.
*
* @author Craig R. McClanahan
*/
public interface Lifecycle {
// ----------------------------------------------------- Manifest Constants
/**
* The LifecycleEvent type for the "component before init" event.
*/
public static final String BEFORE_INIT_EVENT = "before_init";
/**
* The LifecycleEvent type for the "component after init" event.
*/
public static final String AFTER_INIT_EVENT = "after_init";
/**
* The LifecycleEvent type for the "component start" event.
*/
public static final String START_EVENT = "start";
/**
* The LifecycleEvent type for the "component before start" event.
*/
public static final String BEFORE_START_EVENT = "before_start";
/**
* The LifecycleEvent type for the "component after start" event.
*/
public static final String AFTER_START_EVENT = "after_start";
/**
* The LifecycleEvent type for the "component stop" event.
*/
public static final String STOP_EVENT = "stop";
/**
* The LifecycleEvent type for the "component before stop" event.
*/
public static final String BEFORE_STOP_EVENT = "before_stop";
/**
* The LifecycleEvent type for the "component after stop" event.
*/
public static final String AFTER_STOP_EVENT = "after_stop";
/**
* The LifecycleEvent type for the "component after destroy" event.
*/
public static final String AFTER_DESTROY_EVENT = "after_destroy";
/**
* The LifecycleEvent type for the "component before destroy" event.
*/
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
/**
* The LifecycleEvent type for the "periodic" event.
*/
public static final String PERIODIC_EVENT = "periodic";
/**
* The LifecycleEvent type for the "configure_start" event. Used by those
* components that use a separate component to perform configuration and
* need to signal when configuration should be performed - usually after
* {@link #BEFORE_START_EVENT} and before {@link #START_EVENT}.
*/
public static final String CONFIGURE_START_EVENT = "configure_start";
/**
* The LifecycleEvent type for the "configure_stop" event. Used by those
* components that use a separate component to perform configuration and
* need to signal when de-configuration should be performed - usually after
* {@link #STOP_EVENT} and before {@link #AFTER_STOP_EVENT}.
*/
public static final String CONFIGURE_STOP_EVENT = "configure_stop";
// --------------------------------------------------------- Public Methods
/**
* Add a LifecycleEvent listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener);
/**
* Get the life cycle listeners associated with this life cycle.
*
* @return An array containing the life cycle listeners associated with this
* life cycle. If this component has no listeners registered, a
* zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners();
/**
* Remove a LifecycleEvent listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener);
/**
* Prepare the component for starting. This method should perform any
* initialization required post object creation. The following
* {@link LifecycleEvent}s will be fired in the following order:
* <ol>
* <li>INIT_EVENT: On the successful completion of component
* initialization.</li>
* </ol>
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void init() throws LifecycleException;
/**
* Prepare for the beginning of active use of the public methods other than
* property getters/setters and life cycle methods of this component. This
* method should be called before any of the public methods other than
* property getters/setters and life cycle methods of this component are
* utilized. The following {@link LifecycleEvent}s will be fired in the
* following order:
* <ol>
* <li>BEFORE_START_EVENT: At the beginning of the method. It is as this
* point the state transitions to
* {@link LifecycleState#STARTING_PREP}.</li>
* <li>START_EVENT: During the method once it is safe to call start() for
* any child components. It is at this point that the
* state transitions to {@link LifecycleState#STARTING}
* and that the public methods other than property
* getters/setters and life cycle methods may be
* used.</li>
* <li>AFTER_START_EVENT: At the end of the method, immediately before it
* returns. It is at this point that the state
* transitions to {@link LifecycleState#STARTED}.
* </li>
* </ol>
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void start() throws LifecycleException;
/**
* Gracefully terminate the active use of the public methods other than
* property getters/setters and life cycle methods of this component. Once
* the STOP_EVENT is fired, the public methods other than property
* getters/setters and life cycle methods should not be used. The following
* {@link LifecycleEvent}s will be fired in the following order:
* <ol>
* <li>BEFORE_STOP_EVENT: At the beginning of the method. It is at this
* point that the state transitions to
* {@link LifecycleState#STOPPING_PREP}.</li>
* <li>STOP_EVENT: During the method once it is safe to call stop() for
* any child components. It is at this point that the
* state transitions to {@link LifecycleState#STOPPING}
* and that the public methods other than property
* getters/setters and life cycle methods may no longer be
* used.</li>
* <li>AFTER_STOP_EVENT: At the end of the method, immediately before it
* returns. It is at this point that the state
* transitions to {@link LifecycleState#STOPPED}.
* </li>
* </ol>
*
* Note that if transitioning from {@link LifecycleState#FAILED} then the
* three events above will be fired but the component will transition
* directly from {@link LifecycleState#FAILED} to
* {@link LifecycleState#STOPPING}, bypassing
* {@link LifecycleState#STOPPING_PREP}
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
public void stop() throws LifecycleException;
/**
* Prepare to discard the object. The following {@link LifecycleEvent}s will
* be fired in the following order:
* <ol>
* <li>DESTROY_EVENT: On the successful completion of component
* destruction.</li>
* </ol>
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void destroy() throws LifecycleException;
/**
* Obtain the current state of the source component.
*
* @return The current state of the source component.
*/
public LifecycleState getState();
/**
* Obtain a textual representation of the current component state. Useful
* for JMX. The format of this string may vary between point releases and
* should not be relied upon to determine component state. To determine
* component state, use {@link #getState()}.
*
* @return The name of the current component state.
*/
public String getStateName();
/**
* Marker interface used to indicate that the instance should only be used
* once. Calling {@link #stop()} on an instance that supports this interface
* will automatically call {@link #destroy()} after {@link #stop()}
* completes.
*/
public interface SingleUse {
}
}

View File

@@ -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;
import java.util.EventObject;
/**
* General event for notifying listeners of significant changes on a component
* that implements the Lifecycle interface.
*
* @author Craig R. McClanahan
*/
public final class LifecycleEvent extends EventObject {
private static final long serialVersionUID = 1L;
/**
* Construct a new LifecycleEvent with the specified parameters.
*
* @param lifecycle Component on which this event occurred
* @param type Event type (required)
* @param data Event data (if any)
*/
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle);
this.type = type;
this.data = data;
}
/**
* The event data associated with this event.
*/
private final Object data;
/**
* The event type this instance represents.
*/
private final String type;
/**
* @return the event data of this event.
*/
public Object getData() {
return data;
}
/**
* @return the Lifecycle on which this event occurred.
*/
public Lifecycle getLifecycle() {
return (Lifecycle) getSource();
}
/**
* @return the event type of this event.
*/
public String getType() {
return this.type;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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;
/**
* General purpose exception that is thrown to indicate a lifecycle related
* problem. Such exceptions should generally be considered fatal to the
* operation of the application containing this component.
*
* @author Craig R. McClanahan
*/
public final class LifecycleException extends Exception {
private static final long serialVersionUID = 1L;
//------------------------------------------------------------ Constructors
/**
* Construct a new LifecycleException with no other information.
*/
public LifecycleException() {
super();
}
/**
* Construct a new LifecycleException for the specified message.
*
* @param message Message describing this exception
*/
public LifecycleException(String message) {
super(message);
}
/**
* Construct a new LifecycleException for the specified throwable.
*
* @param throwable Throwable that caused this exception
*/
public LifecycleException(Throwable throwable) {
super(throwable);
}
/**
* Construct a new LifecycleException for the specified message
* and throwable.
*
* @param message Message describing this exception
* @param throwable Throwable that caused this exception
*/
public LifecycleException(String message, Throwable throwable) {
super(message, throwable);
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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;
/**
* Interface defining a listener for significant events (including "component
* start" and "component stop" generated by a component that implements the
* Lifecycle interface. The listener will be fired after the associated state
* change has taken place.
*
* @author Craig R. McClanahan
*/
public interface LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}

View File

@@ -0,0 +1,65 @@
/*
* 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;
/**
* The list of valid states for components that implement {@link Lifecycle}.
* See {@link Lifecycle} for the state transition diagram.
*/
public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null);
private final boolean available;
private final String lifecycleEvent;
private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}
/**
* May the public methods other than property getters/setters and lifecycle
* methods be called for a component in this state? It returns
* <code>true</code> for any component in any of the following states:
* <ul>
* <li>{@link #STARTING}</li>
* <li>{@link #STARTED}</li>
* <li>{@link #STOPPING_PREP}</li>
* </ul>
*
* @return <code>true</code> if the component is available for use,
* otherwise <code>false</code>
*/
public boolean isAvailable() {
return available;
}
public String getLifecycleEvent() {
return lifecycleEvent;
}
}

View File

@@ -0,0 +1,135 @@
/*
* 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;
import java.beans.PropertyChangeListener;
/**
* A <b>Loader</b> represents a Java ClassLoader implementation that can
* be used by a Container to load class files (within a repository associated
* with the Loader) that are designed to be reloaded upon request, as well as
* a mechanism to detect whether changes have occurred in the underlying
* repository.
* <p>
* In order for a <code>Loader</code> implementation to successfully operate
* with a <code>Context</code> implementation that implements reloading, it
* must obey the following constraints:
* <ul>
* <li>Must implement <code>Lifecycle</code> so that the Context can indicate
* that a new class loader is required.
* <li>The <code>start()</code> method must unconditionally create a new
* <code>ClassLoader</code> implementation.
* <li>The <code>stop()</code> method must throw away its reference to the
* <code>ClassLoader</code> previously utilized, so that the class loader,
* all classes loaded by it, and all objects of those classes, can be
* garbage collected.
* <li>Must allow a call to <code>stop()</code> to be followed by a call to
* <code>start()</code> on the same <code>Loader</code> instance.
* <li>Based on a policy chosen by the implementation, must call the
* <code>Context.reload()</code> method on the owning <code>Context</code>
* when a change to one or more of the class files loaded by this class
* loader is detected.
* </ul>
*
* @author Craig R. McClanahan
*/
public interface Loader {
/**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
*/
public void backgroundProcess();
/**
* @return the Java class loader to be used by this Container.
*/
public ClassLoader getClassLoader();
/**
* @return the Context with which this Loader has been associated.
*/
public Context getContext();
/**
* Set the Context with which this Loader has been associated.
*
* @param context The associated Context
*/
public void setContext(Context context);
/**
* @return the "follow standard delegation model" flag used to configure
* our ClassLoader.
*/
public boolean getDelegate();
/**
* Set the "follow standard delegation model" flag used to configure
* our ClassLoader.
*
* @param delegate The new flag
*/
public void setDelegate(boolean delegate);
/**
* @return the reloadable flag for this Loader.
*/
public boolean getReloadable();
/**
* Set the reloadable flag for this Loader.
*
* @param reloadable The new reloadable flag
*/
public void setReloadable(boolean reloadable);
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Has the internal repository associated with this Loader been modified,
* such that the loaded classes should be reloaded?
*
* @return <code>true</code> when the repository has been modified,
* <code>false</code> otherwise
*/
public boolean modified();
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
}

View File

@@ -0,0 +1,354 @@
/*
* 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;
import java.beans.PropertyChangeListener;
import java.io.IOException;
/**
* A <b>Manager</b> manages the pool of Sessions that are associated with a
* particular Context. Different Manager implementations may support
* value-added features such as the persistent storage of session data,
* as well as migrating sessions for distributable web applications.
* <p>
* In order for a <code>Manager</code> implementation to successfully operate
* with a <code>Context</code> implementation that implements reloading, it
* must obey the following constraints:
* <ul>
* <li>Must implement <code>Lifecycle</code> so that the Context can indicate
* that a restart is required.
* <li>Must allow a call to <code>stop()</code> to be followed by a call to
* <code>start()</code> on the same <code>Manager</code> instance.
* </ul>
*
* @author Craig R. McClanahan
*/
public interface Manager {
// ------------------------------------------------------------- Properties
/**
* Get the Context with which this Manager is associated.
*
* @return The associated Context
*/
public Context getContext();
/**
* Set the Context with which this Manager is associated. The Context must
* be set to a non-null value before the Manager is first used. Multiple
* calls to this method before first use are permitted. Once the Manager has
* been used, this method may not be used to change the Context (including
* setting a {@code null} value) that the Manager is associated with.
*
* @param context The newly associated Context
*/
public void setContext(Context context);
/**
* @return the session id generator
*/
public SessionIdGenerator getSessionIdGenerator();
/**
* Sets the session id generator
*
* @param sessionIdGenerator The session id generator
*/
public void setSessionIdGenerator(SessionIdGenerator sessionIdGenerator);
/**
* Returns the total number of sessions created by this manager.
*
* @return Total number of sessions created by this manager.
*/
public long getSessionCounter();
/**
* Sets the total number of sessions created by this manager.
*
* @param sessionCounter Total number of sessions created by this manager.
*/
public void setSessionCounter(long sessionCounter);
/**
* Gets the maximum number of sessions that have been active at the same
* time.
*
* @return Maximum number of sessions that have been active at the same
* time
*/
public int getMaxActive();
/**
* (Re)sets the maximum number of sessions that have been active at the
* same time.
*
* @param maxActive Maximum number of sessions that have been active at
* the same time.
*/
public void setMaxActive(int maxActive);
/**
* Gets the number of currently active sessions.
*
* @return Number of currently active sessions
*/
public int getActiveSessions();
/**
* Gets the number of sessions that have expired.
*
* @return Number of sessions that have expired
*/
public long getExpiredSessions();
/**
* Sets the number of sessions that have expired.
*
* @param expiredSessions Number of sessions that have expired
*/
public void setExpiredSessions(long expiredSessions);
/**
* Gets the number of sessions that were not created because the maximum
* number of active sessions was reached.
*
* @return Number of rejected sessions
*/
public int getRejectedSessions();
/**
* Gets the longest time (in seconds) that an expired session had been
* alive.
*
* @return Longest time (in seconds) that an expired session had been
* alive.
*/
public int getSessionMaxAliveTime();
/**
* Sets the longest time (in seconds) that an expired session had been
* alive.
*
* @param sessionMaxAliveTime Longest time (in seconds) that an expired
* session had been alive.
*/
public void setSessionMaxAliveTime(int sessionMaxAliveTime);
/**
* Gets the average time (in seconds) that expired sessions had been
* alive. This may be based on sample data.
*
* @return Average time (in seconds) that expired sessions had been
* alive.
*/
public int getSessionAverageAliveTime();
/**
* Gets the current rate of session creation (in session per minute). This
* may be based on sample data.
*
* @return The current rate (in sessions per minute) of session creation
*/
public int getSessionCreateRate();
/**
* Gets the current rate of session expiration (in session per minute). This
* may be based on sample data
*
* @return The current rate (in sessions per minute) of session expiration
*/
public int getSessionExpireRate();
// --------------------------------------------------------- Public Methods
/**
* Add this Session to the set of active Sessions for this Manager.
*
* @param session Session to be added
*/
public void add(Session session);
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Change the session ID of the current session to a new randomly generated
* session ID.
*
* @param session The session to change the session ID for
*/
public void changeSessionId(Session session);
/**
* Change the session ID of the current session to a specified session ID.
*
* @param session The session to change the session ID for
* @param newId new session ID
*/
public void changeSessionId(Session session, String newId);
/**
* Get a session from the recycled ones or create a new empty one.
* The PersistentManager manager does not need to create session data
* because it reads it from the Store.
*
* @return An empty Session object
*/
public Session createEmptySession();
/**
* Construct and return a new session object, based on the default
* settings specified by this Manager's properties. The session
* id specified will be used as the session id.
* If a new session cannot be created for any reason, return
* <code>null</code>.
*
* @param sessionId The session id which should be used to create the
* new session; if <code>null</code>, the session
* id will be assigned by this method, and available via the getId()
* method of the returned session.
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
*
* @return An empty Session object with the given ID or a newly created
* session ID if none was specified
*/
public Session createSession(String sessionId);
/**
* Return the active Session, associated with this Manager, with the
* specified session id (if any); otherwise return <code>null</code>.
*
* @param id The session id for the session to be returned
*
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
* @exception IOException if an input/output error occurs while
* processing this request
*
* @return the request session or {@code null} if a session with the
* requested ID could not be found
*/
public Session findSession(String id) throws IOException;
/**
* Return the set of active Sessions associated with this Manager.
* If this Manager has no active Sessions, a zero-length array is returned.
*
* @return All the currently active sessions managed by this manager
*/
public Session[] findSessions();
/**
* Load any currently active sessions that were previously unloaded
* to the appropriate persistence mechanism, if any. If persistence is not
* supported, this method returns without doing anything.
*
* @exception ClassNotFoundException if a serialized class cannot be
* found during the reload
* @exception IOException if an input/output error occurs
*/
public void load() throws ClassNotFoundException, IOException;
/**
* Remove this Session from the active Sessions for this Manager.
*
* @param session Session to be removed
*/
public void remove(Session session);
/**
* Remove this Session from the active Sessions for this Manager.
*
* @param session Session to be removed
* @param update Should the expiration statistics be updated
*/
public void remove(Session session, boolean update);
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
/**
* Save any currently active sessions in the appropriate persistence
* mechanism, if any. If persistence is not supported, this method
* returns without doing anything.
*
* @exception IOException if an input/output error occurs
*/
public void unload() throws IOException;
/**
* This method will be invoked by the context/container on a periodic
* basis and allows the manager to implement
* a method that executes periodic tasks, such as expiring sessions etc.
*/
public void backgroundProcess();
/**
* Would the Manager distribute the given session attribute? Manager
* implementations may provide additional configuration options to control
* which attributes are distributable.
*
* @param name The attribute name
* @param value The attribute value
*
* @return {@code true} if the Manager would distribute the given attribute
* otherwise {@code false}
*/
public boolean willAttributeDistribute(String name, Object value);
}

View File

@@ -0,0 +1,149 @@
/*
* 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;
import java.util.Set;
/**
* <p>Interface describing a collection of Valves that should be executed
* in sequence when the <code>invoke()</code> method is invoked. It is
* required that a Valve somewhere in the pipeline (usually the last one)
* must process the request and create the corresponding response, rather
* than trying to pass the request on.</p>
*
* <p>There is generally a single Pipeline instance associated with each
* Container. The container's normal request processing functionality is
* generally encapsulated in a container-specific Valve, which should always
* be executed at the end of a pipeline. To facilitate this, the
* <code>setBasic()</code> method is provided to set the Valve instance that
* will always be executed last. Other Valves will be executed in the order
* that they were added, before the basic Valve is executed.</p>
*
* @author Craig R. McClanahan
* @author Peter Donald
*/
public interface Pipeline {
/**
* @return the Valve instance that has been distinguished as the basic
* Valve for this Pipeline (if any).
*/
public Valve getBasic();
/**
* <p>Set the Valve instance that has been distinguished as the basic
* Valve for this Pipeline (if any). Prior to setting the basic Valve,
* the Valve's <code>setContainer()</code> will be called, if it
* implements <code>Contained</code>, with the owning Container as an
* argument. The method may throw an <code>IllegalArgumentException</code>
* if this Valve chooses not to be associated with this Container, or
* <code>IllegalStateException</code> if it is already associated with
* a different Container.</p>
*
* @param valve Valve to be distinguished as the basic Valve
*/
public void setBasic(Valve valve);
/**
* <p>Add a new Valve to the end of the pipeline associated with this
* Container. Prior to adding the Valve, the Valve's
* <code>setContainer()</code> method will be called, if it implements
* <code>Contained</code>, with the owning Container as an argument.
* The method may throw an
* <code>IllegalArgumentException</code> if this Valve chooses not to
* be associated with this Container, or <code>IllegalStateException</code>
* if it is already associated with a different Container.</p>
*
* <p>Implementation note: Implementations are expected to trigger the
* {@link Container#ADD_VALVE_EVENT} for the associated container if this
* call is successful.</p>
*
* @param valve Valve to be added
*
* @exception IllegalArgumentException if this Container refused to
* accept the specified Valve
* @exception IllegalArgumentException if the specified Valve refuses to be
* associated with this Container
* @exception IllegalStateException if the specified Valve is already
* associated with a different Container
*/
public void addValve(Valve valve);
/**
* @return the set of Valves in the pipeline associated with this
* Container, including the basic Valve (if any). If there are no
* such Valves, a zero-length array is returned.
*/
public Valve[] getValves();
/**
* Remove the specified Valve from the pipeline associated with this
* Container, if it is found; otherwise, do nothing. If the Valve is
* found and removed, the Valve's <code>setContainer(null)</code> method
* will be called if it implements <code>Contained</code>.
*
* <p>Implementation note: Implementations are expected to trigger the
* {@link Container#REMOVE_VALVE_EVENT} for the associated container if this
* call is successful.</p>
*
* @param valve Valve to be removed
*/
public void removeValve(Valve valve);
/**
* @return the Valve instance that has been distinguished as the basic
* Valve for this Pipeline (if any).
*/
public Valve getFirst();
/**
* Returns true if all the valves in this pipeline support async, false otherwise
* @return true if all the valves in this pipeline support async, false otherwise
*/
public boolean isAsyncSupported();
/**
* @return the Container with which this Pipeline is associated.
*/
public Container getContainer();
/**
* Set the Container with which this Pipeline is associated.
*
* @param container The new associated container
*/
public void setContainer(Container container);
/**
* Identifies the Valves, if any, in this Pipeline that do not support
* async.
*
* @param result The Set to which the fully qualified class names of each
* Valve in this Pipeline that does not support async will be
* added
*/
public void findNonAsyncValves(Set<String> result);
}

View File

@@ -0,0 +1,244 @@
/*
* 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;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.ietf.jgss.GSSContext;
/**
* A <b>Realm</b> is a read-only facade for an underlying security realm
* used to authenticate individual users, and identify the security roles
* associated with those users. Realms can be attached at any Container
* level, but will typically only be attached to a Context, or higher level,
* Container.
*
* @author Craig R. McClanahan
*/
public interface Realm {
// ------------------------------------------------------------- Properties
/**
* @return the Container with which this Realm has been associated.
*/
public Container getContainer();
/**
* Set the Container with which this Realm has been associated.
*
* @param container The associated Container
*/
public void setContainer(Container container);
/**
* @return the CredentialHandler configured for this Realm.
*/
public CredentialHandler getCredentialHandler();
/**
* Set the CredentialHandler to be used by this Realm.
*
* @param credentialHandler the {@link CredentialHandler} to use
*/
public void setCredentialHandler(CredentialHandler credentialHandler);
// --------------------------------------------------------- Public Methods
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Try to authenticate with the specified username.
*
* @param username Username of the Principal to look up
* @return the associated principal, or <code>null</code> if none is
* associated.
*/
public Principal authenticate(String username);
/**
* Try to authenticate using the specified username and
* credentials.
*
* @param username Username of the Principal to look up
* @param credentials Password or other credentials to use in
* authenticating this username
* @return the associated principal, or <code>null</code> if there is none
*/
public Principal authenticate(String username, String credentials);
/**
* Try to authenticate with the specified username, which
* matches the digest calculated using the given parameters using the
* method described in RFC 2617 (which is a superset of RFC 2069).
*
* @param username Username of the Principal to look up
* @param digest Digest which has been submitted by the client
* @param nonce Unique (or supposedly unique) token which has been used
* for this request
* @param nc the nonce counter
* @param cnonce the client chosen nonce
* @param qop the "quality of protection" (<code>nc</code> and <code>cnonce</code>
* will only be used, if <code>qop</code> is not <code>null</code>).
* @param realm Realm name
* @param md5a2 Second MD5 digest used to calculate the digest :
* MD5(Method + ":" + uri)
* @return the associated principal, or <code>null</code> if there is none.
*/
public Principal authenticate(String username, String digest,
String nonce, String nc, String cnonce,
String qop, String realm,
String md5a2);
/**
* Try to authenticate using a {@link GSSContext}
*
* @param gssContext The gssContext processed by the {@link Authenticator}.
* @param storeCreds Should the realm attempt to store the delegated
* credentials in the returned Principal?
* @return the associated principal, or <code>null</code> if there is none
*/
public Principal authenticate(GSSContext gssContext, boolean storeCreds);
/**
* Try to authenticate using {@link X509Certificate}s
*
* @param certs Array of client certificates, with the first one in
* the array being the certificate of the client itself.
* @return the associated principal, or <code>null</code> if there is none
*/
public Principal authenticate(X509Certificate certs[]);
/**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
*/
public void backgroundProcess();
/**
* Find the SecurityConstraints configured to guard the request URI for
* this request.
*
* @param request Request we are processing
* @param context {@link Context} for this request
* @return the configured {@link SecurityConstraint}, of <code>null</code>
* if there is none
*/
public SecurityConstraint [] findSecurityConstraints(Request request,
Context context);
/**
* Perform access control based on the specified authorization constraint.
*
* @param request Request we are processing
* @param response Response we are creating
* @param constraint Security constraint we are enforcing
* @param context The Context to which client of this class is attached.
* @return <code>true</code> if this constraint is satisfied and processing
* should continue, or <code>false</code> otherwise
*
* @exception IOException if an input/output error occurs
*/
public boolean hasResourcePermission(Request request,
Response response,
SecurityConstraint [] constraint,
Context context)
throws IOException;
/**
* Check if the specified Principal has the specified
* security role, within the context of this Realm.
*
* @param wrapper wrapper context for evaluating role
* @param principal Principal for whom the role is to be checked
* @param role Security role to be checked
* @return <code>true</code> if the specified Principal has the specified
* security role, within the context of this Realm; otherwise return
* <code>false</code>.
*/
public boolean hasRole(Wrapper wrapper, Principal principal, String role);
/**
* Enforce any user data constraint required by the security constraint
* guarding this request URI.
*
* @param request Request we are processing
* @param response Response we are creating
* @param constraint Security constraint being checked
* @return <code>true</code> if this constraint
* was not violated and processing should continue, or <code>false</code>
* if we have created a response already.
*
* @exception IOException if an input/output error occurs
*/
public boolean hasUserDataPermission(Request request,
Response response,
SecurityConstraint []constraint)
throws IOException;
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
/**
* Return roles associated with given principal
* @param principal the {@link Principal} to get the roles for.
* @return principal roles
* @deprecated This will be removed in Tomcat 10.
*/
@Deprecated
public String[] getRoles(Principal principal);
/**
* Return the availability of the realm for authentication.
* @return <code>true</code> if the realm is able to perform authentication
*/
public boolean isAvailable();
}

View File

@@ -0,0 +1,74 @@
/*
* 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;
import java.security.Principal;
/**
* <p>Abstract representation of a security role, suitable for use in
* environments like JAAS that want to deal with <code>Principals</code>.</p>
*
* @author Craig R. McClanahan
* @since 4.1
*/
public interface Role extends Principal {
// ------------------------------------------------------------- Properties
/**
* @return the description of this role.
*/
public String getDescription();
/**
* Set the description of this role.
*
* @param description The new description
*/
public void setDescription(String description);
/**
* @return the role name of this role, which must be unique
* within the scope of a {@link UserDatabase}.
*/
public String getRolename();
/**
* Set the role name of this role, which must be unique
* within the scope of a {@link UserDatabase}.
*
* @param rolename The new role name
*/
public void setRolename(String rolename);
/**
* @return the {@link UserDatabase} within which this Role is defined.
*/
public UserDatabase getUserDatabase();
}

View File

@@ -0,0 +1,222 @@
/*
* 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;
import java.io.File;
import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.catalina.startup.Catalina;
/**
* A <code>Server</code> element represents the entire Catalina
* servlet container. Its attributes represent the characteristics of
* the servlet container as a whole. A <code>Server</code> may contain
* one or more <code>Services</code>, and the top level set of naming
* resources.
* <p>
* Normally, an implementation of this interface will also implement
* <code>Lifecycle</code>, such that when the <code>start()</code> and
* <code>stop()</code> methods are called, all of the defined
* <code>Services</code> are also started or stopped.
* <p>
* In between, the implementation must open a server socket on the port number
* specified by the <code>port</code> property. When a connection is accepted,
* the first line is read and compared with the specified shutdown command.
* If the command matches, shutdown of the server is initiated.
* <p>
* <strong>NOTE</strong> - The concrete implementation of this class should
* register the (singleton) instance with the <code>ServerFactory</code>
* class in its constructor(s).
*
* @author Craig R. McClanahan
*/
public interface Server extends Lifecycle {
// ------------------------------------------------------------- Properties
/**
* @return the global naming resources.
*/
public NamingResourcesImpl getGlobalNamingResources();
/**
* Set the global naming resources.
*
* @param globalNamingResources The new global naming resources
*/
public void setGlobalNamingResources
(NamingResourcesImpl globalNamingResources);
/**
* @return the global naming resources context.
*/
public javax.naming.Context getGlobalNamingContext();
/**
* @return the port number we listen to for shutdown commands.
*/
public int getPort();
/**
* Set the port number we listen to for shutdown commands.
*
* @param port The new port number
*/
public void setPort(int port);
/**
* @return the address on which we listen to for shutdown commands.
*/
public String getAddress();
/**
* Set the address on which we listen to for shutdown commands.
*
* @param address The new address
*/
public void setAddress(String address);
/**
* @return the shutdown command string we are waiting for.
*/
public String getShutdown();
/**
* Set the shutdown command we are waiting for.
*
* @param shutdown The new shutdown command
*/
public void setShutdown(String shutdown);
/**
* @return the parent class loader for this component. If not set, return
* {@link #getCatalina()} {@link Catalina#getParentClassLoader()}. If
* catalina has not been set, return the system class loader.
*/
public ClassLoader getParentClassLoader();
/**
* Set the parent class loader for this server.
*
* @param parent The new parent class loader
*/
public void setParentClassLoader(ClassLoader parent);
/**
* @return the outer Catalina startup/shutdown component if present.
*/
public Catalina getCatalina();
/**
* Set the outer Catalina startup/shutdown component if present.
*
* @param catalina the outer Catalina component
*/
public void setCatalina(Catalina catalina);
/**
* @return the configured base (instance) directory. Note that home and base
* may be the same (and are by default). If this is not set the value
* returned by {@link #getCatalinaHome()} will be used.
*/
public File getCatalinaBase();
/**
* Set the configured base (instance) directory. Note that home and base
* may be the same (and are by default).
*
* @param catalinaBase the configured base directory
*/
public void setCatalinaBase(File catalinaBase);
/**
* @return the configured home (binary) directory. Note that home and base
* may be the same (and are by default).
*/
public File getCatalinaHome();
/**
* Set the configured home (binary) directory. Note that home and base
* may be the same (and are by default).
*
* @param catalinaHome the configured home directory
*/
public void setCatalinaHome(File catalinaHome);
// --------------------------------------------------------- Public Methods
/**
* Add a new Service to the set of defined Services.
*
* @param service The Service to be added
*/
public void addService(Service service);
/**
* Wait until a proper shutdown command is received, then return.
*/
public void await();
/**
* Find the specified Service
*
* @param name Name of the Service to be returned
* @return the specified Service, or <code>null</code> if none exists.
*/
public Service findService(String name);
/**
* @return the set of Services defined within this Server.
*/
public Service[] findServices();
/**
* Remove the specified Service from the set associated from this
* Server.
*
* @param service The Service to be removed
*/
public void removeService(Service service);
/**
* @return the token necessary for operations on the associated JNDI naming
* context.
*/
public Object getNamingToken();
}

View File

@@ -0,0 +1,152 @@
/*
* 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;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.mapper.Mapper;
/**
* A <strong>Service</strong> is a group of one or more
* <strong>Connectors</strong> that share a single <strong>Container</strong>
* to process their incoming requests. This arrangement allows, for example,
* a non-SSL and SSL connector to share the same population of web apps.
* <p>
* A given JVM can contain any number of Service instances; however, they are
* completely independent of each other and share only the basic JVM facilities
* and classes on the system class path.
*
* @author Craig R. McClanahan
*/
public interface Service extends Lifecycle {
// ------------------------------------------------------------- Properties
/**
* @return the <code>Engine</code> that handles requests for all
* <code>Connectors</code> associated with this Service.
*/
public Engine getContainer();
/**
* Set the <code>Engine</code> that handles requests for all
* <code>Connectors</code> associated with this Service.
*
* @param engine The new Engine
*/
public void setContainer(Engine engine);
/**
* @return the name of this Service.
*/
public String getName();
/**
* Set the name of this Service.
*
* @param name The new service name
*/
public void setName(String name);
/**
* @return the <code>Server</code> with which we are associated (if any).
*/
public Server getServer();
/**
* Set the <code>Server</code> with which we are associated (if any).
*
* @param server The server that owns this Service
*/
public void setServer(Server server);
/**
* @return the parent class loader for this component. If not set, return
* {@link #getServer()} {@link Server#getParentClassLoader()}. If no server
* has been set, return the system class loader.
*/
public ClassLoader getParentClassLoader();
/**
* Set the parent class loader for this service.
*
* @param parent The new parent class loader
*/
public void setParentClassLoader(ClassLoader parent);
/**
* @return the domain under which this container will be / has been
* registered.
*/
public String getDomain();
// --------------------------------------------------------- Public Methods
/**
* Add a new Connector to the set of defined Connectors, and associate it
* with this Service's Container.
*
* @param connector The Connector to be added
*/
public void addConnector(Connector connector);
/**
* Find and return the set of Connectors associated with this Service.
*
* @return the set of associated Connectors
*/
public Connector[] findConnectors();
/**
* Remove the specified Connector from the set associated from this
* Service. The removed Connector will also be disassociated from our
* Container.
*
* @param connector The Connector to be removed
*/
public void removeConnector(Connector connector);
/**
* Adds a named executor to the service
* @param ex Executor
*/
public void addExecutor(Executor ex);
/**
* Retrieves all executors
* @return Executor[]
*/
public Executor[] findExecutors();
/**
* Retrieves executor by name, null if not found
* @param name String
* @return Executor
*/
public Executor getExecutor(String name);
/**
* Removes an executor from the service
* @param ex Executor
*/
public void removeExecutor(Executor ex);
/**
* @return the mapper associated with this Service.
*/
Mapper getMapper();
}

View File

@@ -0,0 +1,378 @@
/*
* 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;
import java.security.Principal;
import java.util.Iterator;
import javax.servlet.http.HttpSession;
/**
* A <b>Session</b> is the Catalina-internal facade for an
* <code>HttpSession</code> that is used to maintain state information
* between requests for a particular user of a web application.
*
* @author Craig R. McClanahan
*/
public interface Session {
// ----------------------------------------------------- Manifest Constants
/**
* The SessionEvent event type when a session is created.
*/
public static final String SESSION_CREATED_EVENT = "createSession";
/**
* The SessionEvent event type when a session is destroyed.
*/
public static final String SESSION_DESTROYED_EVENT = "destroySession";
/**
* The SessionEvent event type when a session is activated.
*/
public static final String SESSION_ACTIVATED_EVENT = "activateSession";
/**
* The SessionEvent event type when a session is passivated.
*/
public static final String SESSION_PASSIVATED_EVENT = "passivateSession";
// ------------------------------------------------------------- Properties
/**
* @return the authentication type used to authenticate our cached
* Principal, if any.
*/
public String getAuthType();
/**
* Set the authentication type used to authenticate our cached
* Principal, if any.
*
* @param authType The new cached authentication type
*/
public void setAuthType(String authType);
/**
* @return the creation time for this session.
*/
public long getCreationTime();
/**
* @return the creation time for this session, bypassing the session validity
* checks.
*/
public long getCreationTimeInternal();
/**
* Set the creation time for this session. This method is called by the
* Manager when an existing Session instance is reused.
*
* @param time The new creation time
*/
public void setCreationTime(long time);
/**
* @return the session identifier for this session.
*/
public String getId();
/**
* @return the session identifier for this session.
*/
public String getIdInternal();
/**
* Set the session identifier for this session and notifies any associated
* listeners that a new session has been created.
*
* @param id The new session identifier
*/
public void setId(String id);
/**
* Set the session identifier for this session and optionally notifies any
* associated listeners that a new session has been created.
*
* @param id The new session identifier
* @param notify Should any associated listeners be notified that a new
* session has been created?
*/
public void setId(String id, boolean notify);
/**
* @return the last time the client sent a request associated with this
* session, as the number of milliseconds since midnight, January 1, 1970
* GMT. Actions that your application takes, such as getting or setting
* a value associated with the session, do not affect the access time.
* This one gets updated whenever a request starts.
*/
public long getThisAccessedTime();
/**
* @return the last client access time without invalidation check
* @see #getThisAccessedTime()
*/
public long getThisAccessedTimeInternal();
/**
* @return the last time the client sent a request associated with this
* session, as the number of milliseconds since midnight, January 1, 1970
* GMT. Actions that your application takes, such as getting or setting
* a value associated with the session, do not affect the access time.
* This one gets updated whenever a request finishes.
*/
public long getLastAccessedTime();
/**
* @return the last client access time without invalidation check
* @see #getLastAccessedTime()
*/
public long getLastAccessedTimeInternal();
/**
* @return the idle time (in milliseconds) from last client access time.
*/
public long getIdleTime();
/**
* @return the idle time from last client access time without invalidation check
* @see #getIdleTime()
*/
public long getIdleTimeInternal();
/**
* @return the Manager within which this Session is valid.
*/
public Manager getManager();
/**
* Set the Manager within which this Session is valid.
*
* @param manager The new Manager
*/
public void setManager(Manager manager);
/**
* @return the maximum time interval, in seconds, between client requests
* before the servlet container will invalidate the session. A negative
* time indicates that the session should never time out.
*/
public int getMaxInactiveInterval();
/**
* Set the maximum time interval, in seconds, between client requests
* before the servlet container will invalidate the session. A negative
* time indicates that the session should never time out.
*
* @param interval The new maximum interval
*/
public void setMaxInactiveInterval(int interval);
/**
* Set the <code>isNew</code> flag for this session.
*
* @param isNew The new value for the <code>isNew</code> flag
*/
public void setNew(boolean isNew);
/**
* @return the authenticated Principal that is associated with this Session.
* This provides an <code>Authenticator</code> with a means to cache a
* previously authenticated Principal, and avoid potentially expensive
* <code>Realm.authenticate()</code> calls on every request. If there
* is no current associated Principal, return <code>null</code>.
*/
public Principal getPrincipal();
/**
* Set the authenticated Principal that is associated with this Session.
* This provides an <code>Authenticator</code> with a means to cache a
* previously authenticated Principal, and avoid potentially expensive
* <code>Realm.authenticate()</code> calls on every request.
*
* @param principal The new Principal, or <code>null</code> if none
*/
public void setPrincipal(Principal principal);
/**
* @return the <code>HttpSession</code> for which this object
* is the facade.
*/
public HttpSession getSession();
/**
* Set the <code>isValid</code> flag for this session.
*
* @param isValid The new value for the <code>isValid</code> flag
*/
public void setValid(boolean isValid);
/**
* @return <code>true</code> if the session is still valid
*/
public boolean isValid();
// --------------------------------------------------------- Public Methods
/**
* Update the accessed time information for this session. This method
* should be called by the context when a request comes in for a particular
* session, even if the application does not reference it.
*/
public void access();
/**
* Add a session event listener to this component.
*
* @param listener the SessionListener instance that should be notified
* for session events
*/
public void addSessionListener(SessionListener listener);
/**
* End access to the session.
*/
public void endAccess();
/**
* Perform the internal processing required to invalidate this session,
* without triggering an exception if the session has already expired.
*/
public void expire();
/**
* @return the object bound with the specified name to the internal notes
* for this session, or <code>null</code> if no such binding exists.
*
* @param name Name of the note to be returned
*/
public Object getNote(String name);
/**
* @return an Iterator containing the String names of all notes bindings
* that exist for this session.
*/
public Iterator<String> getNoteNames();
/**
* Release all object references, and initialize instance variables, in
* preparation for reuse of this object.
*/
public void recycle();
/**
* Remove any object bound to the specified name in the internal notes
* for this session.
*
* @param name Name of the note to be removed
*/
public void removeNote(String name);
/**
* Remove a session event listener from this component.
*
* @param listener remove the session listener, which will no longer be
* notified
*/
public void removeSessionListener(SessionListener listener);
/**
* Bind an object to a specified name in the internal notes associated
* with this session, replacing any existing binding for this name.
*
* @param name Name to which the object should be bound
* @param value Object to be bound to the specified name
*/
public void setNote(String name, Object value);
/**
* Inform the listeners about the change session ID.
*
* @param newId new session ID
* @param oldId old session ID
* @param notifySessionListeners Should any associated sessionListeners be
* notified that session ID has been changed?
* @param notifyContainerListeners Should any associated ContainerListeners
* be notified that session ID has been changed?
*/
public void tellChangedSessionId(String newId, String oldId,
boolean notifySessionListeners, boolean notifyContainerListeners);
/**
* Does the session implementation support the distributing of the given
* attribute? If the Manager is marked as distributable, then this method
* must be used to check attributes before adding them to a session and
* an {@link IllegalArgumentException} thrown if the proposed attribute is
* not distributable.
* <p>
* Note that the {@link Manager} implementation may further restrict which
* attributes are distributed but a {@link Manager} level restriction should
* not trigger an {@link IllegalArgumentException} in
* {@link HttpSession#setAttribute(String, Object)}
*
* @param name The attribute name
* @param value The attribute value
*
* @return {@code true} if distribution is supported, otherwise {@code
* false}
*/
public boolean isAttributeDistributable(String name, Object value);
}

View File

@@ -0,0 +1,100 @@
/*
* 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;
import java.util.EventObject;
/**
* General event for notifying listeners of significant changes on a Session.
*
* @author Craig R. McClanahan
*/
public final class SessionEvent extends EventObject {
private static final long serialVersionUID = 1L;
/**
* The event data associated with this event.
*/
private final Object data;
/**
* The Session on which this event occurred.
*/
private final Session session;
/**
* The event type this instance represents.
*/
private final String type;
/**
* Construct a new SessionEvent with the specified parameters.
*
* @param session Session on which this event occurred
* @param type Event type
* @param data Event data
*/
public SessionEvent(Session session, String type, Object data) {
super(session);
this.session = session;
this.type = type;
this.data = data;
}
/**
* @return the event data of this event.
*/
public Object getData() {
return this.data;
}
/**
* @return the Session on which this event occurred.
*/
public Session getSession() {
return this.session;
}
/**
* @return the event type of this event.
*/
public String getType() {
return this.type;
}
@Override
public String toString() {
return "SessionEvent['" + getSession() + "','" + getType() + "']";
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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;
public interface SessionIdGenerator {
/**
* @return the node identifier associated with this node which will be
* included in the generated session ID.
*/
public String getJvmRoute();
/**
* Specify the node identifier associated with this node which will be
* included in the generated session ID.
*
* @param jvmRoute The node identifier
*/
public void setJvmRoute(String jvmRoute);
/**
* @return the number of bytes for a session ID
*/
public int getSessionIdLength();
/**
* Specify the number of bytes for a session ID
*
* @param sessionIdLength Number of bytes
*/
public void setSessionIdLength(int sessionIdLength);
/**
* Generate and return a new session identifier.
*
* @return the newly generated session id
*/
public String generateSessionId();
/**
* Generate and return a new session identifier.
*
* @param route node identifier to include in generated id
* @return the newly generated session id
*/
public String generateSessionId(String route);
}

View File

@@ -0,0 +1,40 @@
/*
* 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;
import java.util.EventListener;
/**
* Interface defining a listener for significant Session generated events.
*
* @author Craig R. McClanahan
*/
public interface SessionListener extends EventListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event SessionEvent that has occurred
*/
public void sessionEvent(SessionEvent event);
}

View File

@@ -0,0 +1,136 @@
/*
* 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;
import java.beans.PropertyChangeListener;
import java.io.IOException;
/**
* A <b>Store</b> is the abstraction of a Catalina component that provides
* persistent storage and loading of Sessions and their associated user data.
* Implementations are free to save and load the Sessions to any media they
* wish, but it is assumed that saved Sessions are persistent across
* server or context restarts.
*
* @author Craig R. McClanahan
*/
public interface Store {
// ------------------------------------------------------------- Properties
/**
* @return the Manager instance associated with this Store.
*/
public Manager getManager();
/**
* Set the Manager associated with this Store.
*
* @param manager The Manager which will use this Store.
*/
public void setManager(Manager manager);
/**
* @return the number of Sessions present in this Store.
*
* @exception IOException if an input/output error occurs
*/
public int getSize() throws IOException;
// --------------------------------------------------------- Public Methods
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener);
/**
* @return an array containing the session identifiers of all Sessions
* currently saved in this Store. If there are no such Sessions, a
* zero-length array is returned.
*
* @exception IOException if an input/output error occurred
*/
public String[] keys() throws IOException;
/**
* Load and return the Session associated with the specified session
* identifier from this Store, without removing it. If there is no
* such stored Session, return <code>null</code>.
*
* @param id Session identifier of the session to load
*
* @exception ClassNotFoundException if a deserialization error occurs
* @exception IOException if an input/output error occurs
* @return the loaded Session instance
*/
public Session load(String id)
throws ClassNotFoundException, IOException;
/**
* Remove the Session with the specified session identifier from
* this Store, if present. If no such Session is present, this method
* takes no action.
*
* @param id Session identifier of the Session to be removed
*
* @exception IOException if an input/output error occurs
*/
public void remove(String id) throws IOException;
/**
* Remove all Sessions from this Store.
*
* @exception IOException if an input/output error occurs
*/
public void clear() throws IOException;
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
/**
* Save the specified Session into this Store. Any previously saved
* information for the associated session identifier is replaced.
*
* @param session Session to be saved
*
* @exception IOException if an input/output error occurs
*/
public void save(Session session) throws IOException;
}

View File

@@ -0,0 +1,38 @@
/*
* 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;
/**
* PersistentManager would have been a better name but that would have clashed
* with the implementation name.
*/
public interface StoreManager extends DistributedManager {
/**
* @return the Store object which manages persistent Session
* storage for this Manager.
*/
Store getStore();
/**
* Remove this Session from the active Sessions for this Manager,
* but not from the Store. (Used by the PersistentValve)
*
* @param session Session to be removed
*/
void removeSuper(Session session);
}

View File

@@ -0,0 +1,29 @@
/*
* 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;
/**
* Callback for establishing naming association when entering the application
* scope. This corresponds to setting the context classloader.
*/
public interface ThreadBindingListener {
public void bind();
public void unbind();
}

View File

@@ -0,0 +1,50 @@
/*
* 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;
import java.security.Principal;
import org.ietf.jgss.GSSCredential;
/**
* Defines additional methods implemented by {@link Principal}s created by
* Tomcat's standard {@link Realm} implementations.
*/
public interface TomcatPrincipal extends Principal {
/**
* @return The authenticated Principal to be exposed to applications.
*/
Principal getUserPrincipal();
/**
* @return The user's delegated credentials.
*/
GSSCredential getGssCredential();
/**
* Calls logout, if necessary, on any associated JAASLoginContext. May in
* the future be extended to cover other logout requirements.
*
* @throws Exception If something goes wrong with the logout. Uses Exception
* to allow for future expansion of this method to cover
* other logout mechanisms that might throw a different
* exception to LoginContext
*
*/
void logout() throws Exception;
}

View File

@@ -0,0 +1,24 @@
/*
* 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;
import java.io.Closeable;
public interface TrackedWebResource extends Closeable {
Exception getCreatedBy();
String getName();
}

View File

@@ -0,0 +1,174 @@
/*
* 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;
import java.security.Principal;
import java.util.Iterator;
/**
* <p>Abstract representation of a user in a {@link UserDatabase}. Each user
* is optionally associated with a set of {@link Group}s through which he or
* she inherits additional security roles, and is optionally assigned a set
* of specific {@link Role}s.</p>
*
* @author Craig R. McClanahan
* @since 4.1
*/
public interface User extends Principal {
// ------------------------------------------------------------- Properties
/**
* @return the full name of this user.
*/
public String getFullName();
/**
* Set the full name of this user.
*
* @param fullName The new full name
*/
public void setFullName(String fullName);
/**
* @return the set of {@link Group}s to which this user belongs.
*/
public Iterator<Group> getGroups();
/**
* @return the logon password of this user, optionally prefixed with the
* identifier of an encoding scheme surrounded by curly braces, such as
* <code>{md5}xxxxx</code>.
*/
public String getPassword();
/**
* Set the logon password of this user, optionally prefixed with the
* identifier of an encoding scheme surrounded by curly braces, such as
* <code>{md5}xxxxx</code>.
*
* @param password The new logon password
*/
public void setPassword(String password);
/**
* @return the set of {@link Role}s assigned specifically to this user.
*/
public Iterator<Role> getRoles();
/**
* @return the {@link UserDatabase} within which this User is defined.
*/
public UserDatabase getUserDatabase();
/**
* @return the logon username of this user, which must be unique
* within the scope of a {@link UserDatabase}.
*/
public String getUsername();
/**
* Set the logon username of this user, which must be unique within
* the scope of a {@link UserDatabase}.
*
* @param username The new logon username
*/
public void setUsername(String username);
// --------------------------------------------------------- Public Methods
/**
* Add a new {@link Group} to those this user belongs to.
*
* @param group The new group
*/
public void addGroup(Group group);
/**
* Add a {@link Role} to those assigned specifically to this user.
*
* @param role The new role
*/
public void addRole(Role role);
/**
* Is this user in the specified {@link Group}?
*
* @param group The group to check
* @return <code>true</code> if the user is in the specified group
*/
public boolean isInGroup(Group group);
/**
* Is this user specifically assigned the specified {@link Role}? This
* method does <strong>NOT</strong> check for roles inherited based on
* {@link Group} membership.
*
* @param role The role to check
* @return <code>true</code> if the user has the specified role
*/
public boolean isInRole(Role role);
/**
* Remove a {@link Group} from those this user belongs to.
*
* @param group The old group
*/
public void removeGroup(Group group);
/**
* Remove all {@link Group}s from those this user belongs to.
*/
public void removeGroups();
/**
* Remove a {@link Role} from those assigned to this user.
*
* @param role The old role
*/
public void removeRole(Role role);
/**
* Remove all {@link Role}s from those assigned to this user.
*/
public void removeRoles();
}

View File

@@ -0,0 +1,167 @@
/*
* 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;
import java.util.Iterator;
/**
* Abstract representation of a database of {@link User}s and {@link Group}s
* that can be maintained by an application, along with definitions of
* corresponding {@link Role}s, and referenced by a {@link Realm} for
* authentication and access control.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public interface UserDatabase {
// ------------------------------------------------------------- Properties
/**
* @return the set of {@link Group}s defined in this user database.
*/
public Iterator<Group> getGroups();
/**
* @return the unique global identifier of this user database.
*/
public String getId();
/**
* @return the set of {@link Role}s defined in this user database.
*/
public Iterator<Role> getRoles();
/**
* @return the set of {@link User}s defined in this user database.
*/
public Iterator<User> getUsers();
// --------------------------------------------------------- Public Methods
/**
* Finalize access to this user database.
*
* @exception Exception if any exception is thrown during closing
*/
public void close() throws Exception;
/**
* Create and return a new {@link Group} defined in this user database.
*
* @param groupname The group name of the new group (must be unique)
* @param description The description of this group
* @return The new group
*/
public Group createGroup(String groupname, String description);
/**
* Create and return a new {@link Role} defined in this user database.
*
* @param rolename The role name of the new role (must be unique)
* @param description The description of this role
* @return The new role
*/
public Role createRole(String rolename, String description);
/**
* Create and return a new {@link User} defined in this user database.
*
* @param username The logon username of the new user (must be unique)
* @param password The logon password of the new user
* @param fullName The full name of the new user
* @return The new user
*/
public User createUser(String username, String password, String fullName);
/**
* @return the {@link Group} with the specified group name, if any;
* otherwise return <code>null</code>.
*
* @param groupname Name of the group to return
*/
public Group findGroup(String groupname);
/**
* @return the {@link Role} with the specified role name, if any; otherwise
* return <code>null</code>.
*
* @param rolename Name of the role to return
*/
public Role findRole(String rolename);
/**
* @return the {@link User} with the specified user name, if any; otherwise
* return <code>null</code>.
*
* @param username Name of the user to return
*/
public User findUser(String username);
/**
* Initialize access to this user database.
*
* @exception Exception if any exception is thrown during opening
*/
public void open() throws Exception;
/**
* Remove the specified {@link Group} from this user database.
*
* @param group The group to be removed
*/
public void removeGroup(Group group);
/**
* Remove the specified {@link Role} from this user database.
*
* @param role The role to be removed
*/
public void removeRole(Role role);
/**
* Remove the specified {@link User} from this user database.
*
* @param user The user to be removed
*/
public void removeUser(User user);
/**
* Save any updated information to the persistent storage location for this
* user database.
*
* @exception Exception if any exception is thrown during saving
*/
public void save() throws Exception;
}

View File

@@ -0,0 +1,122 @@
/*
* 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;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
/**
* <p>A <b>Valve</b> is a request processing component associated with a
* particular Container. A series of Valves are generally associated with
* each other into a Pipeline. The detailed contract for a Valve is included
* in the description of the <code>invoke()</code> method below.</p>
*
* <b>HISTORICAL NOTE</b>: The "Valve" name was assigned to this concept
* because a valve is what you use in a real world pipeline to control and/or
* modify flows through it.
*
* @author Craig R. McClanahan
* @author Gunnar Rjnning
* @author Peter Donald
*/
public interface Valve {
//-------------------------------------------------------------- Properties
/**
* @return the next Valve in the pipeline containing this Valve, if any.
*/
public Valve getNext();
/**
* Set the next Valve in the pipeline containing this Valve.
*
* @param valve The new next valve, or <code>null</code> if none
*/
public void setNext(Valve valve);
//---------------------------------------------------------- Public Methods
/**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
*/
public void backgroundProcess();
/**
* <p>Perform request processing as required by this Valve.</p>
*
* <p>An individual Valve <b>MAY</b> perform the following actions, in
* the specified order:</p>
* <ul>
* <li>Examine and/or modify the properties of the specified Request and
* Response.
* <li>Examine the properties of the specified Request, completely generate
* the corresponding Response, and return control to the caller.
* <li>Examine the properties of the specified Request and Response, wrap
* either or both of these objects to supplement their functionality,
* and pass them on.
* <li>If the corresponding Response was not generated (and control was not
* returned, call the next Valve in the pipeline (if there is one) by
* executing <code>getNext().invoke()</code>.
* <li>Examine, but not modify, the properties of the resulting Response
* (which was created by a subsequently invoked Valve or Container).
* </ul>
*
* <p>A Valve <b>MUST NOT</b> do any of the following things:</p>
* <ul>
* <li>Change request properties that have already been used to direct
* the flow of processing control for this request (for instance,
* trying to change the virtual host to which a Request should be
* sent from a pipeline attached to a Host or Context in the
* standard implementation).
* <li>Create a completed Response <strong>AND</strong> pass this
* Request and Response on to the next Valve in the pipeline.
* <li>Consume bytes from the input stream associated with the Request,
* unless it is completely generating the response, or wrapping the
* request before passing it on.
* <li>Modify the HTTP headers included with the Response after the
* <code>getNext().invoke()</code> method has returned.
* <li>Perform any actions on the output stream associated with the
* specified Response after the <code>getNext().invoke()</code> method has
* returned.
* </ul>
*
* @param request The servlet request to be processed
* @param response The servlet response to be created
*
* @exception IOException if an input/output error occurs, or is thrown
* by a subsequently invoked Valve, Filter, or Servlet
* @exception ServletException if a servlet error occurs, or is thrown
* by a subsequently invoked Valve, Filter, or Servlet
*/
public void invoke(Request request, Response response)
throws IOException, ServletException;
public boolean isAsyncSupported();
}

View File

@@ -0,0 +1,171 @@
/*
* 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;
import java.io.InputStream;
import java.net.URL;
import java.security.cert.Certificate;
import java.util.jar.Manifest;
/**
* Represents a file or directory within a web application. It borrows heavily
* from {@link java.io.File}.
*/
public interface WebResource {
/**
* @return {@link java.io.File#lastModified()}.
*/
long getLastModified();
/**
* @return the last modified time of this resource in the correct format for
* the HTTP Last-Modified header as specified by RFC 2616.
*/
String getLastModifiedHttp();
/**
* @return {@link java.io.File#exists()}.
*/
boolean exists();
/**
* Indicates if this resource is required for applications to correctly scan
* the file structure but that does not exist in either the main or any
* additional {@link WebResourceSet}. For example, if an external
* directory is mapped to /WEB-INF/lib in an otherwise empty web
* application, /WEB-INF will be represented as a virtual resource.
*
* @return <code>true</code> for a virtual resource
*/
boolean isVirtual();
/**
* @return {@link java.io.File#isDirectory()}.
*/
boolean isDirectory();
/**
* @return {@link java.io.File#isFile()}.
*/
boolean isFile();
/**
* @return {@link java.io.File#delete()}.
*/
boolean delete();
/**
* @return {@link java.io.File#getName()}.
*/
String getName();
/**
* @return {@link java.io.File#length()}.
*/
long getContentLength();
/**
* @return {@link java.io.File#getCanonicalPath()}.
*/
String getCanonicalPath();
/**
* @return {@link java.io.File#canRead()}.
*/
boolean canRead();
/**
* @return The path of this resource relative to the web application root. If the
* resource is a directory, the return value will end in '/'.
*/
String getWebappPath();
/**
* Return the strong ETag if available (currently not supported) else return
* the weak ETag calculated from the content length and last modified.
*
* @return The ETag for this resource
*/
String getETag();
/**
* Set the MIME type for this Resource.
*
* @param mimeType The mime type that will be associated with the resource
*/
void setMimeType(String mimeType);
/**
* @return the MIME type for this Resource.
*/
String getMimeType();
/**
* Obtain an InputStream based on the contents of this resource.
*
* @return An InputStream based on the contents of this resource or
* <code>null</code> if the resource does not exist or does not
* represent a file
*/
InputStream getInputStream();
/**
* @return the binary content of this resource or {@code null} if it is not
* available in a byte[] because, for example, it is too big.
*/
byte[] getContent();
/**
* @return The time the file was created. If not available, the result of
* {@link #getLastModified()} will be returned.
*/
long getCreation();
/**
* @return a URL to access the resource or <code>null</code> if no such URL
* is available or if the resource does not exist.
*/
URL getURL();
/**
* @return the code base for this resource that will be used when looking up the
* assigned permissions for the code base in the security policy file when
* running under a security manager.
*/
URL getCodeBase();
/**
* @return a reference to the WebResourceRoot of which this WebResource is a
* part.
*/
WebResourceRoot getWebResourceRoot();
/**
* @return the certificates that were used to sign this resource to verify
* it or @null if none.
*
* @see java.util.jar.JarEntry#getCertificates()
*/
Certificate[] getCertificates();
/**
* @return the manifest associated with this resource or @null if none.
*
* @see java.util.jar.JarFile#getManifest()
*/
Manifest getManifest();
}

View File

@@ -0,0 +1,440 @@
/*
* 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;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.Set;
/**
* Represents the complete set of resources for a web application. The resources
* for a web application comprise of multiple ResourceSets and when looking for
* a Resource, the ResourceSets are processed in the following order:
* <ol>
* <li>Pre - Resources defined by the &lt;PreResource&gt; element in the web
* application's context.xml. Resources will be searched in the order
* they were specified.</li>
* <li>Main - The main resources for the web application - i.e. the WAR or the
* directory containing the expanded WAR</li>
* <li>JARs - Resource JARs as defined by the Servlet specification. JARs will
* be searched in the order they were added to the ResourceRoot.</li>
* <li>Post - Resources defined by the &lt;PostResource&gt; element in the web
* application's context.xml. Resources will be searched in the order
* they were specified.</li>
* </ol>
* The following conventions should be noted:
* <ul>
* <li>Write operations (including delete) will only be applied to the main
* ResourceSet. The write operation will fail if the presence of a Resource
* in one of the other ResourceSets effectively makes the operation on the
* main ResourceSet a NO-OP.</li>
* <li>A file in a ResourceSet will hide a directory of the same name (and all
* the contents of that directory) in a ResourceSet that is later in the
* search order.</li>
* <li>Only the main ResourceSet may define a META-INF/context.xml since that
* file defines the Pre- and Post-Resources.</li>
* <li>As per the Servlet specification, any META-INF or WEB-INF directories in
* a resource JAR will be ignored.</li>
* <li>Pre- and Post-Resources may define WEB-INF/lib and WEB-INF/classes in
* order to make additional libraries and/or classes available to the web
* application.
* </ul>
* This mechanism replaces and extends the following features that were present
* in earlier versions:
* <ul>
* <li>Aliases - Replaced by Post-Resources with the addition of
* support for single files as well as directories
* and JARs.</li>
* <li>VirtualWebappLoader - Replaced by Pre- and Post-Resources mapped to
* WEB-INF/lib and WEB-INF/classes</li>
* <li>VirtualDirContext - Replaced by Pre- and Post-Resources</li>
* <li>External repositories - Replaced by Pre- and Post-Resources mapped to
* WEB-INF/lib and WEB-INF/classes</li>
* <li>Resource JARs - Same feature but implemented using the same
* mechanism as all the other additional
* resources.</li>
* </ul>
*/
/*
* A potential future enhancement is to allow writing to any ResourceSet,
* not just the main ResourceSet although that adds all sorts complications
* including:
* - which ResourceSet to write to
* - unexpected behaviour when deleting a resource from one ResourceSet since
* that may unmask a resource in a lower priority ResourceSet so what was a
* delete looks like a replace with the user having no idea where the 'new'
* resource came from
* - how to handle PUT when the target is read-only but it could be written to
* a higher priority ResourceSet that is read-write
*/
public interface WebResourceRoot extends Lifecycle {
/**
* Obtain the object that represents the resource at the given path. Note
* that the resource at that path may not exist. If the path does not
* exist, the WebResource returned will be associated with the main
* WebResourceSet.
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The object that represents the resource at the given path
*/
WebResource getResource(String path);
/**
* Obtain the objects that represent the resource at the given path. Note
* that the resource at that path may not exist. If the path does not
* exist, the WebResource returned will be associated with the main
* WebResourceSet. This will include all matches even if the resource would
* not normally be accessible (e.g. because it was overridden by another
* resource)
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The objects that represents the resource at the given path
*/
WebResource[] getResources(String path);
/**
* Obtain the object that represents the class loader resource at the given
* path. WEB-INF/classes is always searched prior to searching JAR files in
* WEB-INF/lib. The search order for JAR files will be consistent across
* subsequent calls to this method until the web application is reloaded. No
* guarantee is made as to what the search order for JAR files may be.
*
* @param path The path of the class loader resource of interest relative
* to the the root of class loader resources for this web
* application.
*
* @return The object that represents the class loader resource at the
* given path
*/
WebResource getClassLoaderResource(String path);
/**
* Obtain the objects that represent the class loader resource at the given
* path. Note that the resource at that path may not exist. If the path does
* not exist, the WebResource returned will be associated with the main
* WebResourceSet. This will include all matches even if the resource would
* not normally be accessible (e.g. because it was overridden by another
* resource)
*
* @param path The path for the class loader resource of interest relative
* to the root of the class loader resources for the web
* application. It must start with '/'.
*
* @return The objects that represents the class loader resources at the
* given path. There will always be at least one element although
* that element may represent a resource that is not present.
*/
WebResource[] getClassLoaderResources(String path);
/**
* Obtain the list of the names of all of the files and directories located
* in the specified directory.
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The list of resources. If path does not refer to a directory
* then a zero length array will be returned.
*/
String[] list(String path);
/**
* Obtain the Set of the web applications pathnames of all of the files and
* directories located in the specified directory. Paths representing
* directories will end with a '/' character.
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The Set of resources. If path does not refer to a directory
* then null will be returned.
*/
Set<String> listWebAppPaths(String path);
/**
* Obtain the list of all of the WebResources in the specified directory.
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The list of resources. If path does not refer to a directory
* then a zero length array will be returned.
*/
WebResource[] listResources(String path);
/**
* Create a new directory at the given path.
*
* @param path The path for the new resource to create relative to the root
* of the web application. It must start with '/'.
*
* @return <code>true</code> if the directory was created, otherwise
* <code>false</code>
*/
boolean mkdir(String path);
/**
* Create a new resource at the requested path using the provided
* InputStream.
*
* @param path The path to be used for the new Resource. It is relative
* to the root of the web application and must start with
* '/'.
* @param is The InputStream that will provide the content for the
* new Resource.
* @param overwrite If <code>true</code> and the resource already exists it
* will be overwritten. If <code>false</code> and the
* resource already exists the write will fail.
*
* @return <code>true</code> if and only if the new Resource is written
*/
boolean write(String path, InputStream is, boolean overwrite);
/**
* Creates a new {@link WebResourceSet} for this {@link WebResourceRoot}
* based on the provided parameters.
*
* @param type The type of {@link WebResourceSet} to create
* @param webAppMount The path within the web application that the
* resources should be published at. It must start
* with '/'.
* @param url The URL of the resource (must locate a JAR, file or
* directory)
* @param internalPath The path within the resource where the content is to
* be found. It must start with '/'.
*/
void createWebResourceSet(ResourceSetType type, String webAppMount, URL url,
String internalPath);
/**
* Creates a new {@link WebResourceSet} for this {@link WebResourceRoot}
* based on the provided parameters.
*
* @param type The type of {@link WebResourceSet} to create
* @param webAppMount The path within the web application that the
* resources should be published at. It must start
* with '/'.
* @param base The location of the resources
* @param archivePath The path within the resource to the archive where
* the content is to be found. If there is no
* archive then this should be <code>null</code>.
* @param internalPath The path within the archive (or the resource if the
* archivePath is <code>null</code> where the
* content is to be found. It must start with '/'.
*/
void createWebResourceSet(ResourceSetType type, String webAppMount,
String base, String archivePath, String internalPath);
/**
* Adds the provided WebResourceSet to this web application as a 'Pre'
* resource.
*
* @param webResourceSet the resource set to use
*/
void addPreResources(WebResourceSet webResourceSet);
/**
* @return the list of WebResourceSet configured to this web application
* as a 'Pre' resource.
*/
WebResourceSet[] getPreResources();
/**
* Adds the provided WebResourceSet to this web application as a 'Jar'
* resource.
*
* @param webResourceSet the resource set to use
*/
void addJarResources(WebResourceSet webResourceSet);
/**
* @return the list of WebResourceSet configured to this web application
* as a 'Jar' resource.
*/
WebResourceSet[] getJarResources();
/**
* Adds the provided WebResourceSet to this web application as a 'Post'
* resource.
*
* @param webResourceSet the resource set to use
*/
void addPostResources(WebResourceSet webResourceSet);
/**
* @return the list of WebResourceSet configured to this web application
* as a 'Post' resource.
*/
WebResourceSet[] getPostResources();
/**
* @return the web application this WebResourceRoot is associated with.
*/
Context getContext();
/**
* Set the web application this WebResourceRoot is associated with.
*
* @param context the associated context
*/
void setContext(Context context);
/**
* Configure if this resources allow the use of symbolic links.
*
* @param allowLinking <code>true</code> if symbolic links are allowed.
*/
void setAllowLinking(boolean allowLinking);
/**
* Determine if this resources allow the use of symbolic links.
*
* @return <code>true</code> if symbolic links are allowed
*/
boolean getAllowLinking();
/**
* Set whether or not caching is permitted for this web application.
*
* @param cachingAllowed <code>true</code> to enable caching, else
* <code>false</code>
*/
void setCachingAllowed(boolean cachingAllowed);
/**
* @return <code>true</code> if caching is permitted for this web application.
*/
boolean isCachingAllowed();
/**
* Set the Time-To-Live (TTL) for cache entries.
*
* @param ttl TTL in milliseconds
*/
void setCacheTtl(long ttl);
/**
* Get the Time-To-Live (TTL) for cache entries.
*
* @return TTL in milliseconds
*/
long getCacheTtl();
/**
* Set the maximum permitted size for the cache.
*
* @param cacheMaxSize Maximum cache size in kilobytes
*/
void setCacheMaxSize(long cacheMaxSize);
/**
* Get the maximum permitted size for the cache.
*
* @return Maximum cache size in kilobytes
*/
long getCacheMaxSize();
/**
* Set the maximum permitted size for a single object in the cache. Note
* that the maximum size in bytes may not exceed {@link Integer#MAX_VALUE}.
*
* @param cacheObjectMaxSize Maximum size for a single cached object in
* kilobytes
*/
void setCacheObjectMaxSize(int cacheObjectMaxSize);
/**
* Get the maximum permitted size for a single object in the cache. Note
* that the maximum size in bytes may not exceed {@link Integer#MAX_VALUE}.
*
* @return Maximum size for a single cached object in kilobytes
*/
int getCacheObjectMaxSize();
/**
* Controls whether the track locked files feature is enabled. If enabled,
* all calls to methods that return objects that lock a file and need to be
* closed to release that lock (e.g. {@link WebResource#getInputStream()}
* will perform a number of additional tasks.
* <ul>
* <li>The stack trace at the point where the method was called will be
* recorded and associated with the returned object.</li>
* <li>The returned object will be wrapped so that the point where close()
* (or equivalent) is called to release the resources can be detected.
* Tracking of the object will cease once the resources have been
* released.</li>
* <li>All remaining locked resources on web application shutdown will be
* logged and then closed.</li>
* </ul>
*
* @param trackLockedFiles {@code true} to enable it, {@code false} to
* disable it
*/
void setTrackLockedFiles(boolean trackLockedFiles);
/**
* Has the track locked files feature been enabled?
*
* @return {@code true} if it has been enabled, otherwise {@code false}
*/
boolean getTrackLockedFiles();
/**
* This method will be invoked by the context on a periodic basis and allows
* the implementation a method that executes periodic tasks, such as purging
* expired cache entries.
*/
void backgroundProcess();
/**
* Add a specified resource to track to be able to later release
* resources on stop.
* @param trackedResource the resource that will be tracked
*/
void registerTrackedResource(TrackedWebResource trackedResource);
/**
* Stop tracking specified resource, once it no longer needs to free resources.
* @param trackedResource the resource that was tracked
*/
void deregisterTrackedResource(TrackedWebResource trackedResource);
/**
* @return the set of {@link WebResourceSet#getBaseUrl()} for all
* {@link WebResourceSet}s used by this root.
*/
List<URL> getBaseUrls();
/**
* Implementations may cache some information to improve performance. This
* method triggers the clean-up of those resources.
*/
void gc();
enum ResourceSetType {
PRE,
RESOURCE_JAR,
POST,
CLASSES_JAR
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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;
import java.io.InputStream;
import java.net.URL;
import java.util.Set;
/**
* Represents a set of resources that are part of a web application. Examples
* include a directory structure, a resources JAR and a WAR file.
*/
public interface WebResourceSet extends Lifecycle {
/**
* Obtain the object that represents the resource at the given path. Note
* the resource at that path may not exist.
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The object that represents the resource at the given path
*/
WebResource getResource(String path);
/**
* Obtain the list of the names of all of the files and directories located
* in the specified directory.
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The list of resources. If path does not refer to a directory
* then a zero length array will be returned.
*/
String[] list(String path);
/**
* Obtain the Set of the web applications pathnames of all of the files and
* directories located in the specified directory. Paths representing
* directories will end with a "/" character.
*
* @param path The path for the resource of interest relative to the root
* of the web application. It must start with '/'.
*
* @return The Set of resources. If path does not refer to a directory
* then an empty set will be returned.
*/
Set<String> listWebAppPaths(String path);
/**
* Create a new directory at the given path.
*
* @param path The path for the new resource to create relative to the root
* of the web application. It must start with '/'.
*
* @return <code>true</code> if the directory was created, otherwise
* <code>false</code>
*/
boolean mkdir(String path);
/**
* Create a new resource at the requested path using the provided
* InputStream.
*
* @param path The path to be used for the new Resource. It is relative
* to the root of the web application and must start with
* '/'.
* @param is The InputStream that will provide the content for the
* new Resource.
* @param overwrite If <code>true</code> and the resource already exists it
* will be overwritten. If <code>false</code> and the
* resource already exists the write will fail.
*
* @return <code>true</code> if and only if the new Resource is written
*/
boolean write(String path, InputStream is, boolean overwrite);
void setRoot(WebResourceRoot root);
/**
* Should resources returned by this resource set only be included in any
* results when the lookup is explicitly looking for class loader resources.
* i.e. should these resources be excluded from look ups that are explicitly
* looking for static (non-class loader) resources.
*
* @return <code>true</code> if these resources should only be used for
* class loader resource lookups, otherwise <code>false</code>
*/
boolean getClassLoaderOnly();
void setClassLoaderOnly(boolean classLoaderOnly);
/**
* Should resources returned by this resource set only be included in any
* results when the lookup is explicitly looking for static (non-class
* loader) resources. i.e. should these resources be excluded from look ups
* that are explicitly looking for class loader resources.
*
* @return <code>true</code> if these resources should only be used for
* static (non-class loader) resource lookups, otherwise
* <code>false</code>
*/
boolean getStaticOnly();
void setStaticOnly(boolean staticOnly);
/**
* Obtain the base URL for this set of resources. One of the uses of this is
* to grant read permissions to the resources when running under a security
* manager.
*
* @return The base URL for this set of resources
*/
URL getBaseUrl();
/**
* Configures whether or not this set of resources is read-only.
*
* @param readOnly <code>true</code> if this set of resources should be
* configured to be read-only
*
* @throws IllegalArgumentException if an attempt is made to configure a
* {@link WebResourceSet} that is hard-coded to be read-only as
* writable
*/
void setReadOnly(boolean readOnly);
/**
* Obtains the current value of the read-only setting for this set of
* resources.
*
* @return <code>true</code> if this set of resources is configured to be
* read-only, otherwise <code>false</code>
*/
boolean isReadOnly();
/**
* Implementations may cache some information to improve performance. This
* method triggers the clean-up of those resources.
*/
void gc();
}

View File

@@ -0,0 +1,403 @@
/*
* 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;
import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
/**
* A <b>Wrapper</b> is a Container that represents an individual servlet
* definition from the deployment descriptor of the web application. It
* provides a convenient mechanism to use Interceptors that see every single
* request to the servlet represented by this definition.
* <p>
* Implementations of Wrapper are responsible for managing the servlet life
* cycle for their underlying servlet class, including calling init() and
* destroy() at appropriate times, as well as respecting the existence of
* the SingleThreadModel declaration on the servlet class itself.
* <p>
* The parent Container attached to a Wrapper will generally be an
* implementation of Context, representing the servlet context (and
* therefore the web application) within which this servlet executes.
* <p>
* Child Containers are not allowed on Wrapper implementations, so the
* <code>addChild()</code> method should throw an
* <code>IllegalArgumentException</code>.
*
* @author Craig R. McClanahan
*/
public interface Wrapper extends Container {
/**
* Container event for adding a wrapper.
*/
public static final String ADD_MAPPING_EVENT = "addMapping";
/**
* Container event for removing a wrapper.
*/
public static final String REMOVE_MAPPING_EVENT = "removeMapping";
// ------------------------------------------------------------- Properties
/**
* @return the available date/time for this servlet, in milliseconds since
* the epoch. If this date/time is in the future, any request for this
* servlet will return an SC_SERVICE_UNAVAILABLE error. If it is zero,
* the servlet is currently available. A value equal to Long.MAX_VALUE
* is considered to mean that unavailability is permanent.
*/
public long getAvailable();
/**
* Set the available date/time for this servlet, in milliseconds since the
* epoch. If this date/time is in the future, any request for this servlet
* will return an SC_SERVICE_UNAVAILABLE error. A value equal to
* Long.MAX_VALUE is considered to mean that unavailability is permanent.
*
* @param available The new available date/time
*/
public void setAvailable(long available);
/**
* @return the load-on-startup order value (negative value means
* load on first call).
*/
public int getLoadOnStartup();
/**
* Set the load-on-startup order value (negative value means
* load on first call).
*
* @param value New load-on-startup value
*/
public void setLoadOnStartup(int value);
/**
* @return the run-as identity for this servlet.
*/
public String getRunAs();
/**
* Set the run-as identity for this servlet.
*
* @param runAs New run-as identity value
*/
public void setRunAs(String runAs);
/**
* @return the fully qualified servlet class name for this servlet.
*/
public String getServletClass();
/**
* Set the fully qualified servlet class name for this servlet.
*
* @param servletClass Servlet class name
*/
public void setServletClass(String servletClass);
/**
* Gets the names of the methods supported by the underlying servlet.
*
* This is the same set of methods included in the Allow response header
* in response to an OPTIONS request method processed by the underlying
* servlet.
*
* @return Array of names of the methods supported by the underlying
* servlet
*
* @throws ServletException If the target servlet cannot be loaded
*/
public String[] getServletMethods() throws ServletException;
/**
* @return <code>true</code> if this Servlet is currently unavailable.
*/
public boolean isUnavailable();
/**
* @return the associated Servlet instance.
*/
public Servlet getServlet();
/**
* Set the associated Servlet instance
*
* @param servlet The associated Servlet
*/
public void setServlet(Servlet servlet);
// --------------------------------------------------------- Public Methods
/**
* Add a new servlet initialization parameter for this servlet.
*
* @param name Name of this initialization parameter to add
* @param value Value of this initialization parameter to add
*/
public void addInitParameter(String name, String value);
/**
* Add a mapping associated with the Wrapper.
*
* @param mapping The new wrapper mapping
*/
public void addMapping(String mapping);
/**
* Add a new security role reference record to the set of records for
* this servlet.
*
* @param name Role name used within this servlet
* @param link Role name used within the web application
*/
public void addSecurityReference(String name, String link);
/**
* Allocate an initialized instance of this Servlet that is ready to have
* its <code>service()</code> method called. If the Servlet class does
* not implement <code>SingleThreadModel</code>, the (only) initialized
* instance may be returned immediately. If the Servlet class implements
* <code>SingleThreadModel</code>, the Wrapper implementation must ensure
* that this instance is not allocated again until it is deallocated by a
* call to <code>deallocate()</code>.
*
* @exception ServletException if the Servlet init() method threw
* an exception
* @exception ServletException if a loading error occurs
* @return a new Servlet instance
*/
public Servlet allocate() throws ServletException;
/**
* Return this previously allocated servlet to the pool of available
* instances. If this servlet class does not implement SingleThreadModel,
* no action is actually required.
*
* @param servlet The servlet to be returned
*
* @exception ServletException if a deallocation error occurs
*/
public void deallocate(Servlet servlet) throws ServletException;
/**
* @return the value for the specified initialization parameter name,
* if any; otherwise return <code>null</code>.
*
* @param name Name of the requested initialization parameter
*/
public String findInitParameter(String name);
/**
* @return the names of all defined initialization parameters for this
* servlet.
*/
public String[] findInitParameters();
/**
* @return the mappings associated with this wrapper.
*/
public String[] findMappings();
/**
* @return the security role link for the specified security role
* reference name, if any; otherwise return <code>null</code>.
*
* @param name Security role reference used within this servlet
*/
public String findSecurityReference(String name);
/**
* @return the set of security role reference names associated with
* this servlet, if any; otherwise return a zero-length array.
*/
public String[] findSecurityReferences();
/**
* Increment the error count value used when monitoring.
*/
public void incrementErrorCount();
/**
* Load and initialize an instance of this Servlet, if there is not already
* at least one initialized instance. This can be used, for example, to
* load Servlets that are marked in the deployment descriptor to be loaded
* at server startup time.
*
* @exception ServletException if the Servlet init() method threw
* an exception or if some other loading problem occurs
*/
public void load() throws ServletException;
/**
* Remove the specified initialization parameter from this Servlet.
*
* @param name Name of the initialization parameter to remove
*/
public void removeInitParameter(String name);
/**
* Remove a mapping associated with the wrapper.
*
* @param mapping The pattern to remove
*/
public void removeMapping(String mapping);
/**
* Remove any security role reference for the specified role name.
*
* @param name Security role used within this servlet to be removed
*/
public void removeSecurityReference(String name);
/**
* Process an UnavailableException, marking this Servlet as unavailable
* for the specified amount of time.
*
* @param unavailable The exception that occurred, or <code>null</code>
* to mark this Servlet as permanently unavailable
*/
public void unavailable(UnavailableException unavailable);
/**
* Unload all initialized instances of this servlet, after calling the
* <code>destroy()</code> method for each instance. This can be used,
* for example, prior to shutting down the entire servlet engine, or
* prior to reloading all of the classes from the Loader associated with
* our Loader's repository.
*
* @exception ServletException if an unload error occurs
*/
public void unload() throws ServletException;
/**
* @return the multi-part configuration for the associated Servlet. If no
* multi-part configuration has been defined, then <code>null</code> will be
* returned.
*/
public MultipartConfigElement getMultipartConfigElement();
/**
* Set the multi-part configuration for the associated Servlet. To clear the
* multi-part configuration specify <code>null</code> as the new value.
*
* @param multipartConfig The configuration associated with the Servlet
*/
public void setMultipartConfigElement(
MultipartConfigElement multipartConfig);
/**
* Does the associated Servlet support async processing? Defaults to
* <code>false</code>.
*
* @return <code>true</code> if the Servlet supports async
*/
public boolean isAsyncSupported();
/**
* Set the async support for the associated Servlet.
*
* @param asyncSupport the new value
*/
public void setAsyncSupported(boolean asyncSupport);
/**
* Is the associated Servlet enabled? Defaults to <code>true</code>.
*
* @return <code>true</code> if the Servlet is enabled
*/
public boolean isEnabled();
/**
* Sets the enabled attribute for the associated servlet.
*
* @param enabled the new value
*/
public void setEnabled(boolean enabled);
/**
* This method is no longer used. All implementations should be NO-OPs.
*
* @param b Unused.
*
* @deprecated This will be removed in Tomcat 9.
*/
@Deprecated
public void setServletSecurityAnnotationScanRequired(boolean b);
/**
* This method is no longer used. All implementations should be NO-OPs.
*
* @throws ServletException Never thrown
*
* @deprecated This will be removed in Tomcat 9.
*/
@Deprecated
public void servletSecurityAnnotationScan() throws ServletException;
/**
* Is the Servlet overridable by a ServletContainerInitializer?
*
* @return <code>true</code> if the Servlet can be overridden in a ServletContainerInitializer
*/
public boolean isOverridable();
/**
* Sets the overridable attribute for this Servlet.
*
* @param overridable the new value
*/
public void setOverridable(boolean overridable);
}

View File

@@ -0,0 +1,84 @@
/*
* 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.ant;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.tools.ant.BuildException;
public abstract class AbstractCatalinaCommandTask extends AbstractCatalinaTask {
/**
* The context path of the web application we are managing.
*/
protected String path = null;
public String getPath() {
return this.path;
}
public void setPath(String path) {
this.path = path;
}
/**
* The context version of the web application we are managing.
*/
protected String version = null;
public String getVersion() {
return this.version;
}
public void setVersion(String version) {
this.version = version;
}
// --------------------------------------------------------- Public Methods
/**
* Create query string for the specified command.
*
* @param command Command to be executed
*
* @return The generated query string
*
* @exception BuildException if an error occurs
*/
public StringBuilder createQueryString(String command) throws BuildException {
StringBuilder buffer = new StringBuilder();
try {
buffer.append(command);
if (path == null) {
throw new BuildException("Must specify 'path' attribute");
} else {
buffer.append("?path=");
buffer.append(URLEncoder.encode(this.path, getCharset()));
if (this.version != null) {
buffer.append("&version=");
buffer.append(URLEncoder.encode(this.version, getCharset()));
}
}
} catch (UnsupportedEncodingException e) {
throw new BuildException("Invalid 'charset' attribute: " + getCharset());
}
return buffer;
}
}

View File

@@ -0,0 +1,341 @@
/*
* 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.ant;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import org.apache.catalina.util.IOTools;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
/**
* Abstract base class for Ant tasks that interact with the <em>Manager</em> web
* application for dynamically deploying and undeploying applications. These
* tasks require Ant 1.4 or later.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
// ----------------------------------------------------- Instance Variables
/**
* manager webapp's encoding.
*/
private static final String CHARSET = "utf-8";
// ------------------------------------------------------------- Properties
/**
* The charset used during URL encoding.
*/
protected String charset = "ISO-8859-1";
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
/**
* The login password for the <code>Manager</code> application.
*/
protected String password = null;
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
/**
* The URL of the <code>Manager</code> application to be used.
*/
protected String url = "http://localhost:8080/manager/text";
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
/**
* The login username for the <code>Manager</code> application.
*/
protected String username = null;
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* If set to true - ignore the constraint of the first line of the response
* message that must be "OK -".
* <p>
* When this attribute is set to {@code false} (the default), the first line
* of server response is expected to start with "OK -". If it does not then
* the task is considered as failed and the first line is treated as an
* error message.
* <p>
* When this attribute is set to {@code true}, the first line of the
* response is treated like any other, regardless of its text.
*/
protected boolean ignoreResponseConstraint = false;
public boolean isIgnoreResponseConstraint() {
return ignoreResponseConstraint;
}
public void setIgnoreResponseConstraint(boolean ignoreResponseConstraint) {
this.ignoreResponseConstraint = ignoreResponseConstraint;
}
// --------------------------------------------------------- Public Methods
/**
* Execute the specified command. This logic only performs the common
* attribute validation required by all subclasses; it does not perform any
* functional logic directly.
*
* @exception BuildException if a validation error occurs
*/
@Override
public void execute() throws BuildException {
if ((username == null) || (password == null) || (url == null)) {
throw new BuildException("Must specify all of 'username', 'password', and 'url'");
}
}
/**
* Execute the specified command, based on the configured properties.
*
* @param command Command to be executed
*
* @exception BuildException if an error occurs
*/
public void execute(String command) throws BuildException {
execute(command, null, null, -1);
}
/**
* Execute the specified command, based on the configured properties. The
* input stream will be closed upon completion of this task, whether it was
* executed successfully or not.
*
* @param command Command to be executed
* @param istream InputStream to include in an HTTP PUT, if any
* @param contentType Content type to specify for the input, if any
* @param contentLength Content length to specify for the input, if any
*
* @exception BuildException if an error occurs
*/
public void execute(String command, InputStream istream, String contentType, long contentLength)
throws BuildException {
URLConnection conn = null;
InputStreamReader reader = null;
try {
// Set up authorization with our credentials
Authenticator.setDefault(new TaskAuthenticator(username, password));
// Create a connection for this command
conn = (new URL(url + command)).openConnection();
HttpURLConnection hconn = (HttpURLConnection) conn;
// Set up standard connection characteristics
hconn.setAllowUserInteraction(false);
hconn.setDoInput(true);
hconn.setUseCaches(false);
if (istream != null) {
preAuthenticate();
hconn.setDoOutput(true);
hconn.setRequestMethod("PUT");
if (contentType != null) {
hconn.setRequestProperty("Content-Type", contentType);
}
if (contentLength >= 0) {
hconn.setRequestProperty("Content-Length", "" + contentLength);
hconn.setFixedLengthStreamingMode(contentLength);
}
} else {
hconn.setDoOutput(false);
hconn.setRequestMethod("GET");
}
hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0");
// Establish the connection with the server
hconn.connect();
// Send the request data (if any)
if (istream != null) {
try (OutputStream ostream = hconn.getOutputStream()) {
IOTools.flow(istream, ostream);
} finally {
try {
istream.close();
} catch (Exception e) {
}
}
}
// Process the response message
reader = new InputStreamReader(hconn.getInputStream(), CHARSET);
StringBuilder buff = new StringBuilder();
String error = null;
int msgPriority = Project.MSG_INFO;
boolean first = true;
while (true) {
int ch = reader.read();
if (ch < 0) {
break;
} else if ((ch == '\r') || (ch == '\n')) {
// in Win \r\n would cause handleOutput() to be called
// twice, the second time with an empty string,
// producing blank lines
if (buff.length() > 0) {
String line = buff.toString();
buff.setLength(0);
if (!ignoreResponseConstraint && first) {
if (!line.startsWith("OK -")) {
error = line;
msgPriority = Project.MSG_ERR;
}
first = false;
}
handleOutput(line, msgPriority);
}
} else {
buff.append((char) ch);
}
}
if (buff.length() > 0) {
handleOutput(buff.toString(), msgPriority);
}
if (error != null && isFailOnError()) {
// exception should be thrown only if failOnError == true
// or error line will be logged twice
throw new BuildException(error);
}
} catch (Exception e) {
if (isFailOnError()) {
throw new BuildException(e);
} else {
handleErrorOutput(e.getMessage());
}
} finally {
closeRedirector();
if (reader != null) {
try {
reader.close();
} catch (IOException ioe) {
// Ignore
}
reader = null;
}
if (istream != null) {
try {
istream.close();
} catch (IOException ioe) {
// Ignore
}
}
}
}
/*
* This is a hack.
* We need to use streaming to avoid OOME on large uploads.
* We'd like to use Authenticator.setDefault() for authentication as the JRE
* then provides the DIGEST client implementation.
* However, the above two are not compatible. When the request is made, the
* resulting 401 triggers an exception because, when using streams, the
* InputStream is no longer available to send with the repeated request that
* now includes the appropriate Authorization header.
* The hack is to make a simple OPTIONS request- i.e. without a request
* body.
* This triggers authentication and the requirement to authenticate for this
* host is cached and used to provide an appropriate Authorization when the
* next request is made (that includes a request body).
*/
private void preAuthenticate() throws IOException {
URLConnection conn = null;
// Create a connection for this command
conn = (new URL(url)).openConnection();
HttpURLConnection hconn = (HttpURLConnection) conn;
// Set up standard connection characteristics
hconn.setAllowUserInteraction(false);
hconn.setDoInput(true);
hconn.setUseCaches(false);
hconn.setDoOutput(false);
hconn.setRequestMethod("OPTIONS");
hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0");
// Establish the connection with the server
hconn.connect();
// Swallow response message
IOTools.flow(hconn.getInputStream(), null);
}
private static class TaskAuthenticator extends Authenticator {
private final String user;
private final String password;
private TaskAuthenticator(String user, String password) {
this.user = user;
this.password = password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password.toCharArray());
}
}
}

View File

@@ -0,0 +1,373 @@
/*
* 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.ant;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Redirector;
import org.apache.tools.ant.types.RedirectorElement;
/**
* Abstract base class to add output redirection support for Catalina Ant tasks.
* These tasks require Ant 1.5 or later.
* <br>
* <strong>WARNING:</strong> due to depends chain, Ant could call a Task more
* than once and this can affect the output redirection when configured. If you
* are collecting the output in a property, it will collect the output of only
* the first run, since Ant properties are immutable and once created they
* cannot be changed. <br>
* If you are collecting output in a file the file will be overwritten with the
* output of the last run, unless you set append="true", in which case each run
* will append it's output to the file.
*
*
* @author Gabriele Garuglieri
* @since 5.5
*/
public abstract class BaseRedirectorHelperTask extends Task {
/** Redirector helper */
protected final Redirector redirector = new Redirector(this);
/** Redirector element for this task */
protected RedirectorElement redirectorElement = null;
/** The stream for info output */
protected OutputStream redirectOutStream = null;
/** The stream for error output */
protected OutputStream redirectErrStream = null;
/** The print stream for info output */
PrintStream redirectOutPrintStream = null;
/** The print stream for error output */
PrintStream redirectErrPrintStream = null;
/**
* Whether to fail (with a BuildException) if ManagerServlet returns an
* error. The default behavior is to do so. <b> This flag does not control
* parameters checking. If the task is called with wrong or invalid
* parameters, it will throw BuildException independently from the setting
* of this flag. </b>
*/
protected boolean failOnError = true;
/**
* <code>true</code> true when output redirection is requested for this task.
* Default is to log on Ant log.
*/
protected boolean redirectOutput = false;
/**
* will be set to <code>true</code> when the configuration of the Redirector
* is complete.
*/
protected boolean redirectorConfigured = false;
/**
* Flag which indicates that, if redirected, output should also be always
* sent to the log. Default is that output is sent only to redirected
* streams.
*/
protected boolean alwaysLog = false;
/**
* Whether to fail (with a BuildException) if ManagerServlet returns an
* error. The default behavior is to do so.
*
* @param fail The new value of failonerror
*/
public void setFailonerror(boolean fail) {
failOnError = fail;
}
/**
* Returns the value of the failOnError property.
*
* @return <code>true</code> if the task should will if an error occurs,
* otherwise <code>false</code>
*/
public boolean isFailOnError() {
return failOnError;
}
/**
* File the output of the task is redirected to.
*
* @param out name of the output file
*/
public void setOutput(File out) {
redirector.setOutput(out);
redirectOutput = true;
}
/**
* File the error output of the task is redirected to.
*
* @param error name of the error file
*
*/
public void setError(File error) {
redirector.setError(error);
redirectOutput = true;
}
/**
* Controls whether error output is logged. This is only useful when output
* is being redirected and error output is desired in the Ant log
*
* @param logError if true the standard error is sent to the Ant log system
* and not sent to output stream.
*/
public void setLogError(boolean logError) {
redirector.setLogError(logError);
redirectOutput = true;
}
/**
* Property name whose value should be set to the output of the task.
*
* @param outputProperty property name
*
*/
public void setOutputproperty(String outputProperty) {
redirector.setOutputProperty(outputProperty);
redirectOutput = true;
}
/**
* Property name whose value should be set to the error of the task.
*
* @param errorProperty property name
*
*/
public void setErrorProperty(String errorProperty) {
redirector.setErrorProperty(errorProperty);
redirectOutput = true;
}
/**
* If true, append output to existing file.
*
* @param append if true, append output to existing file
*
*/
public void setAppend(boolean append) {
redirector.setAppend(append);
redirectOutput = true;
}
/**
* If true, (error and non-error) output will be redirected as specified
* while being sent to Ant's logging mechanism as if no redirection had
* taken place. Defaults to false.
* <br>
* Actually handled internally, with Ant 1.6.3 it will be handled by the
* <code>Redirector</code> itself.
*
* @param alwaysLog <code>boolean</code>
*/
public void setAlwaysLog(boolean alwaysLog) {
this.alwaysLog = alwaysLog;
redirectOutput = true;
}
/**
* Whether output and error files should be created even when empty.
* Defaults to true.
*
* @param createEmptyFiles <CODE>boolean</CODE>.
*/
public void setCreateEmptyFiles(boolean createEmptyFiles) {
redirector.setCreateEmptyFiles(createEmptyFiles);
redirectOutput = true;
}
/**
* Add a <CODE>RedirectorElement</CODE> to this task.
*
* @param redirectorElement <CODE>RedirectorElement</CODE>.
*/
public void addConfiguredRedirector(RedirectorElement redirectorElement) {
if (this.redirectorElement != null) {
throw new BuildException("Cannot have > 1 nested <redirector>s");
} else {
this.redirectorElement = redirectorElement;
}
}
/**
* Set up properties on the Redirector from RedirectorElement if present.
*/
private void configureRedirector() {
if (redirectorElement != null) {
redirectorElement.configure(redirector);
redirectOutput = true;
}
/*
* Due to depends chain, Ant could call the Task more than once, this is
* to prevent that we attempt to configure uselessly more than once the
* Redirector.
*/
redirectorConfigured = true;
}
/**
* Set up properties on the Redirector and create output streams.
*/
protected void openRedirector() {
if (!redirectorConfigured) {
configureRedirector();
}
if (redirectOutput) {
redirector.createStreams();
redirectOutStream = redirector.getOutputStream();
redirectOutPrintStream = new PrintStream(redirectOutStream);
redirectErrStream = redirector.getErrorStream();
redirectErrPrintStream = new PrintStream(redirectErrStream);
}
}
/**
* Ask redirector to close all the streams. It is necessary to call this
* method before leaving the Task to have the Streams flush their contents.
* If you are collecting output in a property, it will be created only if
* this method is called, otherwise you'll find it unset.
*/
protected void closeRedirector() {
try {
if (redirectOutput && redirectOutPrintStream != null) {
redirector.complete();
}
} catch (IOException ioe) {
log("Error closing redirector: " + ioe.getMessage(), Project.MSG_ERR);
}
/*
* Due to depends chain, Ant could call the Task more than once, this is
* to prevent that we attempt to reuse the previously closed Streams.
*/
redirectOutStream = null;
redirectOutPrintStream = null;
redirectErrStream = null;
redirectErrPrintStream = null;
}
/**
* Handles output with the INFO priority.
*
* @param output The output to log. Should not be <code>null</code>.
*/
@Override
protected void handleOutput(String output) {
if (redirectOutput) {
if (redirectOutPrintStream == null) {
openRedirector();
}
redirectOutPrintStream.println(output);
if (alwaysLog) {
log(output, Project.MSG_INFO);
}
} else {
log(output, Project.MSG_INFO);
}
}
/**
* Handles output with the INFO priority and flushes the stream.
*
* @param output The output to log. Should not be <code>null</code>.
*
*/
@Override
protected void handleFlush(String output) {
handleOutput(output);
redirectOutPrintStream.flush();
}
/**
* Handles error output with the ERR priority.
*
* @param output The error output to log. Should not be <code>null</code>.
*/
@Override
protected void handleErrorOutput(String output) {
if (redirectOutput) {
if (redirectErrPrintStream == null) {
openRedirector();
}
redirectErrPrintStream.println(output);
if (alwaysLog) {
log(output, Project.MSG_ERR);
}
} else {
log(output, Project.MSG_ERR);
}
}
/**
* Handles error output with the ERR priority and flushes the stream.
*
* @param output The error output to log. Should not be <code>null</code>.
*
*/
@Override
protected void handleErrorFlush(String output) {
handleErrorOutput(output);
redirectErrPrintStream.flush();
}
/**
* Handles output with ERR priority to error stream and all other priorities
* to output stream.
*
* @param output The output to log. Should not be <code>null</code>.
* @param priority The priority level that should be used
*/
protected void handleOutput(String output, int priority) {
if (priority == Project.MSG_ERR) {
handleErrorOutput(output);
} else {
handleOutput(output);
}
}
}

View File

@@ -0,0 +1,191 @@
/*
* 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.ant;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.regex.Pattern;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/deploy</code> command, supported by the
* Tomcat manager application.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public class DeployTask extends AbstractCatalinaCommandTask {
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("\\w{3,5}\\:");
/**
* URL of the context configuration file for this application, if any.
*/
protected String config = null;
public String getConfig() {
return this.config;
}
public void setConfig(String config) {
this.config = config;
}
/**
* URL of the server local web application archive (WAR) file to be
* deployed.
*/
protected String localWar = null;
public String getLocalWar() {
return this.localWar;
}
public void setLocalWar(String localWar) {
this.localWar = localWar;
}
/**
* Tag to associate with this to be deployed webapp.
*/
protected String tag = null;
public String getTag() {
return this.tag;
}
public void setTag(String tag) {
this.tag = tag;
}
/**
* Update existing webapps.
*/
protected boolean update = false;
public boolean getUpdate() {
return this.update;
}
public void setUpdate(boolean update) {
this.update = update;
}
/**
* URL of the web application archive (WAR) file to be deployed.
*/
protected String war = null;
public String getWar() {
return this.war;
}
public void setWar(String war) {
this.war = war;
}
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
if (path == null) {
throw new BuildException("Must specify 'path' attribute");
}
if ((war == null) && (localWar == null) && (config == null) && (tag == null)) {
throw new BuildException(
"Must specify either 'war', 'localWar', 'config', or 'tag' attribute");
}
// Building an input stream on the WAR to upload, if any
BufferedInputStream stream = null;
String contentType = null;
long contentLength = -1;
if (war != null) {
if (PROTOCOL_PATTERN.matcher(war).lookingAt()) {
try {
URL url = new URL(war);
URLConnection conn = url.openConnection();
contentLength = conn.getContentLengthLong();
stream = new BufferedInputStream(conn.getInputStream(), 1024);
} catch (IOException e) {
throw new BuildException(e);
}
} else {
FileInputStream fsInput = null;
try {
fsInput = new FileInputStream(war);
contentLength = fsInput.getChannel().size();
stream = new BufferedInputStream(fsInput, 1024);
} catch (IOException e) {
if (fsInput != null) {
try {
fsInput.close();
} catch (IOException ioe) {
// Ignore
}
}
throw new BuildException(e);
}
}
contentType = "application/octet-stream";
}
// Building URL
StringBuilder sb = createQueryString("/deploy");
try {
if ((war == null) && (config != null)) {
sb.append("&config=");
sb.append(URLEncoder.encode(config, getCharset()));
}
if ((war == null) && (localWar != null)) {
sb.append("&war=");
sb.append(URLEncoder.encode(localWar, getCharset()));
}
if (update) {
sb.append("&update=true");
}
if (tag != null) {
sb.append("&tag=");
sb.append(URLEncoder.encode(tag, getCharset()));
}
execute(sb.toString(), stream, contentType, contentLength);
} catch (UnsupportedEncodingException e) {
throw new BuildException("Invalid 'charset' attribute: " + getCharset());
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ioe) {
// Ignore
}
}
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/findleaks</code> command, supported by
* the Tomcat manager application.
*/
public class FindLeaksTask extends AbstractCatalinaTask {
private boolean statusLine = true;
/**
* Sets the statusLine parameter that controls if the response includes a
* status line or not.
*
* @param statusLine <code>true</code> if the status line should be included
*/
public void setStatusLine(boolean statusLine) {
this.statusLine = statusLine;
}
/**
* Returns the statusLine parameter that controls if the response includes a
* status line or not.
*
* @return <code>true</code> if the status line should be included,
* otherwise <code>false</code>
*/
public boolean getStatusLine() {
return statusLine;
}
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute("/findleaks?statusLine=" + Boolean.toString(statusLine));
}
}

View File

@@ -0,0 +1,416 @@
/*
* 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.ant;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/status</code> command, supported by the
* mod_jk status (1.2.9) application.
*
* @author Peter Rossbach
* @since 5.5.9
*/
public class JKStatusUpdateTask extends AbstractCatalinaTask {
private String worker = "lb";
private String workerType = "lb";
private int internalid = 0;
private Integer lbRetries;
private Integer lbRecovertime;
private Boolean lbStickySession = Boolean.TRUE;
private Boolean lbForceSession = Boolean.FALSE;
private Integer workerLoadFactor;
private String workerRedirect;
private String workerClusterDomain;
private Boolean workerDisabled = Boolean.FALSE;
private Boolean workerStopped = Boolean.FALSE;
private boolean isLBMode = true;
private String workerLb;
/**
*
*/
public JKStatusUpdateTask() {
super();
setUrl("http://localhost/status");
}
/**
* @return Returns the internalid.
*/
public int getInternalid() {
return internalid;
}
/**
* @param internalid
* The internalid to set.
*/
public void setInternalid(int internalid) {
this.internalid = internalid;
}
/**
* @return Returns the lbForceSession.
*/
public Boolean getLbForceSession() {
return lbForceSession;
}
/**
* @param lbForceSession
* The lbForceSession to set.
*/
public void setLbForceSession(Boolean lbForceSession) {
this.lbForceSession = lbForceSession;
}
/**
* @return Returns the lbRecovertime.
*/
public Integer getLbRecovertime() {
return lbRecovertime;
}
/**
* @param lbRecovertime
* The lbRecovertime to set.
*/
public void setLbRecovertime(Integer lbRecovertime) {
this.lbRecovertime = lbRecovertime;
}
/**
* @return Returns the lbRetries.
*/
public Integer getLbRetries() {
return lbRetries;
}
/**
* @param lbRetries
* The lbRetries to set.
*/
public void setLbRetries(Integer lbRetries) {
this.lbRetries = lbRetries;
}
/**
* @return Returns the lbStickySession.
*/
public Boolean getLbStickySession() {
return lbStickySession;
}
/**
* @param lbStickySession
* The lbStickySession to set.
*/
public void setLbStickySession(Boolean lbStickySession) {
this.lbStickySession = lbStickySession;
}
/**
* @return Returns the worker.
*/
public String getWorker() {
return worker;
}
/**
* @param worker
* The worker to set.
*/
public void setWorker(String worker) {
this.worker = worker;
}
/**
* @return Returns the workerType.
*/
public String getWorkerType() {
return workerType;
}
/**
* @param workerType
* The workerType to set.
*/
public void setWorkerType(String workerType) {
this.workerType = workerType;
}
/**
* @return Returns the workerLb.
*/
public String getWorkerLb() {
return workerLb;
}
/**
* @param workerLb
* The workerLb to set.
*/
public void setWorkerLb(String workerLb) {
this.workerLb = workerLb;
}
/**
* @return Returns the workerClusterDomain.
*/
public String getWorkerClusterDomain() {
return workerClusterDomain;
}
/**
* @param workerClusterDomain
* The workerClusterDomain to set.
*/
public void setWorkerClusterDomain(String workerClusterDomain) {
this.workerClusterDomain = workerClusterDomain;
}
/**
* @return Returns the workerDisabled.
*/
public Boolean getWorkerDisabled() {
return workerDisabled;
}
/**
* @param workerDisabled
* The workerDisabled to set.
*/
public void setWorkerDisabled(Boolean workerDisabled) {
this.workerDisabled = workerDisabled;
}
/**
* @return Returns the workerStopped.
*/
public Boolean getWorkerStopped() {
return workerStopped;
}
/**
* @param workerStopped The workerStopped to set.
*/
public void setWorkerStopped(Boolean workerStopped) {
this.workerStopped = workerStopped;
}
/**
* @return Returns the workerLoadFactor.
*/
public Integer getWorkerLoadFactor() {
return workerLoadFactor;
}
/**
* @param workerLoadFactor
* The workerLoadFactor to set.
*/
public void setWorkerLoadFactor(Integer workerLoadFactor) {
this.workerLoadFactor = workerLoadFactor;
}
/**
* @return Returns the workerRedirect.
*/
public String getWorkerRedirect() {
return workerRedirect;
}
/**
* @param workerRedirect
* The workerRedirect to set.
*/
public void setWorkerRedirect(String workerRedirect) {
this.workerRedirect = workerRedirect;
}
/**
* Execute the requested operation.
*
* @exception BuildException
* if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
checkParameter();
StringBuilder sb = createLink();
execute(sb.toString(), null, null, -1);
}
/**
* Create JkStatus link
* <ul>
* <li><b>load balance example:
* </b>http://localhost/status?cmd=update&mime=txt&w=lb&lf=false&ls=true</li>
* <li><b>worker example:
* </b>http://localhost/status?cmd=update&mime=txt&w=node1&l=lb&wf=1&wd=false&ws=false
* </li>
* </ul>
*
* @return create jkstatus link
*/
private StringBuilder createLink() {
// Building URL
StringBuilder sb = new StringBuilder();
try {
sb.append("?cmd=update&mime=txt");
sb.append("&w=");
sb.append(URLEncoder.encode(worker, getCharset()));
if (isLBMode) {
//http://localhost/status?cmd=update&mime=txt&w=lb&lf=false&ls=true
if ((lbRetries != null)) { // > 0
sb.append("&lr=");
sb.append(lbRetries);
}
if ((lbRecovertime != null)) { // > 59
sb.append("&lt=");
sb.append(lbRecovertime);
}
if ((lbStickySession != null)) {
sb.append("&ls=");
sb.append(lbStickySession);
}
if ((lbForceSession != null)) {
sb.append("&lf=");
sb.append(lbForceSession);
}
} else {
//http://localhost/status?cmd=update&mime=txt&w=node1&l=lb&wf=1&wd=false&ws=false
if ((workerLb != null)) { // must be configured
sb.append("&l=");
sb.append(URLEncoder.encode(workerLb, getCharset()));
}
if ((workerLoadFactor != null)) { // >= 1
sb.append("&wf=");
sb.append(workerLoadFactor);
}
if ((workerDisabled != null)) {
sb.append("&wd=");
sb.append(workerDisabled);
}
if ((workerStopped != null)) {
sb.append("&ws=");
sb.append(workerStopped);
}
if ((workerRedirect != null)) { // other worker conrecte lb's
sb.append("&wr=");
}
if ((workerClusterDomain != null)) {
sb.append("&wc=");
sb.append(URLEncoder.encode(workerClusterDomain,
getCharset()));
}
}
} catch (UnsupportedEncodingException e) {
throw new BuildException("Invalid 'charset' attribute: "
+ getCharset());
}
return sb;
}
/**
* check correct lb and worker parameter
*/
protected void checkParameter() {
if (worker == null) {
throw new BuildException("Must specify 'worker' attribute");
}
if (workerType == null) {
throw new BuildException("Must specify 'workerType' attribute");
}
if ("lb".equals(workerType)) {
if (lbRecovertime == null && lbRetries == null) {
throw new BuildException(
"Must specify at a lb worker either 'lbRecovertime' or"
+ "'lbRetries' attribute");
}
if (lbStickySession == null || lbForceSession == null) {
throw new BuildException("Must specify at a lb worker either"
+ "'lbStickySession' and 'lbForceSession' attribute");
}
if (null != lbRecovertime && 60 < lbRecovertime.intValue()) {
throw new BuildException(
"The 'lbRecovertime' must be greater than 59");
}
if (null != lbRetries && 1 < lbRetries.intValue()) {
throw new BuildException(
"The 'lbRetries' must be greater than 1");
}
isLBMode = true;
} else if ("worker".equals(workerType)) {
if (workerDisabled == null) {
throw new BuildException(
"Must specify at a node worker 'workerDisabled' attribute");
}
if (workerStopped == null) {
throw new BuildException(
"Must specify at a node worker 'workerStopped' attribute");
}
if (workerLoadFactor == null ) {
throw new BuildException(
"Must specify at a node worker 'workerLoadFactor' attribute");
}
if (workerClusterDomain == null) {
throw new BuildException(
"Must specify at a node worker 'workerClusterDomain' attribute");
}
if (workerRedirect == null) {
throw new BuildException(
"Must specify at a node worker 'workerRedirect' attribute");
}
if (workerLb == null) {
throw new BuildException("Must specify 'workerLb' attribute");
}
if (workerLoadFactor.intValue() < 1) {
throw new BuildException(
"The 'workerLoadFactor' must be greater or equal 1");
}
isLBMode = false;
} else {
throw new BuildException(
"Only 'lb' and 'worker' supported as workerType attribute");
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* 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.ant;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the JMX Get command (<code>/jmxproxy/?get</code>)
* supported by the Tomcat manager application.
*
* @author Peter Rossbach
*/
public class JMXGetTask extends AbstractCatalinaTask {
// Properties
/**
* The full bean name
*/
protected String bean = null;
/**
* The attribute you wish to alter
*/
protected String attribute = null;
// Public Methods
/**
* Get method for the bean name
* @return Bean name
*/
public String getBean () {
return this.bean;
}
/**
* Set method for the bean name
* @param bean Bean name
*/
public void setBean (String bean) {
this.bean = bean;
}
/**
* Get method for the attribute name
* @return Attribute name
*/
public String getAttribute () {
return this.attribute;
}
/**
* Set method for the attribute name
* @param attribute Attribute name
*/
public void setAttribute (String attribute) {
this.attribute = attribute;
}
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
if (bean == null || attribute == null) {
throw new BuildException
("Must specify 'bean' and 'attribute' attributes");
}
log("Getting attribute " + attribute +
" in bean " + bean );
try {
execute("/jmxproxy/?get=" + URLEncoder.encode(bean, getCharset())
+ "&att=" + URLEncoder.encode(attribute, getCharset()));
} catch (UnsupportedEncodingException e) {
throw new BuildException
("Invalid 'charset' attribute: " + getCharset());
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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.ant;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the JMX Query command
* (<code>/jmxproxy/?qry</code>) supported by the Tomcat manager application.
*
* @author Vivek Chopra
*/
public class JMXQueryTask extends AbstractCatalinaTask {
// Properties
/**
* The JMX query string
* @see #setQuery(String)
*/
protected String query = null;
// Public Methods
/**
* Get method for the JMX query string
* @return Query string
*/
public String getQuery () {
return this.query;
}
/**
* Set method for the JMX query string.
* <p>Examples of query format:</p>
* <UL>
* <LI>*:*</LI>
* <LI>*:type=RequestProcessor,*</LI>
* <LI>*:j2eeType=Servlet,*</LI>
* <LI>Catalina:type=Environment,resourcetype=Global,name=simpleValue</LI>
* </UL>
* @param query JMX Query string
*/
public void setQuery (String query) {
this.query = query;
}
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
String queryString;
if (query == null) {
queryString = "";
} else {
try {
queryString = "?qry=" + URLEncoder.encode(query, getCharset());
} catch (UnsupportedEncodingException e) {
throw new BuildException
("Invalid 'charset' attribute: " + getCharset());
}
}
log("Query string is " + queryString);
execute ("/jmxproxy/" + queryString);
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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.ant;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the JMX Set command (<code>/jmxproxy/?set</code>)
* supported by the Tomcat manager application.
*
* @author Vivek Chopra
*/
public class JMXSetTask extends AbstractCatalinaTask {
// Properties
/**
* The full bean name
*/
protected String bean = null;
/**
* The attribute you wish to alter
*/
protected String attribute = null;
/**
* The new value for the attribute
*/
protected String value = null;
// Public Methods
/**
* Get method for the bean name
* @return Bean name
*/
public String getBean () {
return this.bean;
}
/**
* Set method for the bean name
* @param bean Bean name
*/
public void setBean (String bean) {
this.bean = bean;
}
/**
* Get method for the attribute name
* @return Attribute name
*/
public String getAttribute () {
return this.attribute;
}
/**
* Set method for the attribute name
* @param attribute Attribute name
*/
public void setAttribute (String attribute) {
this.attribute = attribute;
}
/**
* Get method for the attribute value
* @return Attribute value
*/
public String getValue () {
return this.value;
}
/**
* Set method for the attribute value.
* @param value Attribute value
*/
public void setValue (String value) {
this.value = value;
}
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
if (bean == null || attribute == null || value == null) {
throw new BuildException
("Must specify 'bean', 'attribute' and 'value' attributes");
}
log("Setting attribute " + attribute +
" in bean " + bean +
" to " + value);
try {
execute("/jmxproxy/?set=" + URLEncoder.encode(bean, getCharset())
+ "&att=" + URLEncoder.encode(attribute, getCharset())
+ "&val=" + URLEncoder.encode(value, getCharset()));
} catch (UnsupportedEncodingException e) {
throw new BuildException
("Invalid 'charset' attribute: " + getCharset());
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/list</code> command, supported by the
* Tomcat manager application.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public class ListTask extends AbstractCatalinaTask {
// ------------------------------------------------------------- Properties
// --------------------------------------------------------- Public Methods
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute("/list");
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/reload</code> command, supported by the
* Tomcat manager application.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public class ReloadTask extends AbstractCatalinaCommandTask {
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute(createQueryString("/reload").toString());
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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.ant;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/resources</code> command, supported by
* the Tomcat manager application.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public class ResourcesTask extends AbstractCatalinaTask {
// ------------------------------------------------------------- Properties
/**
* The fully qualified class name of the resource type being requested
* (if any).
*/
protected String type = null;
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
// --------------------------------------------------------- Public Methods
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
if (type != null) {
try {
execute("/resources?type=" +
URLEncoder.encode(type, getCharset()));
} catch (UnsupportedEncodingException e) {
throw new BuildException
("Invalid 'charset' attribute: " + getCharset());
}
} else {
execute("/resources");
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/serverinfo</code> command
* supported by the Tomcat manager application.
*
* @author Vivek Chopra
*/
public class ServerinfoTask extends AbstractCatalinaTask {
// Public Methods
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute("/serverinfo");
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/sessions</code> command
* supported by the Tomcat manager application.
*
* @author Vivek Chopra
*/
public class SessionsTask extends AbstractCatalinaCommandTask {
protected String idle = null;
public String getIdle() {
return this.idle;
}
public void setIdle(String idle) {
this.idle = idle;
}
@Override
public StringBuilder createQueryString(String command) {
StringBuilder buffer = super.createQueryString(command);
if (path != null && idle != null) {
buffer.append("&idle=");
buffer.append(this.idle);
}
return buffer;
}
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute(createQueryString("/sessions").toString());
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/sslConnectorCiphers</code> command
* supported by the Tomcat manager application.
*
*/
public class SslConnectorCiphersTask extends AbstractCatalinaTask {
// Public Methods
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute("/sslConnectorCiphers");
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/start</code> command, supported by the
* Tomcat manager application.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public class StartTask extends AbstractCatalinaCommandTask {
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute(createQueryString("/start").toString());
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/stop</code> command, supported by the
* Tomcat manager application.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public class StopTask extends AbstractCatalinaCommandTask {
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute(createQueryString("/stop").toString());
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/threaddump</code> command
* supported by the Tomcat manager application.
*
*/
public class ThreaddumpTask extends AbstractCatalinaTask {
// Public Methods
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute("/threaddump");
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/undeploy</code> command, supported by
* the Tomcat manager application.
*
* @author Craig R. McClanahan
* @since 4.1
*/
public class UndeployTask extends AbstractCatalinaCommandTask {
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute(createQueryString("/undeploy").toString());
}
}

View File

@@ -0,0 +1,113 @@
/*
* 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.ant;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.catalina.Globals;
import org.apache.tomcat.util.descriptor.DigesterFactory;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tools.ant.BuildException;
import org.xml.sax.InputSource;
/**
* Task for validating a web application deployment descriptor, using XML
* schema validation.
*
* @author Remy Maucherat
* @since 5.0
*/
public class ValidatorTask extends BaseRedirectorHelperTask {
// ----------------------------------------------------- Instance Variables
// ------------------------------------------------------------- Properties
/**
* The path to the webapp directory.
*/
protected String path = null;
public String getPath() {
return this.path;
}
public void setPath(String path) {
this.path = path;
}
// --------------------------------------------------------- Public Methods
/**
* Execute the specified command. This logic only performs the common
* attribute validation required by all subclasses; it does not perform
* any functional logic directly.
*
* @exception BuildException if a validation error occurs
*/
@Override
public void execute() throws BuildException {
if (path == null) {
throw new BuildException("Must specify 'path'");
}
File file = new File(path, "WEB-INF/web.xml");
if (!file.canRead()) {
throw new BuildException("Cannot find web.xml");
}
// Commons-logging likes having the context classloader set
ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader
(ValidatorTask.class.getClassLoader());
// Called through trusted manager interface. If running under a
// SecurityManager assume that untrusted applications may be deployed.
Digester digester = DigesterFactory.newDigester(
true, true, null, Globals.IS_SECURITY_ENABLED);
try (InputStream stream = new BufferedInputStream(new FileInputStream(file.getCanonicalFile()))) {
InputSource is = new InputSource(file.toURI().toURL().toExternalForm());
is.setByteStream(stream);
digester.parse(is);
handleOutput("web.xml validated");
} catch (Exception e) {
if (isFailOnError()) {
throw new BuildException("Validation failure", e);
} else {
handleErrorOutput("Validation failure: " + e);
}
} finally {
Thread.currentThread().setContextClassLoader(oldCL);
closeRedirector();
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.ant;
import org.apache.tools.ant.BuildException;
/**
* Ant task that implements the <code>/vminfo</code> command
* supported by the Tomcat manager application.
*
*/
public class VminfoTask extends AbstractCatalinaTask {
// Public Methods
/**
* Execute the requested operation.
*
* @exception BuildException if an error occurs
*/
@Override
public void execute() throws BuildException {
super.execute();
execute("/vminfo");
}
}

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<antlib>
<!-- Pure Catalina tasks -->
<typedef
name="list"
classname="org.apache.catalina.ant.ListTask" />
<typedef
name="deploy"
classname="org.apache.catalina.ant.DeployTask" />
<typedef
name="start"
classname="org.apache.catalina.ant.StartTask" />
<typedef
name="reload"
classname="org.apache.catalina.ant.ReloadTask" />
<typedef
name="stop"
classname="org.apache.catalina.ant.StopTask" />
<typedef
name="undeploy"
classname="org.apache.catalina.ant.UndeployTask" />
<typedef
name="resources"
classname="org.apache.catalina.ant.ResourcesTask" />
<typedef
name="sessions"
classname="org.apache.catalina.ant.SessionsTask" />
<typedef
name="findleaks"
classname="org.apache.catalina.ant.FindLeaksTask" />
<typedef
name="vminfo"
classname="org.apache.catalina.ant.VminfoTask" />
<typedef
name="threaddump"
classname="org.apache.catalina.ant.ThreaddumpTask" />
<typedef
name="sslConnectorCiphers"
classname="org.apache.catalina.ant.SslConnectorCiphersTask" />
<!-- Jk Task -->
<typedef
name="jkupdate"
classname="org.apache.catalina.ant.JKStatusUpdateTask" />
<!-- Manager JMX -->
<typedef
name="jmxManagerSet"
classname="org.apache.catalina.ant.JMXSetTask" />
<typedef
name="jmxManagerGet"
classname="org.apache.catalina.ant.JMXGetTask" />
<typedef
name="jmxManagerQuery"
classname="org.apache.catalina.ant.JMXQueryTask" />
<!-- Other -->
<!-- These tasks are deliberately omitted here,
because they depend on other Tomcat components besides catalina-ant.jar
and thus are hard to use with antlib.
<typedef
name="validator"
classname="org.apache.catalina.ant.ValidatorTask" />
<typedef
name="jasper"
classname="org.apache.jasper.JspC" />
-->
</antlib>

View File

@@ -0,0 +1,40 @@
# 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.
# Pure catalina tasks
list=org.apache.catalina.ant.ListTask
deploy=org.apache.catalina.ant.DeployTask
start=org.apache.catalina.ant.StartTask
reload=org.apache.catalina.ant.ReloadTask
stop=org.apache.catalina.ant.StopTask
undeploy=org.apache.catalina.ant.UndeployTask
resources=org.apache.catalina.ant.ResourcesTask
sessions=org.apache.catalina.ant.SessionsTask
validator=org.apache.catalina.ant.ValidatorTask
findleaks=org.apache.catalina.ant.FindLeaksTask
vminfo=org.apache.catalina.ant.VminfoTask
threaddump=org.apache.catalina.ant.ThreaddumpTask
sslConnectorCiphers=org.apache.catalina.ant.SslConnectorCiphersTask
#Jk Task
jkupdate=org.apache.catalina.ant.JKStatusUpdateTask
# Manager JMX
jmxManagerSet=org.apache.catalina.ant.JMXSetTask
jmxManagerGet=org.apache.catalina.ant.JMXGetTask
jmxManagerQuery=org.apache.catalina.ant.JMXQueryTask
# Jasper tasks
jasper=org.apache.jasper.JspC

View File

@@ -0,0 +1,44 @@
/*
* 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.ant.jmx;
/**
*
* @author Peter Rossbach
* @since 5.5.10
*/
public class Arg {
private String type;
private String value;
public void setType( String type) {
this.type=type;
}
public void setValue( String value ) {
this.value=value;
}
public String getValue() {
return value;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,229 @@
/*
* 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.ant.jmx;
import org.apache.tools.ant.BuildException;
/**
* <b>Definition</b>:
* <pre>
* &lt;path id="catalina_ant"&gt;
* &lt;fileset dir="${catalina.home}/server/lib"&gt;
* &lt;include name="catalina-ant.jar"/&gt;
* &lt;/fileset&gt;
* &lt;/path&gt;
*
* &lt;typedef
* name="jmxCondition"
* classname="org.apache.catalina.ant.jmx.JMXAccessorCondition"
* classpathref="catalina_ant"/&gt;
* &lt;taskdef
* name="jmxOpen"
* classname="org.apache.catalina.ant.jmx.JMXAccessorTask"
* classpathref="catalina_ant"/&gt;
* </pre>
*
* <b>Usage</b>: Wait for start backup node
* <pre>
* &lt;target name="wait"&gt;
* &lt;jmxOpen
* host="${jmx.host}" port="${jmx.port}" username="${jmx.username}" password="${jmx.password}" /&gt;
* &lt;waitfor maxwait="${maxwait}" maxwaitunit="second" timeoutproperty="server.timeout" &gt;
* &lt;and&gt;
* &lt;socket server="${server.name}" port="${server.port}"/&gt;
* &lt;http url="${url}"/&gt;
* &lt;jmxCondition
* name="Catalina:type=IDataSender,host=localhost,senderAddress=192.168.111.1,senderPort=9025"
* operation="=="
* attribute="connected" value="true"
* /&gt;
* &lt;jmxCondition
* operation="&amp;lt;"
* name="Catalina:j2eeType=WebModule,name=//${tomcat.application.host}${tomcat.application.path},J2EEApplication=none,J2EEServer=none"
* attribute="startupTime" value="250"
* /&gt;
* &lt;/and&gt;
* &lt;/waitfor&gt;
* &lt;fail if="server.timeout" message="Server ${url} don't answer inside ${maxwait} sec" /&gt;
* &lt;echo message="Server ${url} alive" /&gt;
* &lt;/target&gt;
*
* </pre>
* Allowed operation between jmx attribute and reference value:
* <ul>
* <li>== equals</li>
* <li>!= not equals</li>
* <li>&gt; greater than (&amp;gt;)</li>
* <li>&gt;= greater than or equals (&amp;gt;=)</li>
* <li>&lt; lesser than (&amp;lt;)</li>
* <li>&lt;= lesser than or equals (&amp;lt;=)</li>
* </ul>
* <b>NOTE</b>: For numeric expressions the type must be set and use xml entities as operations.<br>
* As type we currently support <em>long</em> and <em>double</em>.
* @author Peter Rossbach
* @since 5.5.10
*/
public class JMXAccessorCondition extends JMXAccessorConditionBase {
// ----------------------------------------------------- Instance Variables
private String operation = "==" ;
private String type = "long" ;
private String unlessCondition;
private String ifCondition;
// ----------------------------------------------------- Properties
/**
* @return Returns the operation.
*/
public String getOperation() {
return operation;
}
/**
* @param operation The operation to set.
*/
public void setOperation(String operation) {
this.operation = operation;
}
/**
* @return Returns the type.
*/
public String getType() {
return type;
}
/**
* @param type The type to set.
*/
public void setType(String type) {
this.type = type;
}
/**
* @return Returns the ifCondition.
*/
public String getIf() {
return ifCondition;
}
/**
* Only execute if a property of the given name exists in the current project.
* @param c property name
*/
public void setIf(String c) {
ifCondition = c;
}
/**
* @return Returns the unlessCondition.
*/
public String getUnless() {
return unlessCondition;
}
/**
* Only execute if a property of the given name does not
* exist in the current project.
* @param c property name
*/
public void setUnless(String c) {
unlessCondition = c;
}
/**
* test the if condition
* @return true if there is no if condition, or the named property exists
*/
protected boolean testIfCondition() {
if (ifCondition == null || "".equals(ifCondition)) {
return true;
}
return getProject().getProperty(ifCondition) != null;
}
/**
* test the unless condition
* @return true if there is no unless condition,
* or there is a named property but it doesn't exist
*/
protected boolean testUnlessCondition() {
if (unlessCondition == null || "".equals(unlessCondition)) {
return true;
}
return getProject().getProperty(unlessCondition) == null;
}
/**
* This method evaluates the condition
* It support for operation "&gt;,&gt;=,&lt;,&lt;=" the types <code>long</code> and <code>double</code>.
* @return expression <em>jmxValue</em> <em>operation</em> <em>value</em>
*/
@Override
public boolean eval() {
String value = getValue();
if (operation == null) {
throw new BuildException("operation attribute is not set");
}
if (value == null) {
throw new BuildException("value attribute is not set");
}
if ((getName() == null || getAttribute() == null)) {
throw new BuildException(
"Must specify an MBean name and attribute for condition");
}
if (testIfCondition() && testUnlessCondition()) {
String jmxValue = accessJMXValue();
if (jmxValue != null) {
String op = getOperation();
if ("==".equals(op)) {
return jmxValue.equals(value);
} else if ("!=".equals(op)) {
return !jmxValue.equals(value);
} else {
if ("long".equals(type)) {
long jvalue = Long.parseLong(jmxValue);
long lvalue = Long.parseLong(value);
if (">".equals(op)) {
return jvalue > lvalue;
} else if (">=".equals(op)) {
return jvalue >= lvalue;
} else if ("<".equals(op)) {
return jvalue < lvalue;
} else if ("<=".equals(op)) {
return jvalue <= lvalue;
}
} else if ("double".equals(type)) {
double jvalue = Double.parseDouble(jmxValue);
double dvalue = Double.parseDouble(value);
if (">".equals(op)) {
return jvalue > dvalue;
} else if (">=".equals(op)) {
return jvalue >= dvalue;
} else if ("<".equals(op)) {
return jvalue < dvalue;
} else if ("<=".equals(op)) {
return jvalue <= dvalue;
}
}
}
}
return false;
}
return true;
}
}

View File

@@ -0,0 +1,181 @@
/*
* 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.ant.jmx;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.taskdefs.condition.Condition;
public abstract class JMXAccessorConditionBase extends ProjectComponent implements Condition {
private String url = null;
private String host = "localhost";
private String port = "8050";
private String password = null;
private String username = null;
private String name = null;
private String attribute;
private String value;
private String ref = "jmx.server" ;
/**
* @return Returns the attribute.
*/
public String getAttribute() {
return attribute;
}
/**
* @param attribute The attribute to set.
*/
public void setAttribute(String attribute) {
this.attribute = attribute;
}
/**
* @return Returns the host.
*/
public String getHost() {
return host;
}
/**
* @param host The host to set.
*/
public void setHost(String host) {
this.host = host;
}
/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @param objectName The name to set.
*/
public void setName(String objectName) {
this.name = objectName;
}
/**
* @return Returns the password.
*/
public String getPassword() {
return password;
}
/**
* @param password The password to set.
*/
public void setPassword(String password) {
this.password = password;
}
/**
* @return Returns the port.
*/
public String getPort() {
return port;
}
/**
* @param port The port to set.
*/
public void setPort(String port) {
this.port = port;
}
/**
* @return Returns the url.
*/
public String getUrl() {
return url;
}
/**
* @param url The url to set.
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return Returns the username.
*/
public String getUsername() {
return username;
}
/**
* @param username The username to set.
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return Returns the value.
*/
public String getValue() {
return value;
}
// The setter for the "value" attribute
public void setValue(String value) {
this.value = value;
}
/**
* @return Returns the ref.
*/
public String getRef() {
return ref;
}
/**
* @param refId The ref to set.
*/
public void setRef(String refId) {
this.ref = refId;
}
/**
* Get JMXConnection (default look at <em>jmx.server</em> project reference
* from jmxOpen Task).
*
* @return active JMXConnection
* @throws MalformedURLException Invalid URL for JMX server
* @throws IOException Connection error
*/
protected MBeanServerConnection getJMXConnection()
throws MalformedURLException, IOException {
return JMXAccessorTask.accessJMXConnection(
getProject(),
getUrl(), getHost(),
getPort(), getUsername(), getPassword(), ref);
}
/**
* Get value from MBeans attribute.
*
* @return The value
*/
protected String accessJMXValue() {
try {
Object result = getJMXConnection().getAttribute(
new ObjectName(name), attribute);
if(result != null)
return result.toString();
} catch (Exception e) {
// ignore access or connection open errors
}
return null;
}
}

View File

@@ -0,0 +1,179 @@
/*
* 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.ant.jmx;
import java.util.ArrayList;
import java.util.List;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import org.apache.tools.ant.BuildException;
/**
* Create new MBean at <em>JMX</em> JSR 160 MBeans Server.
* <ul>
* <li>Create Mbeans</li>
* <li>Create Mbeans with parameter</li>
* <li>Create remote Mbeans with different classloader</li>
* </ul>
* <p>
* Examples:
* <br>
* create a new Mbean at jmx.server connection
* </p>
* <pre>
* &lt;jmx:create
* ref="jmx.server"
* name="Catalina:type=MBeanFactory"
* className="org.apache.catalina.mbeans.MBeanFactory"
* classLoader="Catalina:type=ServerClassLoader,name=server"&gt;
* &lt;Arg value="org.apache.catalina.mbeans.MBeanFactory" /&gt;
* &lt;/jmxCreate/&gt;
* </pre>
* <p>
* <b>WARNING</b>Not all Tomcat MBeans can create remotely and autoregister by its parents!
* Please, use the MBeanFactory operation to generate valves and realms.
* </p>
* <p>
* First call to a remote MBeanserver save the JMXConnection a reference <em>jmx.server</em>
* </p>
* These tasks require Ant 1.6 or later interface.
*
* @author Peter Rossbach
* @since 5.5.12
*/
public class JMXAccessorCreateTask extends JMXAccessorTask {
// ----------------------------------------------------- Instance Variables
private String className;
private String classLoader;
private List<Arg> args=new ArrayList<>();
// ------------------------------------------------------------- Properties
/**
* @return Returns the classLoader.
*/
public String getClassLoader() {
return classLoader;
}
/**
* @param classLoaderName The classLoader to set.
*/
public void setClassLoader(String classLoaderName) {
this.classLoader = classLoaderName;
}
/**
* @return Returns the className.
*/
public String getClassName() {
return className;
}
/**
* @param className The className to set.
*/
public void setClassName(String className) {
this.className = className;
}
public void addArg(Arg arg ) {
args.add(arg);
}
/**
* @return Returns the args.
*/
public List<Arg> getArgs() {
return args;
}
/**
* @param args The args to set.
*/
public void setArgs(List<Arg> args) {
this.args = args;
}
// ------------------------------------------------------ protected Methods
@Override
public String jmxExecute(MBeanServerConnection jmxServerConnection)
throws Exception {
if (getName() == null) {
throw new BuildException("Must specify a 'name'");
}
if ((className == null)) {
throw new BuildException(
"Must specify a 'className' for get");
}
jmxCreate(jmxServerConnection, getName());
return null;
}
/**
* Create new MBean from ClassLoader identified by an ObjectName.
*
* @param jmxServerConnection Connection to the JMX server
* @param name MBean name
* @throws Exception Error creating MBean
*/
protected void jmxCreate(MBeanServerConnection jmxServerConnection,
String name) throws Exception {
Object argsA[] = null;
String sigA[] = null;
if (args != null) {
argsA = new Object[ args.size()];
sigA = new String[args.size()];
for( int i=0; i<args.size(); i++ ) {
Arg arg=args.get(i);
if (arg.getType() == null) {
arg.setType("java.lang.String");
sigA[i]=arg.getType();
argsA[i]=arg.getValue();
} else {
sigA[i]=arg.getType();
argsA[i]=convertStringToType(arg.getValue(),arg.getType());
}
}
}
if (classLoader != null && !"".equals(classLoader)) {
if (isEcho()) {
handleOutput("create MBean " + name + " from class "
+ className + " with classLoader " + classLoader);
}
if(args == null)
jmxServerConnection.createMBean(className, new ObjectName(name), new ObjectName(classLoader));
else
jmxServerConnection.createMBean(className, new ObjectName(name), new ObjectName(classLoader),argsA,sigA);
} else {
if (isEcho()) {
handleOutput("create MBean " + name + " from class "
+ className);
}
if(args == null)
jmxServerConnection.createMBean(className, new ObjectName(name));
else
jmxServerConnection.createMBean(className, new ObjectName(name),argsA,sigA);
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.ant.jmx;
import org.apache.tools.ant.BuildException;
/**
*
* Definition
* <pre>
* &lt;path id="catalina_ant"&gt;
* &lt;fileset dir="${catalina.home}/server/lib"&gt;
* &lt;include name="catalina-ant.jar"/&gt;
* &lt;/fileset&gt;
* &lt;/path&gt;
*
* &lt;typedef
* name="jmxEquals"
* classname="org.apache.catalina.ant.jmx.JMXAccessorEqualsCondition"
* classpathref="catalina_ant"/&gt;
* </pre>
*
* usage: Wait for start backup node
* <pre>
* &lt;target name="wait"&gt;
* &lt;waitfor maxwait="${maxwait}" maxwaitunit="second" timeoutproperty="server.timeout" &gt;
* &lt;and&gt;
* &lt;socket server="${server.name}" port="${server.port}"/&gt;
* &lt;http url="${url}"/&gt;
* &lt;jmxEquals
* host="localhost" port="9014" username="controlRole" password="tomcat"
* name="Catalina:type=IDataSender,host=localhost,senderAddress=192.168.111.1,senderPort=9025"
* attribute="connected" value="true"
* /&gt;
* &lt;/and&gt;
* &lt;/waitfor&gt;
* &lt;fail if="server.timeout" message="Server ${url} don't answer inside ${maxwait} sec" /&gt;
* &lt;echo message="Server ${url} alive" /&gt;
* &lt;/target&gt;
*
* </pre>
*
* @author Peter Rossbach
* @since 5.5.10
*/
public class JMXAccessorEqualsCondition extends JMXAccessorConditionBase {
@Override
public boolean eval() {
String value = getValue();
if (value == null) {
throw new BuildException("value attribute is not set");
}
if (getName() == null || getAttribute() == null) {
throw new BuildException(
"Must specify an MBean name and attribute for equals condition");
}
//FIXME check url or host/parameter
String jmxValue = accessJMXValue();
if (jmxValue != null) {
return jmxValue.equals(value);
}
return false;
}
}

View File

@@ -0,0 +1,120 @@
/*
* 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.ant.jmx;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import org.apache.tools.ant.BuildException;
/**
* Access <em>JMX</em> JSR 160 MBeans Server.
* <ul>
* <li>Get Mbeans attributes</li>
* <li>Show Get result as Ant console log</li>
* <li>Bind Get result as Ant properties</li>
* </ul>
* <p>
* Examples:
* <br>
* Get an Mbean IDataSender attribute nrOfRequests and create a new ant property <em>IDataSender.9025.nrOfRequests</em>
* </p>
* <pre>
* &lt;jmx:get
* ref="jmx.server"
* name="Catalina:type=IDataSender,host=localhost,senderAddress=192.168.1.2,senderPort=9025"
* attribute="nrOfRequests"
* resultproperty="IDataSender.9025.nrOfRequests"
* echo="false"&gt;
* /&gt;
* </pre>
* <p>
* First call to a remote MBeanserver save the JMXConnection a referenz <em>jmx.server</em>
* </p>
* These tasks require Ant 1.6 or later interface.
*
* @author Peter Rossbach
* @since 5.5.10
*/
public class JMXAccessorGetTask extends JMXAccessorTask {
// ----------------------------------------------------- Instance Variables
private String attribute;
// ------------------------------------------------------------- Properties
/**
* @return Returns the attribute.
*/
public String getAttribute() {
return attribute;
}
/**
* @param attribute The attribute to set.
*/
public void setAttribute(String attribute) {
this.attribute = attribute;
}
// ------------------------------------------------------ protected Methods
@Override
public String jmxExecute(MBeanServerConnection jmxServerConnection)
throws Exception {
if (getName() == null) {
throw new BuildException("Must specify a 'name'");
}
if ((attribute == null)) {
throw new BuildException(
"Must specify a 'attribute' for get");
}
return jmxGet(jmxServerConnection, getName());
}
/**
* Get property value.
*
* @param jmxServerConnection Connection to the JMX server
* @param name The MBean name
* @return The error message if any
* @throws Exception An error occurred
*/
protected String jmxGet(MBeanServerConnection jmxServerConnection, String name) throws Exception {
String error = null;
if(isEcho()) {
handleOutput("MBean " + name + " get attribute " + attribute );
}
Object result = jmxServerConnection.getAttribute(
new ObjectName(name), attribute);
if (result != null) {
echoResult(attribute,result);
createProperty(result);
} else
error = "Attribute " + attribute + " is empty";
return error;
}
}

View File

@@ -0,0 +1,184 @@
/*
* 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.ant.jmx;
import java.util.ArrayList;
import java.util.List;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import org.apache.tools.ant.BuildException;
/**
* Access <em>JMX</em> JSR 160 MBeans Server.
* <ul>
* <li>open more then one JSR 160 rmi connection</li>
* <li>Get/Set Mbeans attributes</li>
* <li>Call Mbean Operation with arguments</li>
* <li>Argument values can be converted from string to int,long,float,double,boolean,ObjectName or InetAddress </li>
* <li>Query Mbeans</li>
* <li>Show Get, Call, Query result at Ant console log</li>
* <li>Bind Get, Call, Query result at Ant properties</li>
* </ul>
*
* Examples:
* <ul>
* <li>
* Get a session attribute hello from session with ref <em>${sessionid.0}</em> form
* app <em>Catalina:type=Manager,context=/ClusterTest,host=localhost</em>
* <pre>
* &lt;jmx:invoke
* name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
* operation="getSessionAttribute"
* resultproperty="hello"&gt;
* &lt;arg value="${sessionid.0}"/&gt;
* &lt;arg value="Hello"/&gt;
* &lt;/jmx:invoke&gt;
* </pre>
* </li>
* <li>
* Create new AccessLogger at localhost
* <code>
* &lt;jmx:invoke
* name="Catalina:type=MBeanFactory"
* operation="createAccessLoggerValve"
* resultproperty="accessLoggerObjectName"
* &gt;
* &lt;arg value="Catalina:type=Host,host=localhost"/&gt;
* &lt;/jmx:invoke&gt;
*
* </code>
* </li>
* <li>
* Remove existing AccessLogger at localhost
* <code>
* &lt;jmx:invoke
* name="Catalina:type=MBeanFactory"
* operation="removeValve"
* &gt;
* &lt;arg value="Catalina:type=Valve,name=AccessLogValve,host=localhost"/&gt;
* &lt;/jmx:invoke&gt;
*
* </code>
* </li>
* </ul>
* <p>
* First call to a remote MBeanserver save the JMXConnection a referenz <em>jmx.server</em>
* </p>
* These tasks require Ant 1.6 or later interface.
*
* @author Peter Rossbach
* @since 5.5.10
*/
public class JMXAccessorInvokeTask extends JMXAccessorTask {
// ----------------------------------------------------- Instance Variables
private String operation ;
private List<Arg> args=new ArrayList<>();
// ------------------------------------------------------------- Properties
/**
* @return Returns the operation.
*/
public String getOperation() {
return operation;
}
/**
* @param operation The operation to set.
*/
public void setOperation(String operation) {
this.operation = operation;
}
public void addArg(Arg arg ) {
args.add(arg);
}
/**
* @return Returns the args.
*/
public List<Arg> getArgs() {
return args;
}
/**
* @param args The args to set.
*/
public void setArgs(List<Arg> args) {
this.args = args;
}
// ------------------------------------------------------ protected Methods
@Override
public String jmxExecute(MBeanServerConnection jmxServerConnection)
throws Exception {
if (getName() == null) {
throw new BuildException("Must specify a 'name'");
}
if ((operation == null)) {
throw new BuildException(
"Must specify a 'operation' for call");
}
return jmxInvoke(jmxServerConnection, getName());
}
/**
* Invoke specified operation.
*
* @param jmxServerConnection Connection to the JMX server
* @param name The MBean name
* @return null (no error message to report other than exception)
* @throws Exception An error occurred
*/
protected String jmxInvoke(MBeanServerConnection jmxServerConnection, String name) throws Exception {
Object result ;
if (args == null) {
result = jmxServerConnection.invoke(new ObjectName(name),
operation, null, null);
} else {
Object argsA[]=new Object[ args.size()];
String sigA[]=new String[args.size()];
for( int i=0; i<args.size(); i++ ) {
Arg arg=args.get(i);
if (arg.getType() == null) {
arg.setType("java.lang.String");
sigA[i]=arg.getType();
argsA[i]=arg.getValue();
} else {
sigA[i]=arg.getType();
argsA[i]=convertStringToType(arg.getValue(),arg.getType());
}
}
result = jmxServerConnection.invoke(new ObjectName(name), operation, argsA, sigA);
}
if(result != null) {
echoResult(operation,result);
createProperty(result);
}
return null;
}
}

View File

@@ -0,0 +1,173 @@
/*
* 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.ant.jmx;
import java.util.Iterator;
import java.util.Set;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import org.apache.tools.ant.BuildException;
/**
* Query for Mbeans.
* <ul>
* <li>open no existing JSR 160 rmi jmx connection</li>
* <li>Get all Mbeans attributes</li>
* <li>Get only the Query Mbeans ObjectNames</li>
* <li>Show query result as Ant console log</li>
* <li>Bind query result as Ant properties</li>
* </ul>
* <br>
* Query a list of Mbeans.
* <pre>
* &lt;jmxQuery
* host="127.0.0.1"
* port="9014"
* name="Catalina:type=Manager,*
* resultproperty="manager" /&gt;
* </pre>
* with attribute <em>attributebinding="true"</em> you can get
* all attributes also from result objects.<br>
* The property manager.length show the size of the result
* and with manager.[0..length].name the
* resulted ObjectNames are saved.
* These tasks require Ant 1.6 or later interface.
*
* @author Peter Rossbach
* @since 5.5.10
*/
public class JMXAccessorQueryTask extends JMXAccessorTask {
// ----------------------------------------------------- Instance Variables
private boolean attributebinding = false;
// ------------------------------------------------------------- Properties
/**
* @return Returns the attributebinding.
*/
public boolean isAttributebinding() {
return attributebinding;
}
/**
* @param attributeBinding The attributebinding to set.
*/
public void setAttributebinding(boolean attributeBinding) {
this.attributebinding = attributeBinding;
}
// ------------------------------------------------------ protected Methods
@Override
public String jmxExecute(MBeanServerConnection jmxServerConnection)
throws Exception {
if (getName() == null) {
throw new BuildException("Must specify a 'name'");
}
return jmxQuery(jmxServerConnection, getName());
}
/**
* Call Mbean server for some mbeans with same domain, attributes.
* with <em>attributebinding=true</em> you can save all attributes from all found objects
*
* @param jmxServerConnection Connection to the JMX server
* @param qry The query
* @return null (no error message to report other than exception)
*/
protected String jmxQuery(MBeanServerConnection jmxServerConnection,
String qry) {
String isError = null;
Set<ObjectName> names = null;
String resultproperty = getResultproperty();
try {
names = jmxServerConnection.queryNames(new ObjectName(qry), null);
if (resultproperty != null) {
setProperty(resultproperty + ".Length",Integer.toString(names.size()));
}
} catch (Exception e) {
if (isEcho())
handleErrorOutput(e.getMessage());
return "Can't query mbeans " + qry;
}
if (resultproperty != null) {
Iterator<ObjectName> it = names.iterator();
int oindex = 0;
String pname = null;
while (it.hasNext()) {
ObjectName oname = it.next();
pname = resultproperty + "." + Integer.toString(oindex) + ".";
oindex++;
setProperty(pname + "Name", oname.toString());
if (isAttributebinding()) {
bindAttributes(jmxServerConnection, pname, oname);
}
}
}
return isError;
}
protected void bindAttributes(MBeanServerConnection jmxServerConnection, String pname, ObjectName oname) {
try {
MBeanInfo minfo = jmxServerConnection.getMBeanInfo(oname);
MBeanAttributeInfo attrs[] = minfo.getAttributes();
Object value = null;
for (int i = 0; i < attrs.length; i++) {
if (!attrs[i].isReadable())
continue;
String attName = attrs[i].getName();
if (attName.indexOf('=') >= 0 || attName.indexOf(':') >= 0
|| attName.indexOf(' ') >= 0) {
continue;
}
try {
value = jmxServerConnection
.getAttribute(oname, attName);
} catch (Exception e) {
if (isEcho())
handleErrorOutput("Error getting attribute "
+ oname + " " + pname + attName + " "
+ e.toString());
continue;
}
if (value == null)
continue;
if ("modelerType".equals(attName))
continue;
createProperty(pname + attName, value);
}
} catch (Exception e) {
// Ignore
}
}
}

View File

@@ -0,0 +1,195 @@
/*
* 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.ant.jmx;
import javax.management.Attribute;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import org.apache.tools.ant.BuildException;
/**
* Access <em>JMX</em> JSR 160 MBeans Server.
* <ul>
* <li>Get Mbeans attributes</li>
* <li>Show Get result as Ant console log</li>
* <li>Bind Get result as Ant properties</li>
* </ul>
* <p>
* Examples:
* Set an Mbean Manager attribute maxActiveSessions.
* Set this attribute with fresh jmx connection without save reference
* </p>
* <pre>
* &lt;jmx:set
* host="127.0.0.1"
* port="9014"
* ref=""
* name="Catalina:type=Manager,context="/ClusterTest",host=localhost"
* attribute="maxActiveSessions"
* value="100"
* type="int"
* echo="false"&gt;
* /&gt;
* </pre>
* <p>
* First call to a remote MBeanserver save the JMXConnection a referenz <em>jmx.server</em>
* </p>
* These tasks require Ant 1.6 or later interface.
*
* @author Peter Rossbach
* @since 5.5.10
*/
public class JMXAccessorSetTask extends JMXAccessorTask {
// ----------------------------------------------------- Instance Variables
private String attribute;
private String value;
private String type;
private boolean convert = false ;
// ------------------------------------------------------------- Properties
/**
* @return Returns the attribute.
*/
public String getAttribute() {
return attribute;
}
/**
* @param attribute The attribute to set.
*/
public void setAttribute(String attribute) {
this.attribute = attribute;
}
/**
* @return Returns the value.
*/
public String getValue() {
return value;
}
/**
* @param value The value to set.
*/
public void setValue(String value) {
this.value = value;
}
/**
* @return Returns the type.
*/
public String getType() {
return type;
}
/**
* @param valueType The type to set.
*/
public void setType(String valueType) {
this.type = valueType;
}
/**
* @return Returns the convert.
*/
public boolean isConvert() {
return convert;
}
/**
* @param convert The convert to set.
*/
public void setConvert(boolean convert) {
this.convert = convert;
}
// ------------------------------------------------------ protected Methods
@Override
public String jmxExecute(MBeanServerConnection jmxServerConnection)
throws Exception {
if (getName() == null) {
throw new BuildException("Must specify a 'name'");
}
if ((attribute == null || value == null)) {
throw new BuildException(
"Must specify a 'attribute' and 'value' for set");
}
return jmxSet(jmxServerConnection, getName());
}
/**
* Set property value.
*
* @param jmxServerConnection Connection to the JMX server
* @param name The MBean name
* @return null (no error message to report other than exception)
* @throws Exception An error occurred
*/
protected String jmxSet(MBeanServerConnection jmxServerConnection,
String name) throws Exception {
Object realValue;
if (type != null) {
realValue = convertStringToType(value, type);
} else {
if (isConvert()) {
String mType = getMBeanAttributeType(jmxServerConnection, name,
attribute);
realValue = convertStringToType(value, mType);
} else
realValue = value;
}
jmxServerConnection.setAttribute(new ObjectName(name), new Attribute(
attribute, realValue));
return null;
}
/**
* Get MBean Attribute from Mbean Server
*
* @param jmxServerConnection The JMX connection name
* @param name The MBean name
* @param attribute The attribute name
* @return The type of the attribute
* @throws Exception An error occurred
*/
protected String getMBeanAttributeType(
MBeanServerConnection jmxServerConnection,
String name,
String attribute) throws Exception {
ObjectName oname = new ObjectName(name);
String mattrType = null;
MBeanInfo minfo = jmxServerConnection.getMBeanInfo(oname);
MBeanAttributeInfo attrs[] = minfo.getAttributes();
for (int i = 0; mattrType == null && i < attrs.length; i++) {
if (attribute.equals(attrs[i].getName()))
mattrType = attrs[i].getType();
}
return mattrType;
}
}

View File

@@ -0,0 +1,714 @@
/*
* 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.ant.jmx;
import java.io.IOException;
import java.lang.reflect.Array;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.catalina.ant.BaseRedirectorHelperTask;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
/**
* Access <em>JMX</em> JSR 160 MBeans Server.
* <ul>
* <li>open more then one JSR 160 rmi connection</li>
* <li>Get/Set Mbeans attributes</li>
* <li>Call Mbean Operation with arguments</li>
* <li>Argument values can be converted from string to
* int,long,float,double,boolean,ObjectName or InetAddress</li>
* <li>Query Mbeans</li>
* <li>Show Get, Call, Query result at Ant console log</li>
* <li>Bind Get, Call, Query result at Ant properties</li>
* </ul>
*
* Examples: open server with reference and authorisation
*
* <pre>
*
* &lt;jmxOpen
* host=&quot;127.0.0.1&quot;
* port=&quot;9014&quot;
* username=&quot;monitorRole&quot;
* password=&quot;mysecret&quot;
* ref=&quot;jmx.myserver&quot;
* /&gt;
*
* </pre>
*
* All calls after opening with same refid reuse the connection.
* <p>
* First call to a remote MBeanserver save the JMXConnection a referenz
* <em>jmx.server</em>
* </p>
* All JMXAccessorXXXTask support the attribute <em>if</em> and
* <em>unless</em>. With <em>if</em> the task is only execute when property
* exist and with <em>unless</em> when property not exists. <br><b>NOTE
* </b>: These tasks require Ant 1.6 or later interface.
*
* @author Peter Rossbach
* @since 5.5.10
*/
public class JMXAccessorTask extends BaseRedirectorHelperTask {
public static final String JMX_SERVICE_PREFIX = "service:jmx:rmi:///jndi/rmi://";
public static final String JMX_SERVICE_SUFFIX = "/jmxrmi";
// ----------------------------------------------------- Instance Variables
private String name = null;
private String resultproperty;
private String url = null;
private String host = "localhost";
private String port = "8050";
private String password = null;
private String username = null;
private String ref = "jmx.server";
private boolean echo = false;
private boolean separatearrayresults = true;
private String delimiter;
private String unlessCondition;
private String ifCondition;
private final Properties properties = new Properties();
// ------------------------------------------------------------- Properties
/**
* Get the name used at remote MbeanServer.
*
* @return the name used at remote MbeanServer
*/
public String getName() {
return this.name;
}
public void setName(String objectName) {
this.name = objectName;
}
/**
* @return Returns the resultproperty.
*/
public String getResultproperty() {
return resultproperty;
}
/**
* @param propertyName The resultproperty to set.
*/
public void setResultproperty(String propertyName) {
this.resultproperty = propertyName;
}
/**
* @return Returns the delimiter.
*/
public String getDelimiter() {
return delimiter;
}
/**
* @param separator The delimiter to set.
*/
public void setDelimiter(String separator) {
this.delimiter = separator;
}
/**
* @return Returns the echo.
*/
public boolean isEcho() {
return echo;
}
/**
* @param echo
* The echo to set.
*/
public void setEcho(boolean echo) {
this.echo = echo;
}
/**
* @return Returns the separatearrayresults.
*/
public boolean isSeparatearrayresults() {
return separatearrayresults;
}
/**
* @param separateArrayResults
* The separatearrayresults to set.
*/
public void setSeparatearrayresults(boolean separateArrayResults) {
this.separatearrayresults = separateArrayResults;
}
/**
* @return The login password for the <code>Manager</code> application.
*/
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
/**
* @return The login username for the <code>JMX</code> MBeanServer.
*/
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* @return The URL of the <code>JMX JSR 160</code> MBeanServer to be used.
*/
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
/**
* @return The Host of the <code>JMX JSR 160</code> MBeanServer to be used.
*/
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
/**
* @return The Port of the <code>JMX JSR 160</code> MBeanServer to be used.
*/
public String getPort() {
return this.port;
}
public void setPort(String port) {
this.port = port;
}
/**
* @return Returns the useRef.
*/
public boolean isUseRef() {
return ref != null && !"".equals(ref);
}
/**
* @return Returns the ref.
*/
public String getRef() {
return ref;
}
/**
* @param refId The ref to set.
*/
public void setRef(String refId) {
this.ref = refId;
}
/**
* @return Returns the ifCondition.
*/
public String getIf() {
return ifCondition;
}
/**
* Only execute if a property of the given name exists in the current
* project.
*
* @param c property name
*/
public void setIf(String c) {
ifCondition = c;
}
/**
* @return Returns the unlessCondition.
*/
public String getUnless() {
return unlessCondition;
}
/**
* Only execute if a property of the given name does not exist in the
* current project.
*
* @param c property name
*/
public void setUnless(String c) {
unlessCondition = c;
}
// --------------------------------------------------------- Public Methods
/**
* Execute the specified command. This logic only performs the common
* attribute validation required by all subclasses; it does not perform any
* functional logic directly.
*
* @exception BuildException
* if a validation error occurs
*/
@Override
public void execute() throws BuildException {
if (testIfCondition() && testUnlessCondition()) {
try {
String error = null;
MBeanServerConnection jmxServerConnection = getJMXConnection();
error = jmxExecute(jmxServerConnection);
if (error != null && isFailOnError()) {
// exception should be thrown only if failOnError == true
// or error line will be logged twice
throw new BuildException(error);
}
} catch (Exception e) {
if (isFailOnError()) {
throw new BuildException(e);
} else {
handleErrorOutput(e.getMessage());
}
} finally {
closeRedirector();
}
}
}
/**
* Create a new JMX Connection with auth when username and password is set.
*
* @param url URL to be used for the JMX connection
* (if specified, it is a complete URL so host and port will not
* be used)
* @param host Host name of the JMX server
* @param port Port number for the JMX server
* @param username User name for the connection
* @param password Credentials corresponding to the specified user
* @throws MalformedURLException Invalid URL specified
* @throws IOException Other connection error
* @return the JMX connection
*/
public static MBeanServerConnection createJMXConnection(String url,
String host, String port, String username, String password)
throws MalformedURLException, IOException {
String urlForJMX;
if (url != null)
urlForJMX = url;
else
urlForJMX = JMX_SERVICE_PREFIX + host + ":" + port
+ JMX_SERVICE_SUFFIX;
Map<String, String[]> environment = null;
if (username != null && password != null) {
String[] credentials = new String[2];
credentials[0] = username;
credentials[1] = password;
environment = new HashMap<>();
environment.put(JMXConnector.CREDENTIALS, credentials);
}
return JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX),
environment).getMBeanServerConnection();
}
/**
* test the if condition
*
* @return true if there is no if condition, or the named property exists
*/
protected boolean testIfCondition() {
if (ifCondition == null || "".equals(ifCondition)) {
return true;
}
return getProperty(ifCondition) != null;
}
/**
* test the unless condition
*
* @return true if there is no unless condition, or there is a named
* property but it doesn't exist
*/
protected boolean testUnlessCondition() {
if (unlessCondition == null || "".equals(unlessCondition)) {
return true;
}
return getProperty(unlessCondition) == null;
}
/**
* Get Current Connection from <em>ref</em> parameter or create a new one!
*
* @param project The Ant project
* @param url URL to be used for the JMX connection
* (if specified, it is a complete URL so host and port will not
* be used)
* @param host Host name of the JMX server
* @param port Port number for the JMX server
* @param username User name for the connection
* @param password Credentials corresponding to the specified user
* @param refId The Id of the reference to retrieve in the project
* @throws MalformedURLException Invalid URL specified
* @throws IOException Other connection error
* @return the JMX connection
*/
@SuppressWarnings("null")
public static MBeanServerConnection accessJMXConnection(Project project,
String url, String host, String port, String username,
String password, String refId) throws MalformedURLException,
IOException {
MBeanServerConnection jmxServerConnection = null;
boolean isRef = project != null && refId != null && refId.length() > 0;
if (isRef) {
Object pref = project.getReference(refId);
try {
jmxServerConnection = (MBeanServerConnection) pref;
} catch (ClassCastException cce) {
project.log("wrong object reference " + refId + " - "
+ pref.getClass());
return null;
}
}
if (jmxServerConnection == null) {
jmxServerConnection = createJMXConnection(url, host, port,
username, password);
}
if (isRef && jmxServerConnection != null) {
project.addReference(refId, jmxServerConnection);
}
return jmxServerConnection;
}
// ------------------------------------------------------ protected Methods
/**
* get JMXConnection
*
* @throws MalformedURLException Invalid URL specified
* @throws IOException Other connection error
* @return the JMX connection
*/
protected MBeanServerConnection getJMXConnection()
throws MalformedURLException, IOException {
MBeanServerConnection jmxServerConnection = null;
if (isUseRef()) {
Object pref = null ;
if(getProject() != null) {
pref = getProject().getReference(getRef());
if (pref != null) {
try {
jmxServerConnection = (MBeanServerConnection) pref;
} catch (ClassCastException cce) {
getProject().log(
"Wrong object reference " + getRef() + " - "
+ pref.getClass());
return null;
}
}
}
if (jmxServerConnection == null) {
jmxServerConnection = accessJMXConnection(getProject(),
getUrl(), getHost(), getPort(), getUsername(),
getPassword(), getRef());
}
} else {
jmxServerConnection = accessJMXConnection(getProject(), getUrl(),
getHost(), getPort(), getUsername(), getPassword(), null);
}
return jmxServerConnection;
}
/**
* Execute the specified command, based on the configured properties. The
* input stream will be closed upon completion of this task, whether it was
* executed successfully or not.
*
* @param jmxServerConnection The JMX connection that should be used
* @return An error message string in some situations
* @exception Exception if an error occurs
*/
public String jmxExecute(MBeanServerConnection jmxServerConnection)
throws Exception {
if ((jmxServerConnection == null)) {
throw new BuildException("Must open a connection!");
} else if (isEcho()) {
handleOutput("JMX Connection ref=" + ref + " is open!");
}
return null;
}
/**
* Convert string to datatype FIXME How we can transfer values from ant
* project reference store (ref)?
*
* @param value The value
* @param valueType The type
* @return The converted object
*/
protected Object convertStringToType(String value, String valueType) {
if ("java.lang.String".equals(valueType))
return value;
Object convertValue = value;
if ("java.lang.Integer".equals(valueType) || "int".equals(valueType)) {
try {
convertValue = Integer.valueOf(value);
} catch (NumberFormatException ex) {
if (isEcho())
handleErrorOutput("Unable to convert to integer:" + value);
}
} else if ("java.lang.Long".equals(valueType)
|| "long".equals(valueType)) {
try {
convertValue = Long.valueOf(value);
} catch (NumberFormatException ex) {
if (isEcho())
handleErrorOutput("Unable to convert to long:" + value);
}
} else if ("java.lang.Boolean".equals(valueType)
|| "boolean".equals(valueType)) {
convertValue = Boolean.valueOf(value);
} else if ("java.lang.Float".equals(valueType)
|| "float".equals(valueType)) {
try {
convertValue = Float.valueOf(value);
} catch (NumberFormatException ex) {
if (isEcho())
handleErrorOutput("Unable to convert to float:" + value);
}
} else if ("java.lang.Double".equals(valueType)
|| "double".equals(valueType)) {
try {
convertValue = Double.valueOf(value);
} catch (NumberFormatException ex) {
if (isEcho())
handleErrorOutput("Unable to convert to double:" + value);
}
} else if ("javax.management.ObjectName".equals(valueType)
|| "name".equals(valueType)) {
try {
convertValue = new ObjectName(value);
} catch (MalformedObjectNameException e) {
if (isEcho())
handleErrorOutput("Unable to convert to ObjectName:"
+ value);
}
} else if ("java.net.InetAddress".equals(valueType)) {
try {
convertValue = InetAddress.getByName(value);
} catch (UnknownHostException exc) {
if (isEcho())
handleErrorOutput("Unable to resolve host name:" + value);
}
}
return convertValue;
}
/**
* @param name context of result
* @param result The result
*/
protected void echoResult(String name, Object result) {
if (isEcho()) {
if (result.getClass().isArray()) {
for (int i = 0; i < Array.getLength(result); i++) {
handleOutput(name + "." + i + "=" + Array.get(result, i));
}
} else
handleOutput(name + "=" + result);
}
}
/**
* create result as property with name from attribute resultproperty
*
* @param result The result
* @see #createProperty(String, Object)
*/
protected void createProperty(Object result) {
if (resultproperty != null) {
createProperty(resultproperty, result);
}
}
/**
* create result as property with name from property prefix When result is
* an array and isSeparateArrayResults is true, resultproperty used as
* prefix (<code>resultproperty.0-array.length</code> and store the
* result array length at <code>resultproperty.length</code>. Other
* option is that you delimit your result with a delimiter
* (java.util.StringTokenizer is used).
*
* @param propertyPrefix Prefix for the property
* @param result The result
*/
protected void createProperty(String propertyPrefix, Object result) {
if (propertyPrefix == null)
propertyPrefix = "";
if (result instanceof CompositeDataSupport) {
CompositeDataSupport data = (CompositeDataSupport) result;
CompositeType compositeType = data.getCompositeType();
Set<String> keys = compositeType.keySet();
for (String key : keys) {
Object value = data.get(key);
OpenType<?> type = compositeType.getType(key);
if (type instanceof SimpleType<?>) {
setProperty(propertyPrefix + "." + key, value);
} else {
createProperty(propertyPrefix + "." + key, value);
}
}
} else if (result instanceof TabularDataSupport) {
TabularDataSupport data = (TabularDataSupport) result;
for (Object key : data.keySet()) {
for (Object key1 : ((List<?>) key)) {
CompositeData valuedata = data.get(new Object[] { key1 });
Object value = valuedata.get("value");
OpenType<?> type = valuedata.getCompositeType().getType(
"value");
if (type instanceof SimpleType<?>) {
setProperty(propertyPrefix + "." + key1, value);
} else {
createProperty(propertyPrefix + "." + key1, value);
}
}
}
} else if (result.getClass().isArray()) {
if (isSeparatearrayresults()) {
int size = 0;
for (int i = 0; i < Array.getLength(result); i++) {
if (setProperty(propertyPrefix + "." + size, Array.get(
result, i))) {
size++;
}
}
if (size > 0) {
setProperty(propertyPrefix + ".Length", Integer
.toString(size));
}
}
} else {
String delim = getDelimiter();
if (delim != null) {
StringTokenizer tokenizer = new StringTokenizer(result
.toString(), delim);
int size = 0;
for (; tokenizer.hasMoreTokens();) {
String token = tokenizer.nextToken();
if (setProperty(propertyPrefix + "." + size, token)) {
size++;
}
}
if (size > 0)
setProperty(propertyPrefix + ".Length", Integer
.toString(size));
} else {
setProperty(propertyPrefix, result.toString());
}
}
}
/**
* Get Property
* @param property name
* @return The property value
*/
public String getProperty(String property) {
Project currentProject = getProject();
if (currentProject != null) {
return currentProject.getProperty(property);
} else {
return properties.getProperty(property);
}
}
/**
* @param property The property
* @param value The value
* @return True if successful
*/
public boolean setProperty(String property, Object value) {
if (property != null) {
if (value == null)
value = "";
if (isEcho()) {
handleOutput(property + "=" + value.toString());
}
Project currentProject = getProject();
if (currentProject != null) {
currentProject.setNewProperty(property, value.toString());
} else {
properties.setProperty(property, value.toString());
}
return true;
}
return false;
}
}

View File

@@ -0,0 +1,85 @@
/*
* 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.ant.jmx;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import org.apache.tools.ant.BuildException;
/**
* unregister an MBean at <em>JMX</em> JSR 160 MBeans Server.
* <ul>
* <li>unregister Mbeans</li>
* </ul>
* <p>
* Examples:
* <br>
* unregister an existing Mbean at jmx.server connection
* </p>
* <pre>
* &lt;jmx:unregister
* ref="jmx.server"
* name="Catalina:type=MBeanFactory" /&gt;
* </pre>
* <p>
* <b>WARNING</b>Not all Tomcat MBeans can successfully unregister remotely. The mbean
* unregistration don't remove valves, realm, .. from parent class.
* Please, use the MBeanFactory operation to remove valves and realms.
* </p>
* <p>
* First call to a remote MBeanserver save the JMXConnection a reference <em>jmx.server</em>
* </p>
* These tasks require Ant 1.6 or later interface.
*
* @author Peter Rossbach
* @since 5.5.12
*/
public class JMXAccessorUnregisterTask extends JMXAccessorTask {
// ------------------------------------------------------ protected Methods
@Override
public String jmxExecute(MBeanServerConnection jmxServerConnection)
throws Exception {
if (getName() == null) {
throw new BuildException("Must specify a 'name'");
}
return jmxUuregister(jmxServerConnection, getName());
}
/**
* Unregister MBean.
*
* @param jmxServerConnection Connection to the JMX server
* @param name The MBean name
* @return null (no error message to report other than exception)
* @throws Exception An error occurred
*/
protected String jmxUuregister(MBeanServerConnection jmxServerConnection,String name) throws Exception {
String error = null;
if(isEcho()) {
handleOutput("Unregister MBean " + name );
}
jmxServerConnection.unregisterMBean(
new ObjectName(name));
return error;
}
}

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<antlib>
<typedef
name="open"
classname="org.apache.catalina.ant.jmx.JMXAccessorTask" />
<typedef
name="set"
classname="org.apache.catalina.ant.jmx.JMXAccessorSetTask" />
<typedef
name="get"
classname="org.apache.catalina.ant.jmx.JMXAccessorGetTask" />
<typedef
name="invoke"
classname="org.apache.catalina.ant.jmx.JMXAccessorInvokeTask" />
<typedef
name="query"
classname="org.apache.catalina.ant.jmx.JMXAccessorQueryTask" />
<typedef
name="create"
classname="org.apache.catalina.ant.jmx.JMXAccessorCreateTask" />
<typedef
name="unregister"
classname="org.apache.catalina.ant.jmx.JMXAccessorUnregisterTask" />
<typedef
name="equals"
classname="org.apache.catalina.ant.jmx.JMXAccessorEqualsCondition" />
<typedef
name="condition"
classname="org.apache.catalina.ant.jmx.JMXAccessorCondition" />
</antlib>

View File

@@ -0,0 +1,25 @@
# 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.
# JMX
jmxOpen=org.apache.catalina.ant.jmx.JMXAccessorTask
jmxSet=org.apache.catalina.ant.jmx.JMXAccessorSetTask
jmxGet=org.apache.catalina.ant.jmx.JMXAccessorGetTask
jmxInvoke=org.apache.catalina.ant.jmx.JMXAccessorInvokeTask
jmxQuery=org.apache.catalina.ant.jmx.JMXAccessorQueryTask
jmxCreate=org.apache.catalina.ant.jmx.JMXAccessorCreateTask
jmxUnregister=org.apache.catalina.ant.jmx.JMXAccessorUnregisterTask
jmxEquals=org.apache.catalina.ant.jmx.JMXAccessorEqualsCondition
jmxCondition=org.apache.catalina.ant.jmx.JMXAccessorCondition

View File

@@ -0,0 +1,77 @@
<!--
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.
-->
<body>
<p>This package contains a set of <code>JMX Task</code> implementations for
<em>Ant (version 1.6 or later)</em> that can be used to interact with the
Remote JMX JSR 160 RMI Adaptor to get/set attributes, invoke MBean operations
and query for Mbeans inside a running instance of Tomcat. For more information, see
<a href="https://tomcat.apache.org/tomcat-8.5-doc/monitoring.html">
https://tomcat.apache.org/tomcat-8.5-doc/monitoring.html</a>.</p>
<p>Each task element can open a new jmx connection or reference an
existing one. The following attribute are exists in every tasks:</p>
<table>
<caption>Common task attributes</caption>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
<tr>
<td>url</td>
<td>
The JMX Connection URL of the remote Tomcat MBeansServer.
</td>
</tr>
<tr>
<td>username</td>
<td>
The username of an MBeanServer auth, when configured.
</td>
</tr>
<tr>
<td>password</td>
<td>
The password of an MBeanServer auth, when configured.
</td>
</tr>
<tr>
<td>host</td>
<td>
The JMX Connection host.
</td>
</tr>
<tr>
<td>port</td>
<td>
The JMX Connection port.
</td>
</tr>
<tr>
<td>ref</td>
<td>
The name of the ant internal reference for a jmx connection.
</td>
</tr>
</table>
<p><strong>NOTE</strong> - This Tasks only work,
when JSR 160 MBean Adaptor as remote jvm is configured.</p>
</body>

View File

@@ -0,0 +1,103 @@
<!--
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.
-->
<body>
<p>This package contains a set of <code>Task</code> implementations for
<em>Ant (version 1.6.x or later)</em> that can be used to interact with the
Manager application to deploy, undeploy, list, reload, start and stop web applications
from a running instance of Tomcat. For more information, see
<a href="https://tomcat.apache.org/tomcat-8.5-doc/manager-howto.html">
https://tomcat.apache.org/tomcat-8.5-doc/manager-howto.html</a>.</p>
<p>The attributes of each task element correspond
exactly to the request parameters that are included with an HTTP request
sent directly to the Manager application. They are summarized as follows:
</p>
<table>
<caption>Task attributes</caption>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
<tr>
<td>url</td>
<td>
The URL of the Manager web application you will use to
perform the requested operations. If not specified, defaults to
<code>http://localhost:8080/manager/text</code> (which corresponds
to a standard installation of Tomcat 7).
</td>
</tr>
<tr>
<td>username</td>
<td>
The username of a Tomcat user that has been configured with the
<code>manager-script</code> role, as required to execute Manager
application commands. This attribute is required.
</td>
</tr>
<tr>
<td>password</td>
<td>
The password of a Tomcat user that has been configured with the
<code>manager-script</code> role, as required to execute Manager
application commands. This attribute is required.
</td>
</tr>
<tr>
<td>config</td>
<td>
A URL pointing at the context configuration file (i.e. a file
containing only the <code>&lt;Context&gt;</code> element, and
its nested elements, from <code>server.xml</code> for a particular
web application). This attribute is supported only on the
<code>install</code> target, and is required only if you wish to
install an application with non-default configuration characteristics.
</td>
</tr>
<tr>
<td>path</td>
<td>
The context path (including the leading slash) of the web application
this command is intended to manage, or a zero-length string for the
ROOT web application. This attribute is valid for the
<code>install</code>, <code>reload</code>, <code>remove</code>,
<code>start</code>, and <code>stop</code> tasks only, and is
required in all of those cases.
</td>
</tr>
<tr>
<td>war</td>
<td>
A <code>jar:</code> URL that points at a web application archive (WAR)
file, or a <code>file:</code> URL that points at an unpacked directory
containing the web application. This attribute is supported only on
the <code>install</code> target. You must specify at least one of the
<code>config</code> and <code>war</code> attributes; if you specify
both, the <code>war</code> attribute overrides the <code>docBase</code>
attribute in the context configuration file.
</td>
</tr>
</table>
<p><strong>NOTE</strong> - Commands executed through the <em>Manager</em>
application are <strong>NOT</strong> reflected in updates to the Tomcat
<code>server.xml</code> configuration file, so they do not persist past the
next time you restart the entire Tomcat container.</p>
</body>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,289 @@
/*
* 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;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.connector.Request;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.codec.binary.Base64;
/**
* An <b>Authenticator</b> and <b>Valve</b> implementation of HTTP BASIC
* Authentication, as outlined in RFC 2617: "HTTP Authentication: Basic
* and Digest Access Authentication."
*
* @author Craig R. McClanahan
*/
public class BasicAuthenticator extends AuthenticatorBase {
private final Log log = LogFactory.getLog(BasicAuthenticator.class); // must not be static
private Charset charset = StandardCharsets.ISO_8859_1;
private String charsetString = null;
private boolean trimCredentials = true;
public String getCharset() {
return charsetString;
}
public void setCharset(String charsetString) {
// Only acceptable options are null, "" or "UTF-8" (case insensitive)
if (charsetString == null || charsetString.isEmpty()) {
charset = StandardCharsets.ISO_8859_1;
} else if ("UTF-8".equalsIgnoreCase(charsetString)) {
charset = StandardCharsets.UTF_8;
} else {
throw new IllegalArgumentException(sm.getString("basicAuthenticator.invalidCharset"));
}
this.charsetString = charsetString;
}
public boolean getTrimCredentials() {
return trimCredentials;
}
public void setTrimCredentials(boolean trimCredentials) {
this.trimCredentials = trimCredentials;
}
@Override
protected boolean doAuthenticate(Request request, HttpServletResponse response)
throws IOException {
if (checkForCachedAuthentication(request, response, true)) {
return true;
}
// Validate any credentials already included with this request
MessageBytes authorization =
request.getCoyoteRequest().getMimeHeaders()
.getValue("authorization");
if (authorization != null) {
authorization.toBytes();
ByteChunk authorizationBC = authorization.getByteChunk();
BasicCredentials credentials = null;
try {
credentials = new BasicCredentials(authorizationBC, charset, getTrimCredentials());
String username = credentials.getUsername();
String password = credentials.getPassword();
Principal principal = context.getRealm().authenticate(username, password);
if (principal != null) {
register(request, response, principal,
HttpServletRequest.BASIC_AUTH, username, password);
return true;
}
}
catch (IllegalArgumentException iae) {
if (log.isDebugEnabled()) {
log.debug("Invalid Authorization" + iae.getMessage());
}
}
}
// the request could not be authenticated, so reissue the challenge
StringBuilder value = new StringBuilder(16);
value.append("Basic realm=\"");
value.append(getRealmName(context));
value.append('\"');
if (charsetString != null && !charsetString.isEmpty()) {
value.append(", charset=");
value.append(charsetString);
}
response.setHeader(AUTH_HEADER_NAME, value.toString());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
@Override
protected String getAuthMethod() {
return HttpServletRequest.BASIC_AUTH;
}
/**
* Parser for an HTTP Authorization header for BASIC authentication
* as per RFC 2617 section 2, and the Base64 encoded credentials as
* per RFC 2045 section 6.8.
*/
public static class BasicCredentials {
// the only authentication method supported by this parser
// note: we include single white space as its delimiter
private static final String METHOD = "basic ";
private final Charset charset;
private final boolean trimCredentials;
private final ByteChunk authorization;
private final int initialOffset;
private int base64blobOffset;
private int base64blobLength;
private String username = null;
private String password = null;
/**
* Parse the HTTP Authorization header for BASIC authentication
* as per RFC 2617 section 2, and the Base64 encoded credentials
* as per RFC 2045 section 6.8.
*
* @param input The header value to parse in-place
* @param charset The character set to use to convert the bytes to a
* string
*
* @throws IllegalArgumentException If the header does not conform
* to RFC 2617
* @deprecated Unused. Will be removed in Tomcat 10. Use 3-arg constructor
*/
@Deprecated
public BasicCredentials(ByteChunk input, Charset charset) throws IllegalArgumentException {
this(input, charset, true);
}
/**
* Parse the HTTP Authorization header for BASIC authentication
* as per RFC 2617 section 2, and the Base64 encoded credentials
* as per RFC 2045 section 6.8.
*
* @param input The header value to parse in-place
* @param charset The character set to use to convert the bytes
* to a string
* @param trimCredentials Should leading and trailing whitespace be
* removed from the parsed credentials
*
* @throws IllegalArgumentException If the header does not conform
* to RFC 2617
*/
public BasicCredentials(ByteChunk input, Charset charset, boolean trimCredentials)
throws IllegalArgumentException {
authorization = input;
initialOffset = input.getOffset();
this.charset = charset;
this.trimCredentials = trimCredentials;
parseMethod();
byte[] decoded = parseBase64();
parseCredentials(decoded);
}
/**
* Trivial accessor.
*
* @return the decoded username token as a String, which is
* never be <code>null</code>, but can be empty.
*/
public String getUsername() {
return username;
}
/**
* Trivial accessor.
*
* @return the decoded password token as a String, or <code>null</code>
* if no password was found in the credentials.
*/
public String getPassword() {
return password;
}
/*
* The authorization method string is case-insensitive and must
* hae at least one space character as a delimiter.
*/
private void parseMethod() throws IllegalArgumentException {
if (authorization.startsWithIgnoreCase(METHOD, 0)) {
// step past the auth method name
base64blobOffset = initialOffset + METHOD.length();
base64blobLength = authorization.getLength() - METHOD.length();
}
else {
// is this possible, or permitted?
throw new IllegalArgumentException(
"Authorization header method is not \"Basic\"");
}
}
/*
* Decode the base64-user-pass token, which RFC 2617 states
* can be longer than the 76 characters per line limit defined
* in RFC 2045. The base64 decoder will ignore embedded line
* break characters as well as surplus surrounding white space.
*/
private byte[] parseBase64() throws IllegalArgumentException {
byte[] decoded = Base64.decodeBase64(
authorization.getBuffer(),
base64blobOffset, base64blobLength);
// restore original offset
authorization.setOffset(initialOffset);
if (decoded == null) {
throw new IllegalArgumentException(
"Basic Authorization credentials are not Base64");
}
return decoded;
}
/*
* Extract the mandatory username token and separate it from the
* optional password token. Tolerate surplus surrounding white space.
*/
private void parseCredentials(byte[] decoded)
throws IllegalArgumentException {
int colon = -1;
for (int i = 0; i < decoded.length; i++) {
if (decoded[i] == ':') {
colon = i;
break;
}
}
if (colon < 0) {
username = new String(decoded, charset);
// password will remain null!
}
else {
username = new String(decoded, 0, colon, charset);
password = new String(decoded, colon + 1, decoded.length - colon - 1, charset);
// tolerate surplus white space around credentials
if (password.length() > 1 && trimCredentials) {
password = password.trim();
}
}
// tolerate surplus white space around credentials
if (username.length() > 1 && trimCredentials) {
username = username.trim();
}
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* 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;
public class Constants {
// Authentication methods for login configuration
// Servlet spec schemes are defined in HttpServletRequest
// Vendor specific schemes
public static final String SPNEGO_METHOD = "SPNEGO";
// Form based authentication constants
public static final String FORM_ACTION = "/j_security_check";
public static final String FORM_PASSWORD = "j_password";
public static final String FORM_USERNAME = "j_username";
// SPNEGO authentication constants
public static final String KRB5_CONF_PROPERTY = "java.security.krb5.conf";
public static final String DEFAULT_KRB5_CONF = "conf/krb5.ini";
public static final String JAAS_CONF_PROPERTY = "java.security.auth.login.config";
public static final String DEFAULT_JAAS_CONF = "conf/jaas.conf";
public static final String DEFAULT_LOGIN_MODULE_NAME = "com.sun.security.jgss.krb5.accept";
/**
* @deprecated Unused. Will be removed in Tomcat 9.
*/
@Deprecated
public static final String USE_SUBJECT_CREDS_ONLY_PROPERTY = "javax.security.auth.useSubjectCredsOnly";
// Cookie name for single sign on support
public static final String SINGLE_SIGN_ON_COOKIE = System.getProperty(
"org.apache.catalina.authenticator.Constants.SSO_SESSION_COOKIE_NAME", "JSESSIONIDSSO");
// --------------------------------------------------------- Request Notes
/**
* The notes key to track the single-sign-on identity with which this
* request is associated.
*/
public static final String REQ_SSOID_NOTE = "org.apache.catalina.request.SSOID";
public static final String REQ_JASPIC_SUBJECT_NOTE = "org.apache.catalina.authenticator.jaspic.SUBJECT";
// ---------------------------------------------------------- Session Notes
/**
* The session id used as a CSRF marker when redirecting a user's request.
*/
public static final String SESSION_ID_NOTE = "org.apache.catalina.authenticator.SESSION_ID";
/**
* If the <code>cache</code> property of our authenticator is set, and
* the current request is part of a session, authentication information
* will be cached to avoid the need for repeated calls to
* <code>Realm.authenticate()</code>, under the following keys:
*/
/**
* The notes key for the password used to authenticate this user.
*/
public static final String SESS_PASSWORD_NOTE = "org.apache.catalina.session.PASSWORD";
/**
* The notes key for the username used to authenticate this user.
*/
public static final String SESS_USERNAME_NOTE = "org.apache.catalina.session.USERNAME";
/**
* The following note keys are used during form login processing to
* cache required information prior to the completion of authentication.
*/
/**
* The previously authenticated principal (if caching is disabled).
*
* @deprecated Unused. Will be removed in Tomcat 10.
*/
@Deprecated
public static final String FORM_PRINCIPAL_NOTE = "org.apache.catalina.authenticator.PRINCIPAL";
/**
* The original request information, to which the user will be
* redirected if authentication succeeds.
*/
public static final String FORM_REQUEST_NOTE = "org.apache.catalina.authenticator.REQUEST";
}

View File

@@ -0,0 +1,652 @@
/*
* 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;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Realm;
import org.apache.catalina.connector.Request;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.http.parser.Authorization;
import org.apache.tomcat.util.security.ConcurrentMessageDigest;
import org.apache.tomcat.util.security.MD5Encoder;
/**
* An <b>Authenticator</b> and <b>Valve</b> implementation of HTTP DIGEST
* Authentication (see RFC 2069).
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
public class DigestAuthenticator extends AuthenticatorBase {
private final Log log = LogFactory.getLog(DigestAuthenticator.class); // must not be static
// -------------------------------------------------------------- Constants
/**
* Tomcat's DIGEST implementation only supports auth quality of protection.
*/
protected static final String QOP = "auth";
// ----------------------------------------------------------- Constructors
public DigestAuthenticator() {
super();
setCache(false);
}
// ----------------------------------------------------- Instance Variables
/**
* List of server nonce values currently being tracked
*/
protected Map<String,NonceInfo> nonces;
/**
* The last timestamp used to generate a nonce. Each nonce should get a
* unique timestamp.
*/
protected long lastTimestamp = 0;
protected final Object lastTimestampLock = new Object();
/**
* Maximum number of server nonces to keep in the cache. If not specified,
* the default value of 1000 is used.
*/
protected int nonceCacheSize = 1000;
/**
* The window size to use to track seen nonce count values for a given
* nonce. If not specified, the default of 100 is used.
*/
protected int nonceCountWindowSize = 100;
/**
* Private key.
*/
protected String key = null;
/**
* How long server nonces are valid for in milliseconds. Defaults to 5
* minutes.
*/
protected long nonceValidity = 5 * 60 * 1000;
/**
* Opaque string.
*/
protected String opaque;
/**
* Should the URI be validated as required by RFC2617? Can be disabled in
* reverse proxies where the proxy has modified the URI.
*/
protected boolean validateUri = true;
// ------------------------------------------------------------- Properties
public int getNonceCountWindowSize() {
return nonceCountWindowSize;
}
public void setNonceCountWindowSize(int nonceCountWindowSize) {
this.nonceCountWindowSize = nonceCountWindowSize;
}
public int getNonceCacheSize() {
return nonceCacheSize;
}
public void setNonceCacheSize(int nonceCacheSize) {
this.nonceCacheSize = nonceCacheSize;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public long getNonceValidity() {
return nonceValidity;
}
public void setNonceValidity(long nonceValidity) {
this.nonceValidity = nonceValidity;
}
public String getOpaque() {
return opaque;
}
public void setOpaque(String opaque) {
this.opaque = opaque;
}
public boolean isValidateUri() {
return validateUri;
}
public void setValidateUri(boolean validateUri) {
this.validateUri = validateUri;
}
// --------------------------------------------------------- Public Methods
/**
* Authenticate the user making this request, based on the specified
* login configuration. Return <code>true</code> if any specified
* constraint has been satisfied, or <code>false</code> if we have
* created a response challenge already.
*
* @param request Request we are processing
* @param response Response we are creating
*
* @exception IOException if an input/output error occurs
*/
@Override
protected boolean doAuthenticate(Request request, HttpServletResponse response)
throws IOException {
// NOTE: We don't try to reauthenticate using any existing SSO session,
// because that will only work if the original authentication was
// BASIC or FORM, which are less secure than the DIGEST auth-type
// specified for this webapp
//
// Change to true below to allow previous FORM or BASIC authentications
// to authenticate users for this webapp
// TODO make this a configurable attribute (in SingleSignOn??)
if (checkForCachedAuthentication(request, response, false)) {
return true;
}
// Validate any credentials already included with this request
Principal principal = null;
String authorization = request.getHeader("authorization");
DigestInfo digestInfo = new DigestInfo(getOpaque(), getNonceValidity(),
getKey(), nonces, isValidateUri());
if (authorization != null) {
if (digestInfo.parse(request, authorization)) {
if (digestInfo.validate(request)) {
principal = digestInfo.authenticate(context.getRealm());
}
if (principal != null && !digestInfo.isNonceStale()) {
register(request, response, principal,
HttpServletRequest.DIGEST_AUTH,
digestInfo.getUsername(), null);
return true;
}
}
}
// Send an "unauthorized" response and an appropriate challenge
// Next, generate a nonce token (that is a token which is supposed
// to be unique).
String nonce = generateNonce(request);
setAuthenticateHeader(request, response, nonce,
principal != null && digestInfo.isNonceStale());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
@Override
protected String getAuthMethod() {
return HttpServletRequest.DIGEST_AUTH;
}
// ------------------------------------------------------ Protected Methods
/**
* Removes the quotes on a string. RFC2617 states quotes are optional for
* all parameters except realm.
*
* @param quotedString The quoted string
* @param quotesRequired <code>true</code> if quotes were required
* @return The unquoted string
*/
protected static String removeQuotes(String quotedString,
boolean quotesRequired) {
//support both quoted and non-quoted
if (quotedString.length() > 0 && quotedString.charAt(0) != '"' &&
!quotesRequired) {
return quotedString;
} else if (quotedString.length() > 2) {
return quotedString.substring(1, quotedString.length() - 1);
} else {
return "";
}
}
/**
* Removes the quotes on a string.
*
* @param quotedString The quoted string
* @return The unquoted string
*/
protected static String removeQuotes(String quotedString) {
return removeQuotes(quotedString, false);
}
/**
* Generate a unique token. The token is generated according to the
* following pattern. NOnceToken = Base64 ( MD5 ( client-IP ":"
* time-stamp ":" private-key ) ).
*
* @param request HTTP Servlet request
* @return The generated nonce
*/
protected String generateNonce(Request request) {
long currentTime = System.currentTimeMillis();
synchronized (lastTimestampLock) {
if (currentTime > lastTimestamp) {
lastTimestamp = currentTime;
} else {
currentTime = ++lastTimestamp;
}
}
String ipTimeKey =
request.getRemoteAddr() + ":" + currentTime + ":" + getKey();
byte[] buffer = ConcurrentMessageDigest.digestMD5(
ipTimeKey.getBytes(StandardCharsets.ISO_8859_1));
String nonce = currentTime + ":" + MD5Encoder.encode(buffer);
NonceInfo info = new NonceInfo(currentTime, getNonceCountWindowSize());
synchronized (nonces) {
nonces.put(nonce, info);
}
return nonce;
}
/**
* Generates the WWW-Authenticate header.
* <p>
* The header MUST follow this template :
* <pre>
* WWW-Authenticate = "WWW-Authenticate" ":" "Digest"
* digest-challenge
*
* digest-challenge = 1#( realm | [ domain ] | nonce |
* [ digest-opaque ] |[ stale ] | [ algorithm ] )
*
* realm = "realm" "=" realm-value
* realm-value = quoted-string
* domain = "domain" "=" &lt;"&gt; 1#URI &lt;"&gt;
* nonce = "nonce" "=" nonce-value
* nonce-value = quoted-string
* opaque = "opaque" "=" quoted-string
* stale = "stale" "=" ( "true" | "false" )
* algorithm = "algorithm" "=" ( "MD5" | token )
* </pre>
*
* @param request HTTP Servlet request
* @param response HTTP Servlet response
* @param nonce nonce token
* @param isNonceStale <code>true</code> to add a stale parameter
*/
protected void setAuthenticateHeader(HttpServletRequest request,
HttpServletResponse response,
String nonce,
boolean isNonceStale) {
String realmName = getRealmName(context);
String authenticateHeader;
if (isNonceStale) {
authenticateHeader = "Digest realm=\"" + realmName + "\", " +
"qop=\"" + QOP + "\", nonce=\"" + nonce + "\", " + "opaque=\"" +
getOpaque() + "\", stale=true";
} else {
authenticateHeader = "Digest realm=\"" + realmName + "\", " +
"qop=\"" + QOP + "\", nonce=\"" + nonce + "\", " + "opaque=\"" +
getOpaque() + "\"";
}
response.setHeader(AUTH_HEADER_NAME, authenticateHeader);
}
// ------------------------------------------------------- Lifecycle Methods
@Override
protected synchronized void startInternal() throws LifecycleException {
super.startInternal();
// Generate a random secret key
if (getKey() == null) {
setKey(sessionIdGenerator.generateSessionId());
}
// Generate the opaque string the same way
if (getOpaque() == null) {
setOpaque(sessionIdGenerator.generateSessionId());
}
nonces = new LinkedHashMap<String, DigestAuthenticator.NonceInfo>() {
private static final long serialVersionUID = 1L;
private static final long LOG_SUPPRESS_TIME = 5 * 60 * 1000;
private long lastLog = 0;
@Override
protected boolean removeEldestEntry(
Map.Entry<String,NonceInfo> eldest) {
// This is called from a sync so keep it simple
long currentTime = System.currentTimeMillis();
if (size() > getNonceCacheSize()) {
if (lastLog < currentTime &&
currentTime - eldest.getValue().getTimestamp() <
getNonceValidity()) {
// Replay attack is possible
log.warn(sm.getString(
"digestAuthenticator.cacheRemove"));
lastLog = currentTime + LOG_SUPPRESS_TIME;
}
return true;
}
return false;
}
};
}
public static class DigestInfo {
private final String opaque;
private final long nonceValidity;
private final String key;
private final Map<String,NonceInfo> nonces;
private boolean validateUri = true;
private String userName = null;
private String method = null;
private String uri = null;
private String response = null;
private String nonce = null;
private String nc = null;
private String cnonce = null;
private String realmName = null;
private String qop = null;
private String opaqueReceived = null;
private boolean nonceStale = false;
public DigestInfo(String opaque, long nonceValidity, String key,
Map<String,NonceInfo> nonces, boolean validateUri) {
this.opaque = opaque;
this.nonceValidity = nonceValidity;
this.key = key;
this.nonces = nonces;
this.validateUri = validateUri;
}
public String getUsername() {
return userName;
}
public boolean parse(Request request, String authorization) {
// Validate the authorization credentials format
if (authorization == null) {
return false;
}
Map<String,String> directives;
try {
directives = Authorization.parseAuthorizationDigest(
new StringReader(authorization));
} catch (IOException e) {
return false;
}
if (directives == null) {
return false;
}
method = request.getMethod();
userName = directives.get("username");
realmName = directives.get("realm");
nonce = directives.get("nonce");
nc = directives.get("nc");
cnonce = directives.get("cnonce");
qop = directives.get("qop");
uri = directives.get("uri");
response = directives.get("response");
opaqueReceived = directives.get("opaque");
return true;
}
public boolean validate(Request request) {
if ( (userName == null) || (realmName == null) || (nonce == null)
|| (uri == null) || (response == null) ) {
return false;
}
// Validate the URI - should match the request line sent by client
if (validateUri) {
String uriQuery;
String query = request.getQueryString();
if (query == null) {
uriQuery = request.getRequestURI();
} else {
uriQuery = request.getRequestURI() + "?" + query;
}
if (!uri.equals(uriQuery)) {
// Some clients (older Android) use an absolute URI for
// DIGEST but a relative URI in the request line.
// request. 2.3.5 < fixed Android version <= 4.0.3
String host = request.getHeader("host");
String scheme = request.getScheme();
if (host != null && !uriQuery.startsWith(scheme)) {
StringBuilder absolute = new StringBuilder();
absolute.append(scheme);
absolute.append("://");
absolute.append(host);
absolute.append(uriQuery);
if (!uri.equals(absolute.toString())) {
return false;
}
} else {
return false;
}
}
}
// Validate the Realm name
String lcRealm = getRealmName(request.getContext());
if (!lcRealm.equals(realmName)) {
return false;
}
// Validate the opaque string
if (!opaque.equals(opaqueReceived)) {
return false;
}
// Validate nonce
int i = nonce.indexOf(':');
if (i < 0 || (i + 1) == nonce.length()) {
return false;
}
long nonceTime;
try {
nonceTime = Long.parseLong(nonce.substring(0, i));
} catch (NumberFormatException nfe) {
return false;
}
String md5clientIpTimeKey = nonce.substring(i + 1);
long currentTime = System.currentTimeMillis();
if ((currentTime - nonceTime) > nonceValidity) {
nonceStale = true;
synchronized (nonces) {
nonces.remove(nonce);
}
}
String serverIpTimeKey =
request.getRemoteAddr() + ":" + nonceTime + ":" + key;
byte[] buffer = ConcurrentMessageDigest.digestMD5(
serverIpTimeKey.getBytes(StandardCharsets.ISO_8859_1));
String md5ServerIpTimeKey = MD5Encoder.encode(buffer);
if (!md5ServerIpTimeKey.equals(md5clientIpTimeKey)) {
return false;
}
// Validate qop
if (qop != null && !QOP.equals(qop)) {
return false;
}
// Validate cnonce and nc
// Check if presence of nc and Cnonce is consistent with presence of qop
if (qop == null) {
if (cnonce != null || nc != null) {
return false;
}
} else {
if (cnonce == null || nc == null) {
return false;
}
// RFC 2617 says nc must be 8 digits long. Older Android clients
// use 6. 2.3.5 < fixed Android version <= 4.0.3
if (nc.length() < 6 || nc.length() > 8) {
return false;
}
long count;
try {
count = Long.parseLong(nc, 16);
} catch (NumberFormatException nfe) {
return false;
}
NonceInfo info;
synchronized (nonces) {
info = nonces.get(nonce);
}
if (info == null) {
// Nonce is valid but not in cache. It must have dropped out
// of the cache - force a re-authentication
nonceStale = true;
} else {
if (!info.nonceCountValid(count)) {
return false;
}
}
}
return true;
}
public boolean isNonceStale() {
return nonceStale;
}
public Principal authenticate(Realm realm) {
// Second MD5 digest used to calculate the digest :
// MD5(Method + ":" + uri)
String a2 = method + ":" + uri;
byte[] buffer = ConcurrentMessageDigest.digestMD5(
a2.getBytes(StandardCharsets.ISO_8859_1));
String md5a2 = MD5Encoder.encode(buffer);
return realm.authenticate(userName, response, nonce, nc, cnonce,
qop, realmName, md5a2);
}
}
public static class NonceInfo {
private final long timestamp;
private final boolean seen[];
private final int offset;
private int count = 0;
public NonceInfo(long currentTime, int seenWindowSize) {
this.timestamp = currentTime;
seen = new boolean[seenWindowSize];
offset = seenWindowSize / 2;
}
public synchronized boolean nonceCountValid(long nonceCount) {
if ((count - offset) >= nonceCount ||
(nonceCount > count - offset + seen.length)) {
return false;
}
int checkIndex = (int) ((nonceCount + offset) % seen.length);
if (seen[checkIndex]) {
return false;
} else {
seen[checkIndex] = true;
seen[count % seen.length] = false;
count++;
return true;
}
}
public long getTimestamp() {
return timestamp;
}
}
}

View File

@@ -0,0 +1,725 @@
/*
* 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;
import java.io.IOException;
import java.io.InputStream;
import java.security.Principal;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Locale;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Realm;
import org.apache.catalina.Session;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.coyote.ActionCode;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.http.MimeHeaders;
/**
* An <b>Authenticator</b> and <b>Valve</b> implementation of FORM BASED
* Authentication, as described in the Servlet API Specification.
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
public class FormAuthenticator
extends AuthenticatorBase {
private final Log log = LogFactory.getLog(FormAuthenticator.class); // must not be static
// ----------------------------------------------------- Instance Variables
/**
* Character encoding to use to read the username and password parameters
* from the request. If not set, the encoding of the request body will be
* used.
*/
protected String characterEncoding = null;
/**
* Landing page to use if a user tries to access the login page directly or
* if the session times out during login. If not set, error responses will
* be sent instead.
*/
protected String landingPage = null;
// ------------------------------------------------------------- Properties
/**
* Return the character encoding to use to read the user name and password.
*
* @return The name of the character encoding
*/
public String getCharacterEncoding() {
return characterEncoding;
}
/**
* Set the character encoding to be used to read the user name and password.
*
* @param encoding The name of the encoding to use
*/
public void setCharacterEncoding(String encoding) {
characterEncoding = encoding;
}
/**
* Return the landing page to use when FORM auth is mis-used.
*
* @return The path to the landing page relative to the web application root
*/
public String getLandingPage() {
return landingPage;
}
/**
* Set the landing page to use when the FORM auth is mis-used.
*
* @param landingPage The path to the landing page relative to the web
* application root
*/
public void setLandingPage(String landingPage) {
this.landingPage = landingPage;
}
// ------------------------------------------------------ Protected Methods
/**
* Authenticate the user making this request, based on the specified
* login configuration. Return <code>true</code> if any specified
* constraint has been satisfied, or <code>false</code> if we have
* created a response challenge already.
*
* @param request Request we are processing
* @param response Response we are creating
*
* @exception IOException if an input/output error occurs
*/
@Override
protected boolean doAuthenticate(Request request, HttpServletResponse response)
throws IOException {
// References to objects we will need later
Session session = null;
Principal principal = null;
// Have we authenticated this user before but have caching disabled?
if (!cache) {
session = request.getSessionInternal(true);
if (log.isDebugEnabled()) {
log.debug("Checking for reauthenticate in session " + session);
}
String username = (String) session.getNote(Constants.SESS_USERNAME_NOTE);
String password = (String) session.getNote(Constants.SESS_PASSWORD_NOTE);
if (username != null && password != null) {
if (log.isDebugEnabled()) {
log.debug("Reauthenticating username '" + username + "'");
}
principal = context.getRealm().authenticate(username, password);
if (principal != null) {
register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
if (!matchRequest(request)) {
return true;
}
}
if (log.isDebugEnabled()) {
log.debug("Reauthentication failed, proceed normally");
}
}
}
// Is this the re-submit of the original request URI after successful
// authentication? If so, forward the *original* request instead.
if (matchRequest(request)) {
session = request.getSessionInternal(true);
if (log.isDebugEnabled()) {
log.debug("Restore request from session '" + session.getIdInternal() + "'");
}
if (restoreRequest(request, session)) {
if (log.isDebugEnabled()) {
log.debug("Proceed to restored request");
}
return true;
} else {
if (log.isDebugEnabled()) {
log.debug("Restore of original request failed");
}
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return false;
}
}
// This check has to be after the previous check for a matching request
// because that matching request may also include a cached Principal.
if (checkForCachedAuthentication(request, response, true)) {
return true;
}
// Acquire references to objects we will need to evaluate
String contextPath = request.getContextPath();
String requestURI = request.getDecodedRequestURI();
// Is this the action request from the login page?
boolean loginAction = requestURI.startsWith(contextPath) && requestURI.endsWith(Constants.FORM_ACTION);
LoginConfig config = context.getLoginConfig();
// No -- Save this request and redirect to the form login page
if (!loginAction) {
// If this request was to the root of the context without a trailing
// '/', need to redirect to add it else the submit of the login form
// may not go to the correct web application
if (request.getServletPath().length() == 0 && request.getPathInfo() == null) {
StringBuilder location = new StringBuilder(requestURI);
location.append('/');
if (request.getQueryString() != null) {
location.append('?');
location.append(request.getQueryString());
}
response.sendRedirect(response.encodeRedirectURL(location.toString()));
return false;
}
session = request.getSessionInternal(true);
if (log.isDebugEnabled()) {
log.debug("Save request in session '" + session.getIdInternal() + "'");
}
try {
saveRequest(request, session);
} catch (IOException ioe) {
log.debug("Request body too big to save during authentication");
response.sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("authenticator.requestBodyTooBig"));
return false;
}
forwardToLoginPage(request, response, config);
return false;
}
// Yes -- Acknowledge the request, validate the specified credentials
// and redirect to the error page if they are not correct
request.getResponse().sendAcknowledgement();
Realm realm = context.getRealm();
if (characterEncoding != null) {
request.setCharacterEncoding(characterEncoding);
}
String username = request.getParameter(Constants.FORM_USERNAME);
String password = request.getParameter(Constants.FORM_PASSWORD);
if (log.isDebugEnabled()) {
log.debug("Authenticating username '" + username + "'");
}
principal = realm.authenticate(username, password);
if (principal == null) {
forwardToErrorPage(request, response, config);
return false;
}
if (log.isDebugEnabled()) {
log.debug("Authentication of '" + username + "' was successful");
}
if (session == null) {
session = request.getSessionInternal(false);
}
if (session != null && getChangeSessionIdOnAuthentication()) {
// Does session id match?
String expectedSessionId = (String) session.getNote(Constants.SESSION_ID_NOTE);
if (expectedSessionId == null || !expectedSessionId.equals(request.getRequestedSessionId())) {
session.expire();
session = null;
}
}
if (session == null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug("User took so long to log on the session expired");
}
if (landingPage == null) {
response.sendError(
HttpServletResponse.SC_REQUEST_TIMEOUT, sm.getString("authenticator.sessionExpired"));
} else {
// Make the authenticator think the user originally requested
// the landing page
String uri = request.getContextPath() + landingPage;
SavedRequest saved = new SavedRequest();
saved.setMethod("GET");
saved.setRequestURI(uri);
saved.setDecodedRequestURI(uri);
request.getSessionInternal(true).setNote(Constants.FORM_REQUEST_NOTE, saved);
response.sendRedirect(response.encodeRedirectURL(uri));
}
return false;
}
register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
// Redirect the user to the original request URI (which will cause
// the original request to be restored)
requestURI = savedRequestURL(session);
if (log.isDebugEnabled()) {
log.debug("Redirecting to original '" + requestURI + "'");
}
if (requestURI == null) {
if (landingPage == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString("authenticator.formlogin"));
} else {
// Make the authenticator think the user originally requested
// the landing page
String uri = request.getContextPath() + landingPage;
SavedRequest saved = new SavedRequest();
saved.setMethod("GET");
saved.setRequestURI(uri);
saved.setDecodedRequestURI(uri);
session.setNote(Constants.FORM_REQUEST_NOTE, saved);
response.sendRedirect(response.encodeRedirectURL(uri));
}
} else {
// Until the Servlet API allows specifying the type of redirect to
// use.
Response internalResponse = request.getResponse();
String location = response.encodeRedirectURL(requestURI);
if ("HTTP/1.1".equals(request.getProtocol())) {
internalResponse.sendRedirect(location, HttpServletResponse.SC_SEE_OTHER);
} else {
internalResponse.sendRedirect(location, HttpServletResponse.SC_FOUND);
}
}
return false;
}
@Override
protected boolean isContinuationRequired(Request request) {
// Special handling for form-based logins to deal with the case
// where the login form (and therefore the "j_security_check" URI
// to which it submits) might be outside the secured area
String contextPath = this.context.getPath();
String decodedRequestURI = request.getDecodedRequestURI();
if (decodedRequestURI.startsWith(contextPath) &&
decodedRequestURI.endsWith(Constants.FORM_ACTION)) {
return true;
}
// Special handling for form-based logins to deal with the case where
// a resource is protected for some HTTP methods but not protected for
// GET which is used after authentication when redirecting to the
// protected resource.
// TODO: This is similar to the FormAuthenticator.matchRequest() logic
// Is there a way to remove the duplication?
Session session = request.getSessionInternal(false);
if (session != null) {
SavedRequest savedRequest = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
if (savedRequest != null &&
decodedRequestURI.equals(savedRequest.getDecodedRequestURI())) {
return true;
}
}
return false;
}
@Override
protected String getAuthMethod() {
return HttpServletRequest.FORM_AUTH;
}
@Override
protected void register(Request request, HttpServletResponse response,
Principal principal, String authType, String username,
String password, boolean alwaysUseSession, boolean cache) {
super.register(request, response, principal, authType, username, password, alwaysUseSession, cache);
// If caching an authenticated Principal is turned off,
// store username and password as session notes to use them for re-authentication.
if (!cache) {
Session session = request.getSessionInternal(false);
if (session != null) {
if (username != null) {
session.setNote(Constants.SESS_USERNAME_NOTE, username);
} else {
session.removeNote(Constants.SESS_USERNAME_NOTE);
}
if (password != null) {
session.setNote(Constants.SESS_PASSWORD_NOTE, password);
} else {
session.removeNote(Constants.SESS_PASSWORD_NOTE);
}
}
}
}
/**
* Called to forward to the login page
*
* @param request Request we are processing
* @param response Response we are populating
* @param config Login configuration describing how authentication
* should be performed
* @throws IOException If the forward to the login page fails and the call
* to {@link HttpServletResponse#sendError(int, String)}
* throws an {@link IOException}
*/
protected void forwardToLoginPage(Request request,
HttpServletResponse response, LoginConfig config)
throws IOException {
if (log.isDebugEnabled()) {
log.debug(sm.getString("formAuthenticator.forwardLogin",
request.getRequestURI(), request.getMethod(),
config.getLoginPage(), context.getName()));
}
String loginPage = config.getLoginPage();
if (loginPage == null || loginPage.length() == 0) {
String msg = sm.getString("formAuthenticator.noLoginPage",
context.getName());
log.warn(msg);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
return;
}
if (getChangeSessionIdOnAuthentication()) {
Session session = request.getSessionInternal(false);
if (session != null) {
String newSessionId = changeSessionID(request, session);
session.setNote(Constants.SESSION_ID_NOTE, newSessionId);
}
}
// Always use GET for the login page, regardless of the method used
String oldMethod = request.getMethod();
request.getCoyoteRequest().method().setString("GET");
RequestDispatcher disp =
context.getServletContext().getRequestDispatcher(loginPage);
try {
if (context.fireRequestInitEvent(request.getRequest())) {
disp.forward(request.getRequest(), response);
context.fireRequestDestroyEvent(request.getRequest());
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
String msg = sm.getString("formAuthenticator.forwardLoginFail");
log.warn(msg, t);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
} finally {
// Restore original method so that it is written into access log
request.getCoyoteRequest().method().setString(oldMethod);
}
}
/**
* Called to forward to the error page
*
* @param request Request we are processing
* @param response Response we are populating
* @param config Login configuration describing how authentication
* should be performed
* @throws IOException If the forward to the error page fails and the call
* to {@link HttpServletResponse#sendError(int, String)}
* throws an {@link IOException}
*/
protected void forwardToErrorPage(Request request,
HttpServletResponse response, LoginConfig config)
throws IOException {
String errorPage = config.getErrorPage();
if (errorPage == null || errorPage.length() == 0) {
String msg = sm.getString("formAuthenticator.noErrorPage",
context.getName());
log.warn(msg);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
return;
}
RequestDispatcher disp =
context.getServletContext().getRequestDispatcher(config.getErrorPage());
try {
if (context.fireRequestInitEvent(request.getRequest())) {
disp.forward(request.getRequest(), response);
context.fireRequestDestroyEvent(request.getRequest());
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
String msg = sm.getString("formAuthenticator.forwardErrorFail");
log.warn(msg, t);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
}
}
/**
* Does this request match the saved one (so that it must be the redirect
* we signaled after successful authentication?
*
* @param request The request to be verified
* @return <code>true</code> if the requests matched the saved one
*/
protected boolean matchRequest(Request request) {
// Has a session been created?
Session session = request.getSessionInternal(false);
if (session == null) {
return false;
}
// Is there a saved request?
SavedRequest sreq = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
if (sreq == null) {
return false;
}
// Is there a saved principal?
if (cache && session.getPrincipal() == null || !cache && request.getPrincipal() == null) {
return false;
}
// Does session id match?
if (getChangeSessionIdOnAuthentication()) {
String expectedSessionId = (String) session.getNote(Constants.SESSION_ID_NOTE);
if (expectedSessionId == null || !expectedSessionId.equals(request.getRequestedSessionId())) {
return false;
}
}
// Does the request URI match?
String decodedRequestURI = request.getDecodedRequestURI();
if (decodedRequestURI == null) {
return false;
}
return decodedRequestURI.equals(sreq.getDecodedRequestURI());
}
/**
* Restore the original request from information stored in our session.
* If the original request is no longer present (because the session
* timed out), return <code>false</code>; otherwise, return
* <code>true</code>.
*
* @param request The request to be restored
* @param session The session containing the saved information
* @return <code>true</code> if the request was successfully restored
* @throws IOException if an IO error occurred during the process
*/
protected boolean restoreRequest(Request request, Session session)
throws IOException {
// Retrieve and remove the SavedRequest object from our session
SavedRequest saved = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
session.removeNote(Constants.FORM_REQUEST_NOTE);
session.removeNote(Constants.SESSION_ID_NOTE);
if (saved == null) {
return false;
}
// Swallow any request body since we will be replacing it
// Need to do this before headers are restored as AJP connector uses
// content length header to determine how much data needs to be read for
// request body
byte[] buffer = new byte[4096];
InputStream is = request.createInputStream();
while (is.read(buffer) >= 0) {
// Ignore request body
}
// Modify our current request to reflect the original one
request.clearCookies();
Iterator<Cookie> cookies = saved.getCookies();
while (cookies.hasNext()) {
request.addCookie(cookies.next());
}
String method = saved.getMethod();
MimeHeaders rmh = request.getCoyoteRequest().getMimeHeaders();
rmh.recycle();
boolean cacheable = "GET".equalsIgnoreCase(method) ||
"HEAD".equalsIgnoreCase(method);
Iterator<String> names = saved.getHeaderNames();
while (names.hasNext()) {
String name = names.next();
// The browser isn't expecting this conditional response now.
// Assuming that it can quietly recover from an unexpected 412.
// BZ 43687
if(!("If-Modified-Since".equalsIgnoreCase(name) ||
(cacheable && "If-None-Match".equalsIgnoreCase(name)))) {
Iterator<String> values = saved.getHeaderValues(name);
while (values.hasNext()) {
rmh.addValue(name).setString(values.next());
}
}
}
request.clearLocales();
Iterator<Locale> locales = saved.getLocales();
while (locales.hasNext()) {
request.addLocale(locales.next());
}
request.getCoyoteRequest().getParameters().recycle();
ByteChunk body = saved.getBody();
if (body != null) {
request.getCoyoteRequest().action
(ActionCode.REQ_SET_BODY_REPLAY, body);
// Set content type
MessageBytes contentType = MessageBytes.newInstance();
// If no content type specified, use default for POST
String savedContentType = saved.getContentType();
if (savedContentType == null && "POST".equalsIgnoreCase(method)) {
savedContentType = "application/x-www-form-urlencoded";
}
contentType.setString(savedContentType);
request.getCoyoteRequest().setContentType(contentType);
}
request.getCoyoteRequest().method().setString(method);
// The method, URI, queryString and protocol are normally stored as
// bytes in the HttpInputBuffer and converted lazily to String. At this
// point, the method has already been set as String in the line above
// but the URI, queryString and protocol are still in byte form in the
// HttpInputBuffer. Processing the saved request body will overwrite
// these bytes. Configuring the HttpInputBuffer to retain these bytes as
// it would in a normal request would require some invasive API changes.
// Therefore force the conversion to String now so the correct values
// are presented if the application requests them.
request.getRequestURI();
request.getQueryString();
request.getProtocol();
return true;
}
/**
* Save the original request information into our session.
*
* @param request The request to be saved
* @param session The session to contain the saved information
* @throws IOException if an IO error occurred during the process
*/
protected void saveRequest(Request request, Session session)
throws IOException {
// Create and populate a SavedRequest object for this request
SavedRequest saved = new SavedRequest();
Cookie cookies[] = request.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
saved.addCookie(cookies[i]);
}
}
Enumeration<String> names = request.getHeaderNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
Enumeration<String> values = request.getHeaders(name);
while (values.hasMoreElements()) {
String value = values.nextElement();
saved.addHeader(name, value);
}
}
Enumeration<Locale> locales = request.getLocales();
while (locales.hasMoreElements()) {
Locale locale = locales.nextElement();
saved.addLocale(locale);
}
// May need to acknowledge a 100-continue expectation
request.getResponse().sendAcknowledgement();
int maxSavePostSize = request.getConnector().getMaxSavePostSize();
if (maxSavePostSize != 0) {
ByteChunk body = new ByteChunk();
body.setLimit(maxSavePostSize);
byte[] buffer = new byte[4096];
int bytesRead;
InputStream is = request.getInputStream();
while ( (bytesRead = is.read(buffer) ) >= 0) {
body.append(buffer, 0, bytesRead);
}
// Only save the request body if there is something to save
if (body.getLength() > 0) {
saved.setContentType(request.getContentType());
saved.setBody(body);
}
}
saved.setMethod(request.getMethod());
saved.setQueryString(request.getQueryString());
saved.setRequestURI(request.getRequestURI());
saved.setDecodedRequestURI(request.getDecodedRequestURI());
// Stash the SavedRequest in our session for later use
session.setNote(Constants.FORM_REQUEST_NOTE, saved);
}
/**
* Return the request URI (with the corresponding query string, if any)
* from the saved request so that we can redirect to it.
*
* @param session Our current session
* @return the original request URL
*/
protected String savedRequestURL(Session session) {
SavedRequest saved =
(SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
if (saved == null) {
return null;
}
StringBuilder sb = new StringBuilder(saved.getRequestURI());
if (saved.getQueryString() != null) {
sb.append('?');
sb.append(saved.getQueryString());
}
return sb.toString();
}
}

View File

@@ -0,0 +1,72 @@
# 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.
authenticator.certificates=No client certificate chain in this request
authenticator.changeSessionId=Session ID changed on authentication from [{0}] to [{1}]
authenticator.check.authorize=User name [{0}] obtained from the Connector and trusted to be valid. Obtaining roles for this user from the Tomcat Realm.
authenticator.check.authorizeFail=Realm did not recognise user [{0}]. Creating a Principal with that name and no roles.
authenticator.check.found=Already authenticated [{0}]
authenticator.check.sso=Not authenticated but SSO session ID [{0}] found. Attempting re-authentication.
authenticator.formlogin=Invalid direct reference to form login page
authenticator.jaspicCleanSubjectFail=Failed to clean JASPIC subject
authenticator.jaspicSecureResponseFail=Failed to secure response during JASPIC processing
authenticator.jaspicServerAuthContextFail=Failed to obtain a JASPIC ServerAuthContext instance
authenticator.loginFail=Login failed
authenticator.manager=Exception initializing trust managers
authenticator.noAuthHeader=No authorization header sent by client
authenticator.notContext=Configuration error: Must be attached to a Context
authenticator.requestBodyTooBig=The request body was too large to be cached during the authentication process
authenticator.sessionExpired=The time allowed for the login process has been exceeded. If you wish to continue you must either click back twice and re-click the link you requested or close and re-open your browser
authenticator.tomcatPrincipalLogoutFail=Logout with TomcatPrincipal instance has failed
authenticator.unauthorized=Cannot authenticate with the provided credentials
basicAuthenticator.invalidCharset=The only permitted values are null, the empty string or UTF-8
digestAuthenticator.cacheRemove=A valid entry has been removed from client nonce cache to make room for new entries. A replay attack is now possible. To prevent the possibility of replay attacks, reduce nonceValidity or increase nonceCacheSize. Further warnings of this type will be suppressed for 5 minutes.
formAuthenticator.forwardErrorFail=Unexpected error forwarding to error page
formAuthenticator.forwardLogin=Forwarding request for [{0}] made with method [{1}] to login page [{2}] of context [{3}] using request method GET
formAuthenticator.forwardLoginFail=Unexpected error forwarding to login page
formAuthenticator.noErrorPage=No error page was defined for FORM authentication in context [{0}]
formAuthenticator.noLoginPage=No login page was defined for FORM authentication in context [{0}]
singleSignOn.debug.associate=SSO associating application session [{1}] with SSO session [{0}]
singleSignOn.debug.associateFail=SSO failed to associate application session [{0}] since SSO session [{1}] does not exist
singleSignOn.debug.cookieCheck=SSO checking for SSO cookie
singleSignOn.debug.cookieNotFound=SSO did not find an SSO cookie
singleSignOn.debug.deregister=SSO expiring application session [{0}] associated with SSO session [{1}]
singleSignOn.debug.deregisterFail=SSO failed to deregister the SSO session [{0}] because it was not in the cache
singleSignOn.debug.deregisterNone=SSO deregistered the SSO session [{0}] but found no associated application sessions
singleSignOn.debug.hasPrincipal=SSO found previously authenticated Principal [{0}]
singleSignOn.debug.invoke=SSO processing request for [{0}]
singleSignOn.debug.principalCheck=SSO looking for a cached Principal for SSO session [{0}]
singleSignOn.debug.principalFound=SSO found cached Principal [{0}] with authentication type [{1}]
singleSignOn.debug.principalNotFound=SSO did not find a cached Principal. Erasing SSO cookie for session [{0}]
singleSignOn.debug.register=SSO registering SSO session [{0}] for user [{1}] with authentication type [{2}]
singleSignOn.debug.removeSession=SSO removing application session [{0}] from SSO session [{1}]
singleSignOn.debug.sessionLogout=SSO processing a log out for SSO session [{0}] and application session [{1}]
singleSignOn.debug.sessionTimeout=SSO processing a time out for SSO session [{0}] and application session [{1}]
singleSignOn.debug.update=SSO updating SSO session [{0}] to authentication type [{1}]
singleSignOn.sessionExpire.contextNotFound=SSO unable to expire session [{0}] because the Context could not be found
singleSignOn.sessionExpire.engineNull=SSO unable to expire session [{0}] because the Engine was null
singleSignOn.sessionExpire.hostNotFound=SSO unable to expire session [{0}] because the Host could not be found
singleSignOn.sessionExpire.managerError=SSO unable to expire session [{0}] because the Manager threw an Exception when searching for the session
singleSignOn.sessionExpire.managerNotFound=SSO unable to expire session [{0}] because the Manager could not be found
singleSignOn.sessionExpire.sessionNotFound=SSO unable to expire session [{0}] because the Session could not be found
spnegoAuthenticator.authHeaderNoToken=The Negotiate authorization header sent by the client did not include a token
spnegoAuthenticator.authHeaderNotNego=The authorization header sent by the client did not start with Negotiate
spnegoAuthenticator.serviceLoginFail=Unable to login as the service principal
spnegoAuthenticator.ticketValidateFail=Failed to validate client supplied ticket

View File

@@ -0,0 +1,23 @@
# 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.
authenticator.certificates=Keine Client Zertifikatskette im Request
authenticator.check.found=Bereits authentifiziert [{0}]
authenticator.jaspicCleanSubjectFail=Konnte JASPIC Subject nicht leeren.
authenticator.jaspicServerAuthContextFail=Kontte keine JASPIC ServerAuthContext Instanz erhalten
singleSignOn.debug.cookieCheck=SSO prüfe nach SSO Cookie
singleSignOn.debug.principalFound=SSO fand Principal [{0}] mut Authentication Typ [{1}] im Cache
singleSignOn.sessionExpire.hostNotFound=SSO kann Session [{0}] nicht ablaufen lassen, da der Host nicht gefunden werden konnte

View File

@@ -0,0 +1,44 @@
# 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.
authenticator.certificates=No hay cadena de certificados del cliente en esta petición
authenticator.formlogin=Referencia directa al formulario de conexión (página de formulario de login) inválida
authenticator.jaspicCleanSubjectFail=Fallo al limpiar el elemento JASPIC \n
authenticator.jaspicServerAuthContextFail=Fallo al intentar obtener una instancia JASPIC ServerAuthContext
authenticator.loginFail=No pude ingresar
authenticator.manager=Excepción inicializando administradores de confianza
authenticator.noAuthHeader=El cliente no ha enviado autorización de cabecera
authenticator.notContext=Error de Configuración: Debe de estar unido a un Contexto
authenticator.requestBodyTooBig=El cuerpo del requerimiento era demasiado grande para realizar caché durante el proceso de autenticación
authenticator.sessionExpired=El tiempo permitido para realizar login ha sido excedido. Si deseas continuar, debes hacer clik dos veces y volver a hacer clik otra vez o cerrar y reabrir tu navegador
authenticator.unauthorized=Imposible autenticar mediante las credenciales suministradas
digestAuthenticator.cacheRemove=Se ha quitado una entrada válida de la caché "nonce" del cliente para hacer espacio a nuevas entradas.. Ahora es posible un ataque de reinyección. Para prevenirlos, reduce "nonceValidity" o incrementa "nonceCacheSize". El resto de mensajes de este tipo serán suspendidos durante 5 minutos.
formAuthenticator.forwardErrorFail=Error inesperado de reenvío a página de error
formAuthenticator.forwardLoginFail=Error inesperado de reenvío a pagina de ingreso
formAuthenticator.noErrorPage=No se ha definido página de error para la autenticación FORM en el contexto [{0}]
formAuthenticator.noLoginPage=No se ha definido página de ingreso para la autenticación FORM en el contexto [{0}]
singleSignOn.debug.principalCheck=SSO esta buscando un Principal cacheado para las sesión SSO [{0}]\n
singleSignOn.debug.principalFound=SSO encontró el Principal cacheado [{0}] con autenticación tipo [{1}]\n
singleSignOn.debug.removeSession=SSO removiendo la sesión de la aplicación [{0}] SSO con sesión [{1}]\n
singleSignOn.sessionExpire.hostNotFound=SSO es incapaz de expirar la session [{0}] porque el Host no puede ser encontrado
singleSignOn.sessionExpire.managerError=SSO incapaz de expirar sesión [{0}] porque el Gerenciador lanzó una excepción mientras buscaba la sesión
spnegoAuthenticator.authHeaderNoToken=La cabecera de Negociación de autorización enviada por el cliente no incluía una ficha
spnegoAuthenticator.authHeaderNotNego=La cabecera de autorización enviada por el cliente no comenzaba con Negotiate
spnegoAuthenticator.serviceLoginFail=No puedo ingresar como director del servicio
spnegoAuthenticator.ticketValidateFail=No pude validar el billete suministrado por el cliente

View File

@@ -0,0 +1,72 @@
# 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.
authenticator.certificates=Aucune chaîne de certificat client (client certificate chain) dans cette requête
authenticator.changeSessionId=L''id de session a changé suite à l''authntification de [{0}] en [{1}]
authenticator.check.authorize=Le nom d''utilisateur [{0}] obtenu à partir du connecteur est considéré comme de valide et de confiance, les rôles sont obtenus à partir du royaume
authenticator.check.authorizeFail=Le royaume ne reconnait pas l''utilisateur [{0}], un principal a été crée avec ce nom mais sans rôles
authenticator.check.found=Déjà authentifié [{0}]
authenticator.check.sso=Pas d''authentification mais un session ID SSO [{0}] a été trouvé, nouvelle tentative d''authentification
authenticator.formlogin=Référence directe au formulaire de connexion (form login page) invalide
authenticator.jaspicCleanSubjectFail=Échec du nettoyage du sujet de JASPIC
authenticator.jaspicSecureResponseFail=Echec de la sécurisation de la réponse lors du traitement de JASPIC
authenticator.jaspicServerAuthContextFail=Échec d'obtention d'une instance JASPIC ServerAuthContext
authenticator.loginFail=Échec de connexion ("Login failed")
authenticator.manager=Exception lors de l'initialisation des gestionnaires d'authentification (trust managers)
authenticator.noAuthHeader=Aucun en-tête d'autorisation envoyé par le client
authenticator.notContext=Erreur de configuration: Doit être attaché à un contexte
authenticator.requestBodyTooBig=Le corps de la requête était trop grand pour être mis en cache pendant le processus d'authentification
authenticator.sessionExpired=Le temps alloué au processus de login est échu. Si vous désirez continuer, veuillez soit retourner en arrière 2 fois et recliquer le lien demandé, soit fermer et ré-ouvrir votre navigateur
authenticator.tomcatPrincipalLogoutFail=La déconnection avec l'instance de TomcatPrincipal a échoué
authenticator.unauthorized=Impossible d'authentifier avec les crédits fournis (provided credentials)
basicAuthenticator.invalidCharset=Les seules valeurs permises sont null, la chaîne vide, ou des caractères UTF-8
digestAuthenticator.cacheRemove=Une entrée valide du cache de nonce des clients a été enlevée pour faire de la place pour de nouvelles entrées, ce qui rend possible une attaque par répétition; pour éviter cela, il est possible de reduire nonceValidity ou d'augmenter nonceCacheSize; les avertissements de ce type ne se reproduiront pas avant 5 minutes
formAuthenticator.forwardErrorFail=Erreur inattendue lors de la transmission à la page d'erreur
formAuthenticator.forwardLogin=Transmission de la requête pour [{0}] faite avec la méthode [{1}] à la page de connection [{2}] du contexte [{3}] en utilisant la méthode GET
formAuthenticator.forwardLoginFail=Erreur inattendue lors de la transmission à la page de connection
formAuthenticator.noErrorPage=Aucune page d''erreur n''a été définie pour la méthode d''authentification FORM dans le contexte [{0}]
formAuthenticator.noLoginPage=Aucune page de connection n''a été définie pour la méthode d''authentification FORM dans le contexte [{0}]
singleSignOn.debug.associate=Association de la session [{1}] de l''application avec la session SSO [{0}]
singleSignOn.debug.associateFail=Le SSO n''a pu associer la session [{0}] de l''application car la session SSO [{1}] n''existe pas
singleSignOn.debug.cookieCheck=Le SSO recherche un cookie SSO.
singleSignOn.debug.cookieNotFound=Le SSO n'a pas trouvé de cookie SSO
singleSignOn.debug.deregister=Le SSO expire la session [{0}] de l''application associée à la session SSO [{1}]
singleSignOn.debug.deregisterFail=Le SSO n''a pu déenregistrer la session SSO [{0}] parce qu''elle n''est pas dans le cache
singleSignOn.debug.deregisterNone=Le SSO a désenregistré la session SSO [{0}] mais n''a trouvé aucune session d''application associée
singleSignOn.debug.hasPrincipal=Le SSO a trouvé un principal [{0}] précédemment authentifié
singleSignOn.debug.invoke=Le SSO traite la requête pour [{0}]
singleSignOn.debug.principalCheck=Le SSO recherche le Principal en cache pour la session SSO [{0}]
singleSignOn.debug.principalFound=Le SSO a trouvé en cache le Principal [{0}] avec le type d''authentification [{1}]
singleSignOn.debug.principalNotFound=Le SSO n''a pas trouvé de principal en cache, le cookie SSO de la session [{0}] est effacé
singleSignOn.debug.register=Enregistrement de la session SSO [{0}] pour l''utilisateur [{1}] avec le type d''authentification [{2}]
singleSignOn.debug.removeSession=Le SSO retire la session applicative [{0}] de la session SSO [{1}]
singleSignOn.debug.sessionLogout=Le SSO effectue une déconnection pour la session SSO [{0}] et la session [{1}] de l''application
singleSignOn.debug.sessionTimeout=Le SSO traite un timeout pour la session SSO [{0}] et la session [{1}] de l''application
singleSignOn.debug.update=Le SSO met à jour la session SSO [{0}] avec le type d''authentification [{1}]
singleSignOn.sessionExpire.contextNotFound=Le SSO n''a pu faire expirer la session [{0}] parce que le contexte n''a pas été trouvé
singleSignOn.sessionExpire.engineNull=Le SSO n''a pu faire expirer la session [{0}] parce que le moteur est null
singleSignOn.sessionExpire.hostNotFound=SSO ne peut pas expirer le session [{0}] parce l''hôte ("Host") n''a a pas été trouvé
singleSignOn.sessionExpire.managerError=Impossible d''expirer la session [{0}] parce que le Manager a lancé une exception lors de la recherche de la session
singleSignOn.sessionExpire.managerNotFound=Le SSO n''a pu faire expirer la session [{0}] parce que le gestionnaire de sessions n''a pas été trouvé
singleSignOn.sessionExpire.sessionNotFound=Impossible d''expirer la session [{0}] parce que la session n''a pas été trouvée
spnegoAuthenticator.authHeaderNoToken=L'en-tête de négociation dautorisation ("Negotiate authorization header") envoyé par le client n'incluait pas de jeton ("token")
spnegoAuthenticator.authHeaderNotNego=L'en-tête d'autorisation envoyé par le client ne commence pas par Negotiate
spnegoAuthenticator.serviceLoginFail=Impossible de se connecteur en tant que principal de service
spnegoAuthenticator.ticketValidateFail=Impossible de valider le ticket fourni par le client

View File

@@ -0,0 +1,72 @@
# 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.
authenticator.certificates=このリクエストにはクライアント認証チェーンがありません
authenticator.changeSessionId=認証時に[{0}]から[{1}]にセッションIDが変更されました。
authenticator.check.authorize=Connector から取得したユーザー名 [{0}] を正当なものとして信頼します。ユーザーのロールは Tomcat Realmから取得します。
authenticator.check.authorizeFail=Realm がユーザー[{0}]を認識しませんでした。 その名前とロールのないプリンシパルを作成します。
authenticator.check.found=既に認証された[{0}]
authenticator.check.sso=認証されていませんが、SSOセッションID [{0}]が見つかりました。 再認証を試みます。
authenticator.formlogin=フォームログインページへの無効な直接参照です
authenticator.jaspicCleanSubjectFail=JASPIC の cleanSubject が失敗しました。
authenticator.jaspicSecureResponseFail=JASPIC処理中のsecure レスポンスに失敗しました
authenticator.jaspicServerAuthContextFail=JASPIC ServerAuthContext インスタンスの取得に失敗しました。
authenticator.loginFail=ログイン失敗
authenticator.manager=トラストマネージャを初期化中の例外です
authenticator.noAuthHeader=クライアントは認証ヘッダーを送信しませんでした。
authenticator.notContext=設定エラー: コンテキストに指定しなければいけません
authenticator.requestBodyTooBig=認証処理中にリクエストボディが大きすぎてキャッシュされませんでした。
authenticator.sessionExpired=ログインプロセスに認められていた時間が過ぎました。継続したいならばバックボタンを2度押してから再度リンクを押すかブラウザを立ち上げ直してください
authenticator.tomcatPrincipalLogoutFail=TomcatPrincipal インスタンスによるログアウトが失敗しました。
authenticator.unauthorized=提供された証明書で認証できません
basicAuthenticator.invalidCharset=指定できる値は、null、空の文字列またはUTF-8です。
digestAuthenticator.cacheRemove=有効なエントリがクライアントのnonceキャッシュから削除され、新しいエントリのためのスペースが確保されました。 リプレイ攻撃が可能になりました。 リプレイ攻撃の可能性を防ぐには、nonceValidityを減らすか、nonceCacheSizeを増やしてください。 このタイプの警告は5分間表示されなくなります。
formAuthenticator.forwardErrorFail=予期せぬ異常によりエラーページへ転送します。
formAuthenticator.forwardLogin=リクエストメソッドGETを使用してコンテキスト[{3}]のページ[{2}]にメソッド[{1}]で行われた[{0}]の要求をフォワードします。
formAuthenticator.forwardLoginFail=ログインページへの転送での予期しないエラー
formAuthenticator.noErrorPage=コンテキスト[{0}]のFORM認証にエラーページが定義されていません
formAuthenticator.noLoginPage=コンテキスト[{0}]のFORM認証にログインページが定義されていません。
singleSignOn.debug.associate=SSOはアプリケーションセッション[{1}]をSSOセッション[{0}]に関連付けます
singleSignOn.debug.associateFail=SSOセッション[{1}]が存在しないため、SSOはアプリケーションセッション[{0}]を関連付けられませんでした。
singleSignOn.debug.cookieCheck=SSOがSSOクッキーをチェックします
singleSignOn.debug.cookieNotFound=SSOはSSO Cookieを検出しませんでした。
singleSignOn.debug.deregister=SSOセッション[{1}]に関連付けられたアプリケーションセッション[{0}]を期限切れにします。
singleSignOn.debug.deregisterFail=キャッシュにないため、SSOセッション[{0}]の登録を解除できませんでした。
singleSignOn.debug.deregisterNone=SSOセッション[{0}]の登録を解除しましたが、関連するアプリケーションセッションが見つかりませんでした。
singleSignOn.debug.hasPrincipal=SSOが以前に認証されたプリンシパル[{0}]を検出しました
singleSignOn.debug.invoke=[{0}]に対するSSO処理リクエスト
singleSignOn.debug.principalCheck=SSOセッションのキャッシュされたプリンシパルを探すSSO [{0}]
singleSignOn.debug.principalFound=SSO のキャッシュされたプリンシパル [{0}] を取得しました。認証タイプは [{1}] です。
singleSignOn.debug.principalNotFound=SSOはキャッシュされたプリンシパルを検出しませんでした。 セッション[{0}]のSSO Cookieを消去しています。
singleSignOn.debug.register=認証タイプ[{2}]のユーザー[{1}]のSSOセッション[{0}]を登録しているSSO
singleSignOn.debug.removeSession=SSOセッション[{1}]からのアプリケーションセッション[{0}]の削除
singleSignOn.debug.sessionLogout=SSOセッション[{0}]とアプリケーションセッション[{1}]のログアウトを処理するSSO。
singleSignOn.debug.sessionTimeout=SSOはSSOセッション[{0}]とアプリケーションセッション[{1}]のタイムアウト処理中
singleSignOn.debug.update=SSOはSSOセッション[{0}]を認証タイプ[{1}]に更新します。
singleSignOn.sessionExpire.contextNotFound=Contextが見つからないため、SSOはセッション[{0}]を期限切れにできません
singleSignOn.sessionExpire.engineNull=Engine がNullだったため、SSOはセッション[{0}]を期限切れにできません。
singleSignOn.sessionExpire.hostNotFound=ホストが見つからないため SSO セッション [{0}] を失効できません。
singleSignOn.sessionExpire.managerError=セッションを検索するときにManagerが例外をスローしたため、SSOはセッション[{0}]を期限切れにできません
singleSignOn.sessionExpire.managerNotFound=Managerが見つからなかったので、SSOはセッション[{0}]を期限切れにできません。
singleSignOn.sessionExpire.sessionNotFound=セッションが見つかりませんでしたので、SSOはセッション[{0}]を期限切れにできません。
spnegoAuthenticator.authHeaderNoToken=クライアントから受信した Negoiate 認証ヘッダにはトークンがありません。
spnegoAuthenticator.authHeaderNotNego=クライアントから受信した認証ヘッダーは Negotiate から始まっていません。
spnegoAuthenticator.serviceLoginFail=サービスプリンシパルとしてログインできません
spnegoAuthenticator.ticketValidateFail=クライアント提供のチケットの検証に失敗しました。

View File

@@ -0,0 +1,72 @@
# 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.
authenticator.certificates=이 요청에 클라인트 인증서 체인이 없습니다.
authenticator.changeSessionId=인증 처리 시, 세션 ID를 [{0}]에서 [{1}](으)로 변경했습니다.
authenticator.check.authorize=사용자 이름 [{0}]을(를) Connector로부터 얻었으며, 이는 유효한 것으로 신뢰되었습니다. Tomcat Realm으로부터, 이 사용자를 위한 역할들을 구합니다.
authenticator.check.authorizeFail=Realm이 사용자 [{0}]을(를) 인식하지 못했습니다. 해당 사용자명에 대해 아무런 역할 없이 Principal을 생성합니다.
authenticator.check.found=[{0}]은(는) 이미 인증되었습니다.
authenticator.check.sso=인증되지 않았는데, SSO 세션 ID [{0}]이(가) 발견되었습니다. 다시 인증을 시도합니다.
authenticator.formlogin=폼 로그인 페이지에 대한 유효하지 않은 직접 참조
authenticator.jaspicCleanSubjectFail=JASPIC subject를 제거하지 못했습니다.
authenticator.jaspicSecureResponseFail=JASPIC 처리 중 응답을 보안처리 하지 못했습니다.
authenticator.jaspicServerAuthContextFail=JASPIC ServerAuthContext 인스턴스를 획득하지 못했습니다.
authenticator.loginFail=로그인 실패
authenticator.manager=Trust 매니저들을 초기화하는 중 예외 발생
authenticator.noAuthHeader=클라이언트가 authorization 헤더를 보내지 않았습니다.
authenticator.notContext=설정 오류: 컨텍스트에 설정되어야만 합니다.
authenticator.requestBodyTooBig=요청의 body가 너무 커서, 인증 처리 과정에서 캐시에 저장될 수 없습니다.
authenticator.sessionExpired=로그인 처리 허용 시간이 초과되었습니다. 계속하시려면 뒤로 가기를 두번 클릭한 후, 요청했던 링크를 다시 클릭하거나, 브라우저를 닫았다가 다시 시작해야 합니다.
authenticator.tomcatPrincipalLogoutFail=TomcatPrincipal 인스턴스를 사용한 로그아웃 시도가 실패했습니다.
authenticator.unauthorized=제공된 credentials를 사용하여 인증할 수 없습니다.
basicAuthenticator.invalidCharset=허용된 값들은 오직 널, 빈 문자열, 또는 UTF-8 문자열입니다.
digestAuthenticator.cacheRemove=새로운 엔트리들을 위한 공간을 만들기 위해, client nonce cache로부터 유효한 엔트리를 제거했습니다. 리플레이 공격이 가능해진 상태입니다. 가능성 있는 리플레이 공격들을 방지하려면, nonceValidity를 감소 시키거나, nonceCacheSize를 증가 시키십시오. 더 이상 이러한 종류의 경고 메시지들은 향후 5분 동안 나오지 않을 것입니다.
formAuthenticator.forwardErrorFail=오류 페이지로 forward하는 중 예기치 않은 오류 발생
formAuthenticator.forwardLogin=메소드 [{1}]을(를) 사용한 [{0}]에 대한 요청을, 컨텍스트 [{3}]의 로그인 페이지 [{2}](으)로, GET 요청 메소드를 사용하여 forward 합니다.
formAuthenticator.forwardLoginFail=로그인 페이지로 forward하는 중 예기치 않은 오류 발생
formAuthenticator.noErrorPage=컨텍스트 [{0}]에서 폼 기반 인증을 위한 오류 페이지가 정의되지 않았습니다.
formAuthenticator.noLoginPage=컨텍스트 [{0}]에서, 폼 기반 인증을 위한 로그인 페이지가 정의되지 않았습니다.
singleSignOn.debug.associate=SSO가, 애플리케이션 세션 [{1}]을(를) SSO 세션 [{0}]와(과) 연관시킵니다.
singleSignOn.debug.associateFail=SSO 세션 [{1}]이(가) 존재하지 않기 때문에, SSO가 애플리케이션 세션 [{0}]을(를) 연관시키지 못했습니다.
singleSignOn.debug.cookieCheck=SSO가, SSO 쿠키가 존재하는지 점검합니다.
singleSignOn.debug.cookieNotFound=SSO가, SSO 쿠키를 찾지 못했습니다.
singleSignOn.debug.deregister=SSO가, SSO 세션 [{1}]와(과) 연관된 애플리케이션 세션 [{0}]을(를) 만료시킵니다.
singleSignOn.debug.deregisterFail=SSO 세션 [{0}]이(가) 캐시에 존재하지 않기 때문에, SSO가 해당 SSO 세션에 대한 등록을 제거하지 못했습니다.
singleSignOn.debug.deregisterNone=SSO가 SSO 세션 [{0}]의 등록을 제거했으나, 연관된 애플리케이션 세션들을 찾지 못했습니다.
singleSignOn.debug.hasPrincipal=SSO가 이전에 인증된 Principal [{0}]을(를) 발견했습니다.
singleSignOn.debug.invoke=SSO가 [{0}]을(를) 위해 요청을 처리합니다.
singleSignOn.debug.principalCheck=SSO 세션 [{0}]을(를) 위하여, SSO가 캐시된 Principal을 찾습니다.
singleSignOn.debug.principalFound=인증 타입이 [{1}]인, 캐시된 Principal [{0}]을(를), SSO가 발견했습니다.
singleSignOn.debug.principalNotFound=SSO가 캐시된 Principal을 찾지 못했습니다. 세션 [{0}]을(를) 위한 SSO 쿠키를 지웁니다.
singleSignOn.debug.register=사용자 [{1}]을(를) 위해, 인증 타입 [{2}]을 사용하여, SSO가 SSO 세션 [{0}]을(를) 등록합니다.
singleSignOn.debug.removeSession=SSO가 SSO 세션 [{1}](으)로부터 세션 [{0}]을(를) 제거합니다.
singleSignOn.debug.sessionLogout=SSO 세션 [{0}]와(과) 애플리케이션 세션 [{1}]을(를) 위해, SSO가 로그아웃을 처리 중
singleSignOn.debug.sessionTimeout=SSO 세션 [{0}]와(과) 애플리케이션 세션 [{1}]을(를) 위한, SSO 처리가 제한 시간 초과되었습니다.
singleSignOn.debug.update=SSO가, SSO 세션 [{0}]의 인증 타입을 [{1}](으)로 변경합니다.
singleSignOn.sessionExpire.contextNotFound=컨텍스트를 찾을 수 없기 때문에, SSO가 세션 [{0}]을(를) 만료시킬 수 없습니다.
singleSignOn.sessionExpire.engineNull=엔진이 널이기 때문에 SSO가 세션 [{0}]을(를) 만료시킬 수 없습니다.
singleSignOn.sessionExpire.hostNotFound=호스트를 찾을 수 없어서, SSO가 세션 [{0}]을(를) 만료시킬 수 없습니다.
singleSignOn.sessionExpire.managerError=세션을 찾는 동안 매니저가 예외를 발생시켜, SSO가 세션 [{0}]을(를) 만료시킬 수 없습니다.
singleSignOn.sessionExpire.managerNotFound=매니저를 찾을 수 없기 때문에, SSO가 세션 [{0}]을(를) 만료시킬 수 없습니다.
singleSignOn.sessionExpire.sessionNotFound=세션을 찾을 수 없기 때문에, SSO가 세션 [{0}]을(를) 만료시킬 수 없습니다.
spnegoAuthenticator.authHeaderNoToken=클라이언트에 의해 전송된 Negotiate authorization 헤더가 토큰을 포함하지 않았습니다.
spnegoAuthenticator.authHeaderNotNego=클라이언트가 보낸 Authorization 헤더가 Negotiate로 시작하지 않았습니다.
spnegoAuthenticator.serviceLoginFail=서비스 Principal로서 로그인 할 수 없습니다.
spnegoAuthenticator.ticketValidateFail=클라이언트에 의해 제공된 티켓이 유효한지를 확인하지 못했습니다.

View File

@@ -0,0 +1,53 @@
# 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.
authenticator.certificates=此请求中没有客户端证书链
authenticator.changeSessionId=在身份验证时, 会话 ID 从 [{0} 更改为 [{1}]
authenticator.check.found=已通过身份验证 [{0}]
authenticator.check.sso=未经过身份验证但找到了SSO会话ID [{0}]。尝试重新验证。
authenticator.formlogin=对表单登录页的直接引用无效
authenticator.jaspicCleanSubjectFail=清除 JASPIC 主题失败
authenticator.jaspicSecureResponseFail=在JASPIC处理期间无法保证响应
authenticator.jaspicServerAuthContextFail=失败的获取一个JASPIC ServerAuthContext 实例
authenticator.loginFail=登录失败
authenticator.manager=初始化信任管理器异常
authenticator.noAuthHeader=客户端未发送授权请求头
authenticator.notContext=配置错误:必须被附属于一个上下文
authenticator.requestBodyTooBig=请求正文太大,无法在身份验证过程中进行缓存
authenticator.sessionExpired=已超出登录过程所允许的时间。 如果您希望继续,则必须单击两次后退并重新单击您请求的链接或先关闭然后重新打开浏览器
authenticator.tomcatPrincipalLogoutFail=使用TomcatPrincipal实例注销失败
authenticator.unauthorized=无法使用提供的凭据进行身份验证
basicAuthenticator.invalidCharset=只允许值为null、空字符串或UTF-8
digestAuthenticator.cacheRemove=已从客户端 nonce 缓存中删除有效条目以便为新条目腾出空间。重播攻击现在是可能的。为防止重播攻击的可能性请降低nonceValidity或增加nonceCacheSize。此类型的进一步警告将被抑制5分钟。
formAuthenticator.noErrorPage=没有为上下文[{0}]中的表单身份验证定义错误页
singleSignOn.debug.associate=SSO将应用程序会话[{1}]与SSO会话[{0}]关联
singleSignOn.debug.cookieCheck=SSO检查SSO cookie
singleSignOn.debug.cookieNotFound=SSO没有找到SSO cookie
singleSignOn.debug.deregisterFail=SSO撤销登记SSO会话[{0}]失败因为缓存中不包含这个SSO会话
singleSignOn.debug.hasPrincipal=找到以前经过身份验证的主体[{0}]
singleSignOn.debug.invoke=SSO为[{0}]处理请求
singleSignOn.debug.principalCheck=SSO为SSO会话[{0}]寻找缓存的Principal
singleSignOn.debug.principalFound=SSO 找到了带着认证类型的缓存代理
singleSignOn.debug.removeSession=SSO 从 SSO session [{1}] 中删除应用程序会话 [{0}]
singleSignOn.debug.update=SSO 更新SSO 会话[{0}] 对认证 类型[{1}]
singleSignOn.sessionExpire.hostNotFound=因为 Host 丢失SSO 无法使 session [{0}] 失效
singleSignOn.sessionExpire.managerError=由于会话管理器在检索会话时抛出异常,导致单点登录无法使会话[{0}]失效
singleSignOn.sessionExpire.managerNotFound=SSO无法使会话[{0}]过期,因为找不到管理器
spnegoAuthenticator.authHeaderNoToken=客户端发送的协商授权 header 未包含 token

View File

@@ -0,0 +1,110 @@
/*
* 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;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.connector.Request;
/**
* An <b>Authenticator</b> and <b>Valve</b> implementation that checks
* only security constraints not involving user authentication.
*
* @author Craig R. McClanahan
*/
public final class NonLoginAuthenticator extends AuthenticatorBase {
// --------------------------------------------------------- Public Methods
/**
* <p>Authenticate the user making this request, based on the fact that no
* <code>login-config</code> has been defined for the container.</p>
*
* <p>This implementation means "login the user even though there is no
* self-contained way to establish a security Principal for that user".</p>
*
* <p>This method is called by the AuthenticatorBase super class to
* establish a Principal for the user BEFORE the container security
* constraints are examined, i.e. it is not yet known whether the user
* will eventually be permitted to access the requested resource.
* Therefore, it is necessary to always return <code>true</code> to
* indicate the user has not failed authentication.</p>
*
* <p>There are two cases:</p>
* <ul>
* <li>without SingleSignon: a Session instance does not yet exist
* and there is no <code>auth-method</code> to authenticate the
* user, so leave Request's Principal as null.
* Note: AuthenticatorBase will later examine the security constraints
* to determine whether the resource is accessible by a user
* without a security Principal and Role (i.e. unauthenticated).
* </li>
* <li>with SingleSignon: if the user has already authenticated via
* another container (using its own login configuration), then
* associate this Session with the SSOEntry so it inherits the
* already-established security Principal and associated Roles.
* Note: This particular session will become a full member of the
* SingleSignOnEntry Session collection and so will potentially
* keep the SSOE "alive", even if all the other properly
* authenticated Sessions expire first... until it expires too.
* </li>
* </ul>
*
* @param request Request we are processing
* @param response Response we are creating
* @return boolean to indicate whether the user is authenticated
* @exception IOException if an input/output error occurs
*/
@Override
protected boolean doAuthenticate(Request request, HttpServletResponse response)
throws IOException {
// Don't try and use SSO to authenticate since there is no auth
// configured for this web application
if (checkForCachedAuthentication(request, response, true)) {
// Save the inherited Principal in this session so it can remain
// authenticated until it expires.
if (cache) {
request.getSessionInternal(true).setPrincipal(request.getPrincipal());
}
return true;
}
// No Principal means the user is not already authenticated
// and so will not be assigned any roles. It is safe to
// to say the user is now authenticated because access to
// protected resources will only be allowed with a matching role.
// i.e. SC_FORBIDDEN (403 status) will be generated later.
if (containerLog.isDebugEnabled())
containerLog.debug("User authenticated without any roles");
return true;
}
/**
* Return the authentication method, which is vendor-specific and
* not defined by HttpServletRequest.
*/
@Override
protected String getAuthMethod() {
return "NONE";
}
}

View File

@@ -0,0 +1,103 @@
/*
* 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;
import java.io.IOException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.connector.Request;
/**
* An <b>Authenticator</b> and <b>Valve</b> implementation of authentication
* that utilizes SSL certificates to identify client users.
*
* @author Craig R. McClanahan
*/
public class SSLAuthenticator extends AuthenticatorBase {
// --------------------------------------------------------- Public Methods
/**
* Authenticate the user by checking for the existence of a certificate
* chain, validating it against the trust manager for the connector and then
* validating the user's identity against the configured Realm.
*
* @param request Request we are processing
* @param response Response we are creating
*
* @exception IOException if an input/output error occurs
*/
@Override
protected boolean doAuthenticate(Request request, HttpServletResponse response)
throws IOException {
// NOTE: We don't try to reauthenticate using any existing SSO session,
// because that will only work if the original authentication was
// BASIC or FORM, which are less secure than the CLIENT-CERT auth-type
// specified for this webapp
//
// Change to true below to allow previous FORM or BASIC authentications
// to authenticate users for this webapp
// TODO make this a configurable attribute (in SingleSignOn??)
if (checkForCachedAuthentication(request, response, false)) {
return true;
}
// Retrieve the certificate chain for this client
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Looking up certificates");
}
X509Certificate certs[] = getRequestCertificates(request);
if ((certs == null) || (certs.length < 1)) {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" No certificates included with this request");
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
sm.getString("authenticator.certificates"));
return false;
}
// Authenticate the specified certificate chain
Principal principal = context.getRealm().authenticate(certs);
if (principal == null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Realm.authenticate() returned false");
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
sm.getString("authenticator.unauthorized"));
return false;
}
// Cache the principal (if requested) and record this authentication
register(request, response, principal,
HttpServletRequest.CLIENT_CERT_AUTH, null, null);
return true;
}
@Override
protected String getAuthMethod() {
return HttpServletRequest.CLIENT_CERT_AUTH;
}
}

View File

@@ -0,0 +1,188 @@
/*
* 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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.Cookie;
import org.apache.tomcat.util.buf.ByteChunk;
/**
* Object that saves the critical information from a request so that
* form-based authentication can reproduce it once the user has been
* authenticated.
* <p>
* <b>IMPLEMENTATION NOTE</b> - It is assumed that this object is accessed
* only from the context of a single thread, so no synchronization around
* internal collection classes is performed.
*
* @author Craig R. McClanahan
*/
public final class SavedRequest {
/**
* The set of Cookies associated with this Request.
*/
private final List<Cookie> cookies = new ArrayList<>();
public void addCookie(Cookie cookie) {
cookies.add(cookie);
}
public Iterator<Cookie> getCookies() {
return cookies.iterator();
}
/**
* The set of Headers associated with this Request. Each key is a header
* name, while the value is a List containing one or more actual
* values for this header. The values are returned as an Iterator when
* you ask for them.
*/
private final Map<String, List<String>> headers = new HashMap<>();
public void addHeader(String name, String value) {
List<String> values = headers.get(name);
if (values == null) {
values = new ArrayList<>();
headers.put(name, values);
}
values.add(value);
}
public Iterator<String> getHeaderNames() {
return headers.keySet().iterator();
}
public Iterator<String> getHeaderValues(String name) {
List<String> values = headers.get(name);
if (values == null)
return Collections.emptyIterator();
else
return values.iterator();
}
/**
* The set of Locales associated with this Request.
*/
private final List<Locale> locales = new ArrayList<>();
public void addLocale(Locale locale) {
locales.add(locale);
}
public Iterator<Locale> getLocales() {
return locales.iterator();
}
/**
* The request method used on this Request.
*/
private String method = null;
public String getMethod() {
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
/**
* The query string associated with this Request.
*/
private String queryString = null;
public String getQueryString() {
return this.queryString;
}
public void setQueryString(String queryString) {
this.queryString = queryString;
}
/**
* The request URI associated with this Request.
*/
private String requestURI = null;
public String getRequestURI() {
return this.requestURI;
}
public void setRequestURI(String requestURI) {
this.requestURI = requestURI;
}
/**
* The decode request URI associated with this Request. Path parameters are
* also excluded
*/
private String decodedRequestURI = null;
public String getDecodedRequestURI() {
return this.decodedRequestURI;
}
public void setDecodedRequestURI(String decodedRequestURI) {
this.decodedRequestURI = decodedRequestURI;
}
/**
* The body of this request.
*/
private ByteChunk body = null;
public ByteChunk getBody() {
return this.body;
}
public void setBody(ByteChunk body) {
this.body = body;
}
/**
* The content type of the request, used if this is a POST.
*/
private String contentType = null;
public String getContentType() {
return this.contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
}

Some files were not shown because too many files have changed in this diff Show More