org.apache.tomcat.util.res.StringManager

Here are the examples of the java api org.apache.tomcat.util.res.StringManager taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

846 Examples 7

19 Source : Util.java
with Apache License 2.0
from wangyingjie

/**
 * Utility clreplaced for internal use only within the
 * {@link org.apache.tomcat.websocket} package.
 */
public clreplaced Util {

    private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME);

    private static final Queue<SecureRandom> randoms = new ConcurrentLinkedQueue<SecureRandom>();

    private Util() {
    // Hide default constructor
    }

    static boolean isControl(byte opCode) {
        return (opCode & 0x08) > 0;
    }

    static boolean isText(byte opCode) {
        return opCode == Constants.OPCODE_TEXT;
    }

    static boolean isContinuation(byte opCode) {
        return opCode == Constants.OPCODE_CONTINUATION;
    }

    static CloseCode getCloseCode(int code) {
        if (code > 2999 && code < 5000) {
            return CloseCodes.getCloseCode(code);
        }
        switch(code) {
            case 1000:
                return CloseCodes.NORMAL_CLOSURE;
            case 1001:
                return CloseCodes.GOING_AWAY;
            case 1002:
                return CloseCodes.PROTOCOL_ERROR;
            case 1003:
                return CloseCodes.CANNOT_ACCEPT;
            case 1004:
                // Should not be used in a close frame
                // return CloseCodes.RESERVED;
                return CloseCodes.PROTOCOL_ERROR;
            case 1005:
                // Should not be used in a close frame
                // return CloseCodes.NO_STATUS_CODE;
                return CloseCodes.PROTOCOL_ERROR;
            case 1006:
                // Should not be used in a close frame
                // return CloseCodes.CLOSED_ABNORMALLY;
                return CloseCodes.PROTOCOL_ERROR;
            case 1007:
                return CloseCodes.NOT_CONSISTENT;
            case 1008:
                return CloseCodes.VIOLATED_POLICY;
            case 1009:
                return CloseCodes.TOO_BIG;
            case 1010:
                return CloseCodes.NO_EXTENSION;
            case 1011:
                return CloseCodes.UNEXPECTED_CONDITION;
            case 1012:
                // Not in RFC6455
                // return CloseCodes.SERVICE_RESTART;
                return CloseCodes.PROTOCOL_ERROR;
            case 1013:
                // Not in RFC6455
                // return CloseCodes.TRY_AGAIN_LATER;
                return CloseCodes.PROTOCOL_ERROR;
            case 1015:
                // Should not be used in a close frame
                // return CloseCodes.TLS_HANDSHAKE_FAILURE;
                return CloseCodes.PROTOCOL_ERROR;
            default:
                return CloseCodes.PROTOCOL_ERROR;
        }
    }

    static byte[] generateMask() {
        // SecureRandom is not thread-safe so need to make sure only one thread
        // uses it at a time. In theory, the pool could grow to the same size
        // as the number of request processing threads. In reality it will be
        // a lot smaller.
        // Get a SecureRandom from the pool
        SecureRandom sr = randoms.poll();
        // If one isn't available, generate a new one
        if (sr == null) {
            try {
                sr = SecureRandom.getInstance("SHA1PRNG");
            } catch (NoSuchAlgorithmException e) {
                // Fall back to platform default
                sr = new SecureRandom();
            }
        }
        // Generate the mask
        byte[] result = new byte[4];
        sr.nextBytes(result);
        // Put the SecureRandom back in the poll
        randoms.add(sr);
        return result;
    }

    static Clreplaced<?> getMessageType(MessageHandler listener) {
        return Util.getGenericType(MessageHandler.clreplaced, listener.getClreplaced()).getClazz();
    }

    private static Clreplaced<?> getDecoderType(Clreplaced<? extends Decoder> decoder) {
        return Util.getGenericType(Decoder.clreplaced, decoder).getClazz();
    }

    static Clreplaced<?> getEncoderType(Clreplaced<? extends Encoder> encoder) {
        return Util.getGenericType(Encoder.clreplaced, encoder).getClazz();
    }

    private static <T> TypeResult getGenericType(Clreplaced<T> type, Clreplaced<? extends T> clazz) {
        // Look to see if this clreplaced implements the generic MessageHandler<>
        // interface
        // Get all the interfaces
        Type[] interfaces = clazz.getGenericInterfaces();
        for (Type iface : interfaces) {
            // Only need to check interfaces that use generics
            if (iface instanceof ParameterizedType) {
                ParameterizedType pi = (ParameterizedType) iface;
                // Look for the MessageHandler<> interface
                if (pi.getRawType() instanceof Clreplaced) {
                    if (type.isreplacedignableFrom((Clreplaced<?>) pi.getRawType())) {
                        return getTypeParameter(clazz, pi.getActualTypeArguments()[0]);
                    }
                }
            }
        }
        // Interface not found on this clreplaced. Look at the superclreplaced.
        @SuppressWarnings("unchecked")
        Clreplaced<? extends T> superClazz = (Clreplaced<? extends T>) clazz.getSuperclreplaced();
        if (superClazz == null) {
            // Finished looking up the clreplaced hierarchy without finding anything
            return null;
        }
        TypeResult superClreplacedTypeResult = getGenericType(type, superClazz);
        int dimension = superClreplacedTypeResult.getDimension();
        if (superClreplacedTypeResult.getIndex() == -1 && dimension == 0) {
            // Superclreplaced implements interface and defines explicit type for
            // MessageHandler<>
            return superClreplacedTypeResult;
        }
        if (superClreplacedTypeResult.getIndex() > -1) {
            // Superclreplaced implements interface and defines unknown type for
            // MessageHandler<>
            // Map that unknown type to the generic types defined in this clreplaced
            ParameterizedType superClreplacedType = (ParameterizedType) clazz.getGenericSuperclreplaced();
            TypeResult result = getTypeParameter(clazz, superClreplacedType.getActualTypeArguments()[superClreplacedTypeResult.getIndex()]);
            result.incrementDimension(superClreplacedTypeResult.getDimension());
            if (result.getClazz() != null && result.getDimension() > 0) {
                superClreplacedTypeResult = result;
            } else {
                return result;
            }
        }
        if (superClreplacedTypeResult.getDimension() > 0) {
            StringBuilder clreplacedName = new StringBuilder();
            for (int i = 0; i < dimension; i++) {
                clreplacedName.append('[');
            }
            clreplacedName.append('L');
            clreplacedName.append(superClreplacedTypeResult.getClazz().getCanonicalName());
            clreplacedName.append(';');
            Clreplaced<?> arrayClazz;
            try {
                arrayClazz = Clreplaced.forName(clreplacedName.toString());
            } catch (ClreplacedNotFoundException e) {
                throw new IllegalArgumentException(e);
            }
            return new TypeResult(arrayClazz, -1, 0);
        }
        // Error will be logged further up the call stack
        return null;
    }

    /*
     * For a generic parameter, return either the Clreplaced used or if the type
     * is unknown, the index for the type in definition of the clreplaced
     */
    private static TypeResult getTypeParameter(Clreplaced<?> clazz, Type argType) {
        if (argType instanceof Clreplaced<?>) {
            return new TypeResult((Clreplaced<?>) argType, -1, 0);
        } else if (argType instanceof ParameterizedType) {
            return new TypeResult((Clreplaced<?>) ((ParameterizedType) argType).getRawType(), -1, 0);
        } else if (argType instanceof GenericArrayType) {
            Type arrayElementType = ((GenericArrayType) argType).getGenericComponentType();
            TypeResult result = getTypeParameter(clazz, arrayElementType);
            result.incrementDimension(1);
            return result;
        } else {
            TypeVariable<?>[] tvs = clazz.getTypeParameters();
            for (int i = 0; i < tvs.length; i++) {
                if (tvs[i].equals(argType)) {
                    return new TypeResult(null, i, 0);
                }
            }
            return null;
        }
    }

    public static boolean isPrimitive(Clreplaced<?> clazz) {
        if (clazz.isPrimitive()) {
            return true;
        } else if (clazz.equals(Boolean.clreplaced) || clazz.equals(Byte.clreplaced) || clazz.equals(Character.clreplaced) || clazz.equals(Double.clreplaced) || clazz.equals(Float.clreplaced) || clazz.equals(Integer.clreplaced) || clazz.equals(Long.clreplaced) || clazz.equals(Short.clreplaced)) {
            return true;
        }
        return false;
    }

    public static Object coerceToType(Clreplaced<?> type, String value) {
        if (type.equals(String.clreplaced)) {
            return value;
        } else if (type.equals(boolean.clreplaced) || type.equals(Boolean.clreplaced)) {
            return Boolean.valueOf(value);
        } else if (type.equals(byte.clreplaced) || type.equals(Byte.clreplaced)) {
            return Byte.valueOf(value);
        } else if (type.equals(char.clreplaced) || type.equals(Character.clreplaced)) {
            return Character.valueOf(value.charAt(0));
        } else if (type.equals(double.clreplaced) || type.equals(Double.clreplaced)) {
            return Double.valueOf(value);
        } else if (type.equals(float.clreplaced) || type.equals(Float.clreplaced)) {
            return Float.valueOf(value);
        } else if (type.equals(int.clreplaced) || type.equals(Integer.clreplaced)) {
            return Integer.valueOf(value);
        } else if (type.equals(long.clreplaced) || type.equals(Long.clreplaced)) {
            return Long.valueOf(value);
        } else if (type.equals(short.clreplaced) || type.equals(Short.clreplaced)) {
            return Short.valueOf(value);
        } else {
            throw new IllegalArgumentException(sm.getString("util.invalidType", value, type.getName()));
        }
    }

    public static List<DecoderEntry> getDecoders(List<Clreplaced<? extends Decoder>> decoderClazzes) throws DeploymentException {
        List<DecoderEntry> result = new ArrayList<DecoderEntry>();
        if (decoderClazzes != null) {
            for (Clreplaced<? extends Decoder> decoderClazz : decoderClazzes) {
                // Need to instantiate decoder to ensure it is valid and that
                // deployment can be failed if it is not
                @SuppressWarnings("unused")
                Decoder instance;
                try {
                    instance = decoderClazz.newInstance();
                } catch (InstantiationException e) {
                    throw new DeploymentException(sm.getString("pojoMethodMapping.invalidDecoder", decoderClazz.getName()), e);
                } catch (IllegalAccessException e) {
                    throw new DeploymentException(sm.getString("pojoMethodMapping.invalidDecoder", decoderClazz.getName()), e);
                }
                DecoderEntry entry = new DecoderEntry(Util.getDecoderType(decoderClazz), decoderClazz);
                result.add(entry);
            }
        }
        return result;
    }

    static Set<MessageHandlerResult> getMessageHandlers(Clreplaced<?> target, MessageHandler listener, EndpointConfig endpointConfig, Session session) {
        // Will never be more than 2 types
        Set<MessageHandlerResult> results = new HashSet<MessageHandlerResult>(2);
        // Simple cases - handlers already accepts one of the types expected by
        // the frame handling code
        if (String.clreplaced.isreplacedignableFrom(target)) {
            MessageHandlerResult result = new MessageHandlerResult(listener, MessageHandlerResultType.TEXT);
            results.add(result);
        } else if (ByteBuffer.clreplaced.isreplacedignableFrom(target)) {
            MessageHandlerResult result = new MessageHandlerResult(listener, MessageHandlerResultType.BINARY);
            results.add(result);
        } else if (PongMessage.clreplaced.isreplacedignableFrom(target)) {
            MessageHandlerResult result = new MessageHandlerResult(listener, MessageHandlerResultType.PONG);
            results.add(result);
        // Handler needs wrapping and optional decoder to convert it to one of
        // the types expected by the frame handling code
        } else if (byte[].clreplaced.isreplacedignableFrom(target)) {
            boolean whole = MessageHandler.Whole.clreplaced.isreplacedignableFrom(listener.getClreplaced());
            MessageHandlerResult result = new MessageHandlerResult(whole ? new PojoMessageHandlerWholeBinary(listener, getOnMessageMethod(listener), session, endpointConfig, matchDecoders(target, endpointConfig, true), new Object[1], 0, true, -1, false, -1) : new PojoMessageHandlerPartialBinary(listener, getOnMessagePartialMethod(listener), session, new Object[2], 0, true, 1, -1, -1), MessageHandlerResultType.BINARY);
            results.add(result);
        } else if (InputStream.clreplaced.isreplacedignableFrom(target)) {
            MessageHandlerResult result = new MessageHandlerResult(new PojoMessageHandlerWholeBinary(listener, getOnMessageMethod(listener), session, endpointConfig, matchDecoders(target, endpointConfig, true), new Object[1], 0, true, -1, true, -1), MessageHandlerResultType.BINARY);
            results.add(result);
        } else if (Reader.clreplaced.isreplacedignableFrom(target)) {
            MessageHandlerResult result = new MessageHandlerResult(new PojoMessageHandlerWholeText(listener, getOnMessageMethod(listener), session, endpointConfig, matchDecoders(target, endpointConfig, false), new Object[1], 0, true, -1, -1), MessageHandlerResultType.TEXT);
            results.add(result);
        } else {
            // Handler needs wrapping and requires decoder to convert it to one
            // of the types expected by the frame handling code
            DecoderMatch decoderMatch = matchDecoders(target, endpointConfig);
            Method m = getOnMessageMethod(listener);
            if (decoderMatch.getBinaryDecoders().size() > 0) {
                MessageHandlerResult result = new MessageHandlerResult(new PojoMessageHandlerWholeBinary(listener, m, session, endpointConfig, decoderMatch.getBinaryDecoders(), new Object[1], 0, false, -1, false, -1), MessageHandlerResultType.BINARY);
                results.add(result);
            }
            if (decoderMatch.getTextDecoders().size() > 0) {
                MessageHandlerResult result = new MessageHandlerResult(new PojoMessageHandlerWholeText(listener, m, session, endpointConfig, decoderMatch.getTextDecoders(), new Object[1], 0, false, -1, -1), MessageHandlerResultType.TEXT);
                results.add(result);
            }
        }
        if (results.size() == 0) {
            throw new IllegalArgumentException(sm.getString("wsSession.unknownHandler", listener, target));
        }
        return results;
    }

    private static List<Clreplaced<? extends Decoder>> matchDecoders(Clreplaced<?> target, EndpointConfig endpointConfig, boolean binary) {
        DecoderMatch decoderMatch = matchDecoders(target, endpointConfig);
        if (binary) {
            if (decoderMatch.getBinaryDecoders().size() > 0) {
                return decoderMatch.getBinaryDecoders();
            }
        } else if (decoderMatch.getTextDecoders().size() > 0) {
            return decoderMatch.getTextDecoders();
        }
        return null;
    }

    private static DecoderMatch matchDecoders(Clreplaced<?> target, EndpointConfig endpointConfig) {
        DecoderMatch decoderMatch;
        try {
            List<Clreplaced<? extends Decoder>> decoders = endpointConfig.getDecoders();
            List<DecoderEntry> decoderEntries = getDecoders(decoders);
            decoderMatch = new DecoderMatch(target, decoderEntries);
        } catch (DeploymentException e) {
            throw new IllegalArgumentException(e);
        }
        return decoderMatch;
    }

    public static void parseExtensionHeader(List<Extension> extensions, String header) {
        // The relevant ABNF for the Sec-WebSocket-Extensions is as follows:
        // extension-list = 1#extension
        // extension = extension-token *( ";" extension-param )
        // extension-token = registered-token
        // registered-token = token
        // extension-param = token [ "=" (token | quoted-string) ]
        // ; When using the quoted-string syntax variant, the value
        // ; after quoted-string unescaping MUST conform to the
        // ; 'token' ABNF.
        // 
        // The limiting of parameter values to tokens or "quoted tokens" makes
        // the parsing of the header significantly simpler and allows a number
        // of short-cuts to be taken.
        // Step one, split the header into individual extensions using ',' as a
        // separator
        String[] unparsedExtensions = header.split(",");
        for (String unparsedExtension : unparsedExtensions) {
            // Step two, split the extension into the registered name and
            // parameter/value pairs using ';' as a separator
            String[] unparsedParameters = unparsedExtension.split(";");
            WsExtension extension = new WsExtension(unparsedParameters[0].trim());
            for (int i = 1; i < unparsedParameters.length; i++) {
                int equalsPos = unparsedParameters[i].indexOf('=');
                String name;
                String value;
                if (equalsPos == -1) {
                    name = unparsedParameters[i].trim();
                    value = null;
                } else {
                    name = unparsedParameters[i].substring(0, equalsPos).trim();
                    value = unparsedParameters[i].substring(equalsPos + 1).trim();
                    int len = value.length();
                    if (len > 1) {
                        if (value.charAt(0) == '\"' && value.charAt(len - 1) == '\"') {
                            value = value.substring(1, value.length() - 1);
                        }
                    }
                }
                // Make sure value doesn't contain any of the delimiters since
                // that would indicate something went wrong
                if (containsDelims(name) || containsDelims(value)) {
                    throw new IllegalArgumentException(sm.getString("util.notToken", name, value));
                }
                if (value != null && (value.indexOf(',') > -1 || value.indexOf(';') > -1 || value.indexOf('\"') > -1 || value.indexOf('=') > -1)) {
                    throw new IllegalArgumentException(sm.getString("", value));
                }
                extension.addParameter(new WsExtensionParameter(name, value));
            }
            extensions.add(extension);
        }
    }

    private static boolean containsDelims(String input) {
        if (input == null || input.length() == 0) {
            return false;
        }
        for (char c : input.toCharArray()) {
            switch(c) {
                case ',':
                case ';':
                case '\"':
                case '=':
                    return true;
                default:
            }
        }
        return false;
    }

    private static Method getOnMessageMethod(MessageHandler listener) {
        try {
            return listener.getClreplaced().getMethod("onMessage", Object.clreplaced);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException(sm.getString("util.invalidMessageHandler"), e);
        } catch (SecurityException e) {
            throw new IllegalArgumentException(sm.getString("util.invalidMessageHandler"), e);
        }
    }

    private static Method getOnMessagePartialMethod(MessageHandler listener) {
        try {
            return listener.getClreplaced().getMethod("onMessage", Object.clreplaced, Boolean.TYPE);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException(sm.getString("util.invalidMessageHandler"), e);
        } catch (SecurityException e) {
            throw new IllegalArgumentException(sm.getString("util.invalidMessageHandler"), e);
        }
    }

    public static clreplaced DecoderMatch {

        private final List<Clreplaced<? extends Decoder>> textDecoders = new ArrayList<Clreplaced<? extends Decoder>>();

        private final List<Clreplaced<? extends Decoder>> binaryDecoders = new ArrayList<Clreplaced<? extends Decoder>>();

        private final Clreplaced<?> target;

        public DecoderMatch(Clreplaced<?> target, List<DecoderEntry> decoderEntries) {
            this.target = target;
            for (DecoderEntry decoderEntry : decoderEntries) {
                if (decoderEntry.getClazz().isreplacedignableFrom(target)) {
                    if (Binary.clreplaced.isreplacedignableFrom(decoderEntry.getDecoderClazz())) {
                        binaryDecoders.add(decoderEntry.getDecoderClazz());
                    // willDecode() method means this decoder may or may not
                    // decode a message so need to carry on checking for
                    // other matches
                    } else if (BinaryStream.clreplaced.isreplacedignableFrom(decoderEntry.getDecoderClazz())) {
                        binaryDecoders.add(decoderEntry.getDecoderClazz());
                        // Stream decoders have to process the message so no
                        // more decoders can be matched
                        break;
                    } else if (Text.clreplaced.isreplacedignableFrom(decoderEntry.getDecoderClazz())) {
                        textDecoders.add(decoderEntry.getDecoderClazz());
                    // willDecode() method means this decoder may or may not
                    // decode a message so need to carry on checking for
                    // other matches
                    } else if (TextStream.clreplaced.isreplacedignableFrom(decoderEntry.getDecoderClazz())) {
                        textDecoders.add(decoderEntry.getDecoderClazz());
                        // Stream decoders have to process the message so no
                        // more decoders can be matched
                        break;
                    } else {
                        throw new IllegalArgumentException(sm.getString("util.unknownDecoderType"));
                    }
                }
            }
        }

        public List<Clreplaced<? extends Decoder>> getTextDecoders() {
            return textDecoders;
        }

        public List<Clreplaced<? extends Decoder>> getBinaryDecoders() {
            return binaryDecoders;
        }

        public Clreplaced<?> getTarget() {
            return target;
        }

        public boolean hasMatches() {
            return (textDecoders.size() > 0) || (binaryDecoders.size() > 0);
        }
    }

    private static clreplaced TypeResult {

        private final Clreplaced<?> clazz;

        private final int index;

        private int dimension;

        public TypeResult(Clreplaced<?> clazz, int index, int dimension) {
            this.clazz = clazz;
            this.index = index;
            this.dimension = dimension;
        }

        public Clreplaced<?> getClazz() {
            return clazz;
        }

        public int getIndex() {
            return index;
        }

        public int getDimension() {
            return dimension;
        }

        public void incrementDimension(int inc) {
            dimension += inc;
        }
    }
}

19 Source : TransformationFactory.java
with Apache License 2.0
from wangyingjie

public clreplaced TransformationFactory {

    private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME);

    private static final TransformationFactory factory = new TransformationFactory();

    private TransformationFactory() {
    // Hide default constructor
    }

    public static TransformationFactory getInstance() {
        return factory;
    }

    public Transformation create(String name, List<List<Extension.Parameter>> preferences, boolean isServer) {
        if (PerMessageDeflate.NAME.equals(name)) {
            return PerMessageDeflate.negotiate(preferences, isServer);
        }
        if (Constants.ALLOW_UNSUPPORTED_EXTENSIONS) {
            return null;
        } else {
            throw new IllegalArgumentException(sm.getString("transformerFactory.unsupportedExtension", name));
        }
    }
}

19 Source : WsFrameServer.java
with Apache License 2.0
from wangyingjie

public clreplaced WsFrameServer extends WsFrameBase {

    private static final Log log = LogFactory.getLog(WsFrameServer.clreplaced);

    private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME);

    private final AbstractServletInputStream sis;

    private final Object connectionReadLock = new Object();

    public WsFrameServer(AbstractServletInputStream sis, WsSession wsSession, Transformation transformation) {
        super(wsSession, transformation);
        this.sis = sis;
    }

    /**
     * Called when there is data in the ServletInputStream to process.
     */
    public void onDataAvailable() throws IOException {
        if (log.isDebugEnabled()) {
            log.debug("wsFrameServer.onDataAvailable");
        }
        synchronized (connectionReadLock) {
            while (isOpen() && sis.isReady()) {
                // Fill up the input buffer with as much data as we can
                int read = sis.read(inputBuffer, writePos, inputBuffer.length - writePos);
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("wsFrameServer.bytesRead", Integer.toString(read)));
                }
                if (read == 0) {
                    return;
                }
                if (read == -1) {
                    throw new EOFException();
                }
                writePos += read;
                processInputBuffer();
            }
        }
    }

    @Override
    protected boolean isMasked() {
        // Data is from the client so it should be masked
        return true;
    }

    @Override
    protected Transformation getTransformation() {
        // Overridden to make it visible to other clreplacedes in this package
        return super.getTransformation();
    }

    @Override
    protected Log getLog() {
        return log;
    }
}

19 Source : UpgradeUtil.java
with Apache License 2.0
from wangyingjie

public clreplaced UpgradeUtil {

    private static final StringManager sm = StringManager.getManager(org.apache.tomcat.websocket.server.Constants.PACKAGE_NAME);

    private static final byte[] WS_ACCEPT = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes(StandardCharsets.ISO_8859_1);

    private UpgradeUtil() {
    // Utility clreplaced. Hide default constructor.
    }

    /**
     * Checks to see if this is an HTTP request that includes a valid upgrade
     * request to web socket.
     * <p>
     * Note: RFC 2616 does not limit HTTP upgrade to GET requests but the Java
     *       WebSocket spec 1.0, section 8.2 implies such a limitation and RFC
     *       6455 section 4.1 requires that a WebSocket Upgrade uses GET.
     */
    public static boolean isWebSocketUpgradeRequest(ServletRequest request, ServletResponse response) {
        return ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) && headerContainsToken((HttpServletRequest) request, Constants.UPGRADE_HEADER_NAME, Constants.UPGRADE_HEADER_VALUE) && "GET".equals(((HttpServletRequest) request).getMethod()));
    }

    public static void doUpgrade(WsServerContainer sc, HttpServletRequest req, HttpServletResponse resp, ServerEndpointConfig sec, Map<String, String> pathParams) throws ServletException, IOException {
        // Validate the rest of the headers and reject the request if that
        // validation fails
        String key;
        String subProtocol = null;
        if (!headerContainsToken(req, Constants.CONNECTION_HEADER_NAME, Constants.CONNECTION_HEADER_VALUE)) {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        if (!headerContainsToken(req, Constants.WS_VERSION_HEADER_NAME, Constants.WS_VERSION_HEADER_VALUE)) {
            resp.setStatus(426);
            resp.setHeader(Constants.WS_VERSION_HEADER_NAME, Constants.WS_VERSION_HEADER_VALUE);
            return;
        }
        key = req.getHeader(Constants.WS_KEY_HEADER_NAME);
        if (key == null) {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        // Origin check
        String origin = req.getHeader(Constants.ORIGIN_HEADER_NAME);
        if (!sec.getConfigurator().checkOrigin(origin)) {
            resp.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        // Sub-protocols
        List<String> subProtocols = getTokensFromHeader(req, Constants.WS_PROTOCOL_HEADER_NAME);
        subProtocol = sec.getConfigurator().getNegotiatedSubprotocol(sec.getSubprotocols(), subProtocols);
        // Extensions
        // Should normally only be one header but handle the case of multiple
        // headers
        List<Extension> extensionsRequested = new ArrayList<Extension>();
        Enumeration<String> extHeaders = req.getHeaders(Constants.WS_EXTENSIONS_HEADER_NAME);
        while (extHeaders.hasMoreElements()) {
            Util.parseExtensionHeader(extensionsRequested, extHeaders.nextElement());
        }
        // Negotiation phase 1. By default this simply filters out the
        // extensions that the server does not support but applications could
        // use a custom configurator to do more than this.
        List<Extension> installedExtensions = null;
        if (sec.getExtensions().size() == 0) {
            installedExtensions = Constants.INSTALLED_EXTENSIONS;
        } else {
            installedExtensions = new ArrayList<Extension>();
            installedExtensions.addAll(sec.getExtensions());
            installedExtensions.addAll(Constants.INSTALLED_EXTENSIONS);
        }
        List<Extension> negotiatedExtensionsPhase1 = sec.getConfigurator().getNegotiatedExtensions(installedExtensions, extensionsRequested);
        // Negotiation phase 2. Create the Transformations that will be applied
        // to this connection. Note than an extension may be dropped at this
        // point if the client has requested a configuration that the server is
        // unable to support.
        List<Transformation> transformations = createTransformations(negotiatedExtensionsPhase1);
        List<Extension> negotiatedExtensionsPhase2;
        if (transformations.isEmpty()) {
            negotiatedExtensionsPhase2 = Collections.emptyList();
        } else {
            negotiatedExtensionsPhase2 = new ArrayList<Extension>(transformations.size());
            for (Transformation t : transformations) {
                negotiatedExtensionsPhase2.add(t.getExtensionResponse());
            }
        }
        // Build the transformation pipeline
        Transformation transformation = null;
        StringBuilder responseHeaderExtensions = new StringBuilder();
        boolean first = true;
        for (Transformation t : transformations) {
            if (first) {
                first = false;
            } else {
                responseHeaderExtensions.append(',');
            }
            append(responseHeaderExtensions, t.getExtensionResponse());
            if (transformation == null) {
                transformation = t;
            } else {
                transformation.setNext(t);
            }
        }
        // Now we have the full pipeline, validate the use of the RSV bits.
        if (transformation != null && !transformation.validateRsvBits(0)) {
            throw new ServletException(sm.getString("upgradeUtil.incompatibleRsv"));
        }
        // If we got this far, all is good. Accept the connection.
        resp.setHeader(Constants.UPGRADE_HEADER_NAME, Constants.UPGRADE_HEADER_VALUE);
        resp.setHeader(Constants.CONNECTION_HEADER_NAME, Constants.CONNECTION_HEADER_VALUE);
        resp.setHeader(HandshakeResponse.SEC_WEBSOCKET_ACCEPT, getWebSocketAccept(key));
        if (subProtocol != null && subProtocol.length() > 0) {
            // RFC6455 4.2.2 explicitly states "" is not valid here
            resp.setHeader(Constants.WS_PROTOCOL_HEADER_NAME, subProtocol);
        }
        if (!transformations.isEmpty()) {
            resp.setHeader(Constants.WS_EXTENSIONS_HEADER_NAME, responseHeaderExtensions.toString());
        }
        WsHandshakeRequest wsRequest = new WsHandshakeRequest(req, pathParams);
        WsHandshakeResponse wsResponse = new WsHandshakeResponse();
        WsPerSessionServerEndpointConfig perSessionServerEndpointConfig = new WsPerSessionServerEndpointConfig(sec);
        sec.getConfigurator().modifyHandshake(perSessionServerEndpointConfig, wsRequest, wsResponse);
        wsRequest.finished();
        // Add any additional headers
        for (Entry<String, List<String>> entry : wsResponse.getHeaders().entrySet()) {
            for (String headerValue : entry.getValue()) {
                resp.addHeader(entry.getKey(), headerValue);
            }
        }
        Endpoint ep;
        try {
            Clreplaced<?> clazz = sec.getEndpointClreplaced();
            if (Endpoint.clreplaced.isreplacedignableFrom(clazz)) {
                ep = (Endpoint) sec.getConfigurator().getEndpointInstance(clazz);
            } else {
                ep = new PojoEndpointServer();
                // Need to make path params available to POJO
                perSessionServerEndpointConfig.getUserProperties().put(PojoEndpointServer.POJO_PATH_PARAM_KEY, pathParams);
            }
        } catch (InstantiationException e) {
            throw new ServletException(e);
        }
        // Small hack until the Servlet API provides a way to do this.
        ServletRequest inner = req;
        // Unwrap the request
        while (inner instanceof ServletRequestWrapper) {
            inner = ((ServletRequestWrapper) inner).getRequest();
        }
        if (inner instanceof RequestFacade) {
            WsHttpUpgradeHandler wsHandler = ((RequestFacade) inner).upgrade(WsHttpUpgradeHandler.clreplaced);
            wsHandler.preInit(ep, perSessionServerEndpointConfig, sc, wsRequest, negotiatedExtensionsPhase2, subProtocol, transformation, pathParams, req.isSecure());
        } else {
            throw new ServletException("Upgrade failed");
        }
    }

    private static List<Transformation> createTransformations(List<Extension> negotiatedExtensions) {
        TransformationFactory factory = TransformationFactory.getInstance();
        LinkedHashMap<String, List<List<Extension.Parameter>>> extensionPreferences = new LinkedHashMap<String, List<List<Extension.Parameter>>>();
        // Result will likely be smaller than this
        List<Transformation> result = new ArrayList<Transformation>(negotiatedExtensions.size());
        for (Extension extension : negotiatedExtensions) {
            List<List<Extension.Parameter>> preferences = extensionPreferences.get(extension.getName());
            if (preferences == null) {
                preferences = new ArrayList<List<Extension.Parameter>>();
                extensionPreferences.put(extension.getName(), preferences);
            }
            preferences.add(extension.getParameters());
        }
        for (Map.Entry<String, List<List<Extension.Parameter>>> entry : extensionPreferences.entrySet()) {
            Transformation transformation = factory.create(entry.getKey(), entry.getValue(), true);
            if (transformation != null) {
                result.add(transformation);
            }
        }
        return result;
    }

    private static void append(StringBuilder sb, Extension extension) {
        if (extension == null || extension.getName() == null || extension.getName().length() == 0) {
            return;
        }
        sb.append(extension.getName());
        for (Extension.Parameter p : extension.getParameters()) {
            sb.append(';');
            sb.append(p.getName());
            if (p.getValue() != null) {
                sb.append('=');
                sb.append(p.getValue());
            }
        }
    }

    /*
     * This only works for tokens. Quoted strings need more sophisticated
     * parsing.
     */
    private static boolean headerContainsToken(HttpServletRequest req, String headerName, String target) {
        Enumeration<String> headers = req.getHeaders(headerName);
        while (headers.hasMoreElements()) {
            String header = headers.nextElement();
            String[] tokens = header.split(",");
            for (String token : tokens) {
                if (target.equalsIgnoreCase(token.trim())) {
                    return true;
                }
            }
        }
        return false;
    }

    /*
     * This only works for tokens. Quoted strings need more sophisticated
     * parsing.
     */
    private static List<String> getTokensFromHeader(HttpServletRequest req, String headerName) {
        List<String> result = new ArrayList<String>();
        Enumeration<String> headers = req.getHeaders(headerName);
        while (headers.hasMoreElements()) {
            String header = headers.nextElement();
            String[] tokens = header.split(",");
            for (String token : tokens) {
                result.add(token.trim());
            }
        }
        return result;
    }

    private static String getWebSocketAccept(String key) {
        byte[] digest = ConcurrentMessageDigest.digestSHA1(key.getBytes(StandardCharsets.ISO_8859_1), WS_ACCEPT);
        return Base64.encodeBase64String(digest);
    }
}

19 Source : PojoEndpointServer.java
with Apache License 2.0
from wangyingjie

/**
 * Wrapper clreplaced for instances of POJOs annotated with
 * {@link javax.websocket.server.ServerEndpoint} so they appear as standard
 * {@link javax.websocket.Endpoint} instances.
 */
public clreplaced PojoEndpointServer extends PojoEndpointBase {

    private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME);

    public static final String POJO_PATH_PARAM_KEY = "org.apache.tomcat.websocket.pojo.PojoEndpoint.pathParams";

    public static final String POJO_METHOD_MAPPING_KEY = "org.apache.tomcat.websocket.pojo.PojoEndpoint.methodMapping";

    @Override
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        ServerEndpointConfig sec = (ServerEndpointConfig) endpointConfig;
        Object pojo;
        try {
            pojo = sec.getConfigurator().getEndpointInstance(sec.getEndpointClreplaced());
        } catch (InstantiationException e) {
            throw new IllegalArgumentException(sm.getString("pojoEndpointServer.getPojoInstanceFail", sec.getEndpointClreplaced().getName()), e);
        }
        setPojo(pojo);
        @SuppressWarnings("unchecked")
        Map<String, String> pathParameters = (Map<String, String>) sec.getUserProperties().get(POJO_PATH_PARAM_KEY);
        setPathParameters(pathParameters);
        PojoMethodMapping methodMapping = (PojoMethodMapping) sec.getUserProperties().get(POJO_METHOD_MAPPING_KEY);
        setMethodMapping(methodMapping);
        doOnOpen(session, endpointConfig);
    }
}

19 Source : JSSESocketFactory.java
with Apache License 2.0
from wangyingjie

/**
 * SSL server socket factory. It <b>requires</b> a valid RSA key and
 * JSSE.<br/>
 * keytool -genkey -alias tomcat -keyalg RSA</br>
 * Use "changeit" as preplacedword (this is the default we use).
 *
 * @author Harish Prabandham
 * @author Costin Manolache
 * @author Stefan Freyr Stefansson
 * @author EKR -- renamed to JSSESocketFactory
 * @author Jan Luehe
 * @author Bill Barker
 */
public clreplaced JSSESocketFactory implements ServerSocketFactory, Sreplacedil {

    private static final org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.clreplaced);

    private static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.net.jsse.res");

    // Defaults - made public where re-used
    private static final String defaultProtocol = Constants.SSL_PROTO_TLS;

    private static final String defaultKeystoreType = "JKS";

    private static final String defaultKeystoreFile = System.getProperty("user.home") + "/.keystore";

    private static final int defaultSessionCacheSize = 0;

    private static final int defaultSessionTimeout = 86400;

    private static final String ALLOW_ALL_SUPPORTED_CIPHERS = "ALL";

    public static final String DEFAULT_KEY_Preplaced = "changeit";

    private AbstractEndpoint<?> endpoint;

    private final boolean rfc5746Supported;

    private final String[] defaultServerProtocols;

    private final String[] defaultServerCipherSuites;

    protected SSLServerSocketFactory sslProxy = null;

    protected String[] enabledCiphers;

    protected String[] enabledProtocols;

    protected boolean allowUnsafeLegacyRenegotiation = false;

    /**
     * Flag to state that we require client authentication.
     */
    protected boolean requireClientAuth = false;

    /**
     * Flag to state that we would like client authentication.
     */
    protected boolean wantClientAuth = false;

    public JSSESocketFactory(AbstractEndpoint<?> endpoint) {
        this.endpoint = endpoint;
        String sslProtocol = endpoint.getSslProtocol();
        if (sslProtocol == null) {
            sslProtocol = defaultProtocol;
        }
        SSLContext context;
        try {
            context = SSLContext.getInstance(sslProtocol);
            context.init(null, null, null);
        } catch (NoSuchAlgorithmException e) {
            // This is fatal for the connector so throw an exception to prevent
            // it from starting
            throw new IllegalArgumentException(e);
        } catch (KeyManagementException e) {
            // This is fatal for the connector so throw an exception to prevent
            // it from starting
            throw new IllegalArgumentException(e);
        }
        // Supported cipher suites aren't accessible directly from the
        // SSLContext so use the SSL server socket factory
        SSLServerSocketFactory ssf = context.getServerSocketFactory();
        String[] supportedCiphers = ssf.getSupportedCipherSuites();
        boolean found = false;
        for (String cipher : supportedCiphers) {
            if ("TLS_EMPTY_RENEGOTIATION_INFO_SCSV".equals(cipher)) {
                found = true;
                break;
            }
        }
        rfc5746Supported = found;
        // There is no standard way to determine the default protocols and
        // cipher suites so create a server socket to see what the defaults are
        SSLServerSocket socket;
        try {
            socket = (SSLServerSocket) ssf.createServerSocket();
        } catch (IOException e) {
            // This is very likely to be fatal but there is a slim chance that
            // the JSSE implementation just doesn't like creating unbound
            // sockets so allow the code to proceed.
            defaultServerCipherSuites = new String[0];
            defaultServerProtocols = new String[0];
            log.warn(sm.getString("jsse.noDefaultCiphers", endpoint.getName()));
            log.warn(sm.getString("jsse.noDefaultProtocols", endpoint.getName()));
            return;
        }
        try {
            // Many of the default ciphers supported by older JRE versions are
            // now considered insecure. This code attempts to filter them out
            List<String> filteredCiphers = new ArrayList<String>();
            for (String cipher : socket.getEnabledCipherSuites()) {
                // Remove export ciphers - FREAK
                if (cipher.toUpperCase(Locale.ENGLISH).contains("EXP")) {
                    log.debug(sm.getString("jsse.excludeDefaultCipher", cipher));
                    continue;
                }
                // Remove DES ciphers
                if (cipher.toUpperCase(Locale.ENGLISH).contains("_DES_")) {
                    log.debug(sm.getString("jsse.excludeDefaultCipher", cipher));
                    continue;
                }
                // Remove RC4 ciphers
                if (cipher.toUpperCase(Locale.ENGLISH).contains("_RC4_")) {
                    log.debug(sm.getString("jsse.excludeDefaultCipher", cipher));
                    continue;
                }
                // Remove DHE ciphers unless running on Java 8 or above
                if (!JreCompat.isJre8Available() && cipher.toUpperCase(Locale.ENGLISH).contains("_DHE_")) {
                    log.debug(sm.getString("jsse.excludeDefaultCipher", cipher));
                    continue;
                }
                // Remove kRSA ciphers when running on Java 7 or above. Can't
                // remove them for Java 6 since they are likely to be the only
                // ones left
                if (JreCompat.isJre7Available() && (cipher.toUpperCase(Locale.ENGLISH).startsWith("TLS_RSA_") || cipher.toUpperCase(Locale.ENGLISH).startsWith("SSL_RSA_"))) {
                    log.debug(sm.getString("jsse.excludeDefaultCipher", cipher));
                    continue;
                }
                filteredCiphers.add(cipher);
            }
            defaultServerCipherSuites = filteredCiphers.toArray(new String[filteredCiphers.size()]);
            if (defaultServerCipherSuites.length == 0) {
                log.warn(sm.getString("jsse.noDefaultCiphers", endpoint.getName()));
            }
            // Filter out all the SSL protocols (SSLv2 and SSLv3) from the defaults
            // since they are no longer considered secure
            List<String> filteredProtocols = new ArrayList<String>();
            for (String protocol : socket.getEnabledProtocols()) {
                if (protocol.toUpperCase(Locale.ENGLISH).contains("SSL")) {
                    log.debug(sm.getString("jsse.excludeDefaultProtocol", protocol));
                    continue;
                }
                filteredProtocols.add(protocol);
            }
            defaultServerProtocols = filteredProtocols.toArray(new String[filteredProtocols.size()]);
            if (defaultServerProtocols.length == 0) {
                log.warn(sm.getString("jsse.noDefaultProtocols", endpoint.getName()));
            }
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                log.warn(sm.getString("jsse.exceptionOnClose"), e);
            }
        }
    }

    @Override
    public ServerSocket createSocket(int port) throws IOException {
        init();
        ServerSocket socket = sslProxy.createServerSocket(port);
        initServerSocket(socket);
        return socket;
    }

    @Override
    public ServerSocket createSocket(int port, int backlog) throws IOException {
        init();
        ServerSocket socket = sslProxy.createServerSocket(port, backlog);
        initServerSocket(socket);
        return socket;
    }

    @Override
    public ServerSocket createSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
        init();
        ServerSocket socket = sslProxy.createServerSocket(port, backlog, ifAddress);
        initServerSocket(socket);
        return socket;
    }

    @Override
    public Socket acceptSocket(ServerSocket socket) throws IOException {
        SSLSocket asock = null;
        try {
            asock = (SSLSocket) socket.accept();
        } catch (SSLException e) {
            throw new SocketException("SSL handshake error" + e.toString());
        }
        return asock;
    }

    @Override
    public void handshake(Socket sock) throws IOException {
        // We do getSession instead of startHandshake() so we can call this multiple times
        SSLSession session = ((SSLSocket) sock).getSession();
        if (session.getCipherSuite().equals("SSL_NULL_WITH_NULL_NULL"))
            throw new IOException("SSL handshake failed. Ciper suite in SSL Session is SSL_NULL_WITH_NULL_NULL");
        if (!allowUnsafeLegacyRenegotiation && !rfc5746Supported) {
            // Prevent further handshakes by removing all cipher suites
            ((SSLSocket) sock).setEnabledCipherSuites(new String[0]);
        }
    }

    @Override
    public String[] getEnableableCiphers(SSLContext context) {
        String requestedCiphersStr = endpoint.getCiphers();
        if (ALLOW_ALL_SUPPORTED_CIPHERS.equals(requestedCiphersStr)) {
            return context.getSupportedSSLParameters().getCipherSuites();
        }
        if ((requestedCiphersStr == null) || (requestedCiphersStr.trim().length() == 0)) {
            return defaultServerCipherSuites;
        }
        List<String> requestedCiphers = new ArrayList<String>();
        for (String rc : requestedCiphersStr.split(",")) {
            final String cipher = rc.trim();
            if (cipher.length() > 0) {
                requestedCiphers.add(cipher);
            }
        }
        if (requestedCiphers.isEmpty()) {
            return defaultServerCipherSuites;
        }
        List<String> ciphers = new ArrayList<String>(requestedCiphers);
        String[] supportedCipherSuiteArray = context.getSupportedSSLParameters().getCipherSuites();
        // The IBM JRE will accept cipher suites names SSL_xxx or TLS_xxx but
        // only returns the SSL_xxx form for supported cipher suites. Therefore
        // need to filter the requested cipher suites using both forms with an
        // IBM JRE.
        List<String> supportedCipherSuiteList;
        if (JreVendor.IS_IBM_JVM) {
            supportedCipherSuiteList = new ArrayList<String>(supportedCipherSuiteArray.length * 2);
            for (String name : supportedCipherSuiteArray) {
                supportedCipherSuiteList.add(name);
                if (name.startsWith("SSL")) {
                    supportedCipherSuiteList.add("TLS" + name.substring(3));
                }
            }
        } else {
            supportedCipherSuiteList = Arrays.asList(supportedCipherSuiteArray);
        }
        ciphers.retainAll(supportedCipherSuiteList);
        if (ciphers.isEmpty()) {
            log.warn(sm.getString("jsse.requested_ciphers_not_supported", requestedCiphersStr));
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("jsse.enableable_ciphers", ciphers));
            if (ciphers.size() != requestedCiphers.size()) {
                List<String> skipped = new ArrayList<String>(requestedCiphers);
                skipped.removeAll(ciphers);
                log.debug(sm.getString("jsse.unsupported_ciphers", skipped));
            }
        }
        return ciphers.toArray(new String[ciphers.size()]);
    }

    /*
     * Gets the SSL server's keystore preplacedword.
     */
    protected String getKeystorePreplacedword() {
        String keystorePreplaced = endpoint.getKeystorePreplaced();
        if (keystorePreplaced == null) {
            keystorePreplaced = endpoint.getKeyPreplaced();
        }
        if (keystorePreplaced == null) {
            keystorePreplaced = DEFAULT_KEY_Preplaced;
        }
        return keystorePreplaced;
    }

    /*
     * Gets the SSL server's keystore.
     */
    protected KeyStore getKeystore(String type, String provider, String preplaced) throws IOException {
        String keystoreFile = endpoint.getKeystoreFile();
        if (keystoreFile == null)
            keystoreFile = defaultKeystoreFile;
        return getStore(type, provider, keystoreFile, preplaced);
    }

    /*
     * Gets the SSL server's truststore.
     */
    protected KeyStore getTrustStore(String keystoreType, String keystoreProvider) throws IOException {
        KeyStore trustStore = null;
        String truststoreFile = endpoint.getTruststoreFile();
        if (truststoreFile == null) {
            truststoreFile = System.getProperty("javax.net.ssl.trustStore");
        }
        if (log.isDebugEnabled()) {
            log.debug("Truststore = " + truststoreFile);
        }
        String truststorePreplacedword = endpoint.getTruststorePreplaced();
        if (truststorePreplacedword == null) {
            truststorePreplacedword = System.getProperty("javax.net.ssl.trustStorePreplacedword");
        }
        if (log.isDebugEnabled()) {
            log.debug("TrustPreplaced = " + truststorePreplacedword);
        }
        String truststoreType = endpoint.getTruststoreType();
        if (truststoreType == null) {
            truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
        }
        if (truststoreType == null) {
            truststoreType = keystoreType;
        }
        if (log.isDebugEnabled()) {
            log.debug("trustType = " + truststoreType);
        }
        String truststoreProvider = endpoint.getTruststoreProvider();
        if (truststoreProvider == null) {
            truststoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider");
        }
        if (truststoreProvider == null) {
            truststoreProvider = keystoreProvider;
        }
        if (log.isDebugEnabled()) {
            log.debug("trustProvider = " + truststoreProvider);
        }
        if (truststoreFile != null) {
            try {
                trustStore = getStore(truststoreType, truststoreProvider, truststoreFile, truststorePreplacedword);
            } catch (IOException ioe) {
                Throwable cause = ioe.getCause();
                if (cause instanceof UnrecoverableKeyException) {
                    // Log a warning we had a preplacedword issue
                    log.warn(sm.getString("jsse.invalid_truststore_preplacedword"), cause);
                    // Re-try
                    trustStore = getStore(truststoreType, truststoreProvider, truststoreFile, null);
                } else {
                    // Something else went wrong - re-throw
                    throw ioe;
                }
            }
        }
        return trustStore;
    }

    /*
     * Gets the key- or truststore with the specified type, path, and preplacedword.
     */
    private KeyStore getStore(String type, String provider, String path, String preplaced) throws IOException {
        KeyStore ks = null;
        InputStream istream = null;
        try {
            if (provider == null) {
                ks = KeyStore.getInstance(type);
            } else {
                ks = KeyStore.getInstance(type, provider);
            }
            if (!("PKCS11".equalsIgnoreCase(type) || "".equalsIgnoreCase(path))) {
                istream = ConfigFileLoader.getInputStream(path);
            }
            char[] storePreplaced = null;
            if (preplaced != null && !"".equals(preplaced)) {
                storePreplaced = preplaced.toCharArray();
            }
            ks.load(istream, storePreplaced);
        } catch (FileNotFoundException fnfe) {
            log.error(sm.getString("jsse.keystore_load_failed", type, path, fnfe.getMessage()), fnfe);
            throw fnfe;
        } catch (IOException ioe) {
            // May be expected when working with a trust store
            // Re-throw. Caller will catch and log as required
            throw ioe;
        } catch (Exception ex) {
            String msg = sm.getString("jsse.keystore_load_failed", type, path, ex.getMessage());
            log.error(msg, ex);
            throw new IOException(msg);
        } finally {
            if (istream != null) {
                try {
                    istream.close();
                } catch (IOException ioe) {
                // Do nothing
                }
            }
        }
        return ks;
    }

    /**
     * Reads the keystore and initializes the SSL socket factory.
     */
    void init() throws IOException {
        try {
            String clientAuthStr = endpoint.getClientAuth();
            if ("true".equalsIgnoreCase(clientAuthStr) || "yes".equalsIgnoreCase(clientAuthStr)) {
                requireClientAuth = true;
            } else if ("want".equalsIgnoreCase(clientAuthStr)) {
                wantClientAuth = true;
            }
            SSLContext context = createSSLContext();
            context.init(getKeyManagers(), getTrustManagers(), null);
            // Configure SSL session cache
            SSLSessionContext sessionContext = context.getServerSessionContext();
            if (sessionContext != null) {
                configureSessionContext(sessionContext);
            }
            // create proxy
            sslProxy = context.getServerSocketFactory();
            // Determine which cipher suites to enable
            enabledCiphers = getEnableableCiphers(context);
            enabledProtocols = getEnableableProtocols(context);
            allowUnsafeLegacyRenegotiation = "true".equals(endpoint.getAllowUnsafeLegacyRenegotiation());
            // Check the SSL config is OK
            checkConfig();
        } catch (Exception e) {
            if (e instanceof IOException)
                throw (IOException) e;
            throw new IOException(e.getMessage(), e);
        }
    }

    @Override
    public SSLContext createSSLContext() throws Exception {
        // SSL protocol variant (e.g., TLS, SSL v3, etc.)
        String protocol = endpoint.getSslProtocol();
        if (protocol == null) {
            protocol = defaultProtocol;
        }
        SSLContext context = SSLContext.getInstance(protocol);
        return context;
    }

    @Override
    public KeyManager[] getKeyManagers() throws Exception {
        String keystoreType = endpoint.getKeystoreType();
        if (keystoreType == null) {
            keystoreType = defaultKeystoreType;
        }
        String algorithm = endpoint.getAlgorithm();
        if (algorithm == null) {
            algorithm = KeyManagerFactory.getDefaultAlgorithm();
        }
        return getKeyManagers(keystoreType, endpoint.getKeystoreProvider(), algorithm, endpoint.getKeyAlias());
    }

    @Override
    public TrustManager[] getTrustManagers() throws Exception {
        String truststoreType = endpoint.getTruststoreType();
        if (truststoreType == null) {
            truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
        }
        if (truststoreType == null) {
            truststoreType = endpoint.getKeystoreType();
        }
        if (truststoreType == null) {
            truststoreType = defaultKeystoreType;
        }
        String algorithm = endpoint.getTruststoreAlgorithm();
        if (algorithm == null) {
            algorithm = TrustManagerFactory.getDefaultAlgorithm();
        }
        return getTrustManagers(truststoreType, endpoint.getKeystoreProvider(), algorithm);
    }

    @Override
    public void configureSessionContext(SSLSessionContext sslSessionContext) {
        int sessionCacheSize;
        if (endpoint.getSessionCacheSize() != null) {
            sessionCacheSize = Integer.parseInt(endpoint.getSessionCacheSize());
        } else {
            sessionCacheSize = defaultSessionCacheSize;
        }
        int sessionTimeout;
        if (endpoint.getSessionTimeout() != null) {
            sessionTimeout = Integer.parseInt(endpoint.getSessionTimeout());
        } else {
            sessionTimeout = defaultSessionTimeout;
        }
        sslSessionContext.setSessionCacheSize(sessionCacheSize);
        sslSessionContext.setSessionTimeout(sessionTimeout);
    }

    /**
     * Gets the initialized key managers.
     */
    protected KeyManager[] getKeyManagers(String keystoreType, String keystoreProvider, String algorithm, String keyAlias) throws Exception {
        KeyManager[] kms = null;
        String keystorePreplaced = getKeystorePreplacedword();
        KeyStore ks = getKeystore(keystoreType, keystoreProvider, keystorePreplaced);
        if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
            throw new IOException(sm.getString("jsse.alias_no_key_entry", keyAlias));
        }
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
        String keyPreplaced = endpoint.getKeyPreplaced();
        if (keyPreplaced == null) {
            keyPreplaced = keystorePreplaced;
        }
        kmf.init(ks, keyPreplaced.toCharArray());
        kms = kmf.getKeyManagers();
        if (keyAlias != null) {
            String alias = keyAlias;
            if (JSSESocketFactory.defaultKeystoreType.equals(keystoreType)) {
                alias = alias.toLowerCase(Locale.ENGLISH);
            }
            for (int i = 0; i < kms.length; i++) {
                kms[i] = new JSSEKeyManager((X509KeyManager) kms[i], alias);
            }
        }
        return kms;
    }

    /**
     * Gets the initialized trust managers.
     */
    protected TrustManager[] getTrustManagers(String keystoreType, String keystoreProvider, String algorithm) throws Exception {
        String crlf = endpoint.getCrlFile();
        String clreplacedName = endpoint.getTrustManagerClreplacedName();
        if (clreplacedName != null && clreplacedName.length() > 0) {
            ClreplacedLoader clreplacedLoader = getClreplaced().getClreplacedLoader();
            Clreplaced<?> clazz = clreplacedLoader.loadClreplaced(clreplacedName);
            if (!(TrustManager.clreplaced.isreplacedignableFrom(clazz))) {
                throw new InstantiationException(sm.getString("jsse.invalidTrustManagerClreplacedName", clreplacedName));
            }
            Object trustManagerObject = clazz.newInstance();
            TrustManager trustManager = (TrustManager) trustManagerObject;
            return new TrustManager[] { trustManager };
        }
        TrustManager[] tms = null;
        KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider);
        if (trustStore != null || endpoint.getTrustManagerClreplacedName() != null) {
            if (crlf == null) {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
                tmf.init(trustStore);
                tms = tmf.getTrustManagers();
            } else {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
                CertPathParameters params = getParameters(algorithm, crlf, trustStore);
                ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params);
                tmf.init(mfp);
                tms = tmf.getTrustManagers();
            }
        }
        return tms;
    }

    /**
     * Return the initialization parameters for the TrustManager.
     * Currently, only the default <code>PKIX</code> is supported.
     *
     * @param algorithm The algorithm to get parameters for.
     * @param crlf The path to the CRL file.
     * @param trustStore The configured TrustStore.
     * @return The parameters including the CRLs and TrustStore.
     */
    protected CertPathParameters getParameters(String algorithm, String crlf, KeyStore trustStore) throws Exception {
        CertPathParameters params = null;
        if ("PKIX".equalsIgnoreCase(algorithm)) {
            PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore, new X509CertSelector());
            Collection<? extends CRL> crls = getCRLs(crlf);
            CertStoreParameters csp = new CollectionCertStoreParameters(crls);
            CertStore store = CertStore.getInstance("Collection", csp);
            xparams.addCertStore(store);
            xparams.setRevocationEnabled(true);
            String trustLength = endpoint.getTrustMaxCertLength();
            if (trustLength != null) {
                try {
                    xparams.setMaxPathLength(Integer.parseInt(trustLength));
                } catch (Exception ex) {
                    log.warn("Bad maxCertLength: " + trustLength);
                }
            }
            params = xparams;
        } else {
            throw new CRLException("CRLs not supported for type: " + algorithm);
        }
        return params;
    }

    /**
     * Load the collection of CRLs.
     */
    protected Collection<? extends CRL> getCRLs(String crlf) throws IOException, CRLException, CertificateException {
        Collection<? extends CRL> crls = null;
        InputStream is = null;
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            is = ConfigFileLoader.getInputStream(crlf);
            crls = cf.generateCRLs(is);
        } catch (IOException iex) {
            throw iex;
        } catch (CRLException crle) {
            throw crle;
        } catch (CertificateException ce) {
            throw ce;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception ex) {
                // Ignore
                }
            }
        }
        return crls;
    }

    @Override
    public String[] getEnableableProtocols(SSLContext context) {
        String[] requestedProtocols = endpoint.getSslEnabledProtocolsArray();
        if ((requestedProtocols == null) || (requestedProtocols.length == 0)) {
            return defaultServerProtocols;
        }
        List<String> protocols = new ArrayList<String>(Arrays.asList(requestedProtocols));
        protocols.retainAll(Arrays.asList(context.getSupportedSSLParameters().getProtocols()));
        if (protocols.isEmpty()) {
            log.warn(sm.getString("jsse.requested_protocols_not_supported", Arrays.asList(requestedProtocols)));
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("jsse.enableable_protocols", protocols));
            if (protocols.size() != requestedProtocols.length) {
                List<String> skipped = new ArrayList<String>(Arrays.asList(requestedProtocols));
                skipped.removeAll(protocols);
                log.debug(sm.getString("jsse.unsupported_protocols", skipped));
            }
        }
        return protocols.toArray(new String[protocols.size()]);
    }

    /**
     * Configure Client authentication for this version of JSSE.  The
     * JSSE included in Java 1.4 supports the 'want' value.  Prior
     * versions of JSSE will treat 'want' as 'false'.
     * @param socket the SSLServerSocket
     */
    protected void configureClientAuth(SSLServerSocket socket) {
        if (wantClientAuth) {
            socket.setWantClientAuth(wantClientAuth);
        } else {
            socket.setNeedClientAuth(requireClientAuth);
        }
    }

    /**
     * Configures SSLEngine to honor cipher suites ordering based upon
     * endpoint configuration.
     *
     * @throws InvalidAlgorithmParameterException If the runtime JVM doesn't
     *         support this setting.
     */
    protected void configureUseServerCipherSuitesOrder(SSLServerSocket socket) {
        String useServerCipherSuitesOrderStr = endpoint.getUseServerCipherSuitesOrder().trim();
        // Only use this feature if the user explicitly requested its use.
        if (!"".equals(useServerCipherSuitesOrderStr)) {
            boolean useServerCipherSuitesOrder = ("true".equalsIgnoreCase(useServerCipherSuitesOrderStr) || "yes".equalsIgnoreCase(useServerCipherSuitesOrderStr));
            JreCompat jreCompat = JreCompat.getInstance();
            jreCompat.setUseServerCipherSuitesOrder(socket, useServerCipherSuitesOrder);
        }
    }

    /**
     * Configures the given SSL server socket with the requested cipher suites,
     * protocol versions, and need for client authentication
     */
    private void initServerSocket(ServerSocket ssocket) {
        SSLServerSocket socket = (SSLServerSocket) ssocket;
        socket.setEnabledCipherSuites(enabledCiphers);
        socket.setEnabledProtocols(enabledProtocols);
        // we don't know if client auth is needed -
        // after parsing the request we may re-handshake
        configureClientAuth(socket);
        configureUseServerCipherSuitesOrder(socket);
    }

    /**
     * Checks that the certificate is compatible with the enabled cipher suites.
     * If we don't check now, the JIoEndpoint can enter a nasty logging loop.
     * See bug 45528.
     */
    private void checkConfig() throws IOException {
        // Create an unbound server socket
        ServerSocket socket = sslProxy.createServerSocket();
        initServerSocket(socket);
        try {
            // Set the timeout to 1ms as all we care about is if it throws an
            // SSLException on accept.
            socket.setSoTimeout(1);
            socket.accept();
        // Will never get here - no client can connect to an unbound port
        } catch (SSLException ssle) {
            // SSL configuration is invalid. Possibly cert doesn't match ciphers
            IOException ioe = new IOException(sm.getString("jsse.invalid_ssl_conf", ssle.getMessage()));
            ioe.initCause(ssle);
            throw ioe;
        } catch (Exception e) {
        /*
             * Possible ways of getting here
             * socket.accept() throws a SecurityException
             * socket.setSoTimeout() throws a SocketException
             * socket.accept() throws some other exception (after a JDK change)
             *      In these cases the test won't work so carry on - essentially
             *      the behaviour before this patch
             * socket.accept() throws a SocketTimeoutException
             *      In this case all is well so carry on
             */
        } finally {
            // Should be open here but just in case
            if (!socket.isClosed()) {
                socket.close();
            }
        }
    }
}

19 Source : MimeHeaders.java
with Apache License 2.0
from wangyingjie

/* XXX XXX XXX Need a major rewrite  !!!!
 */
/**
 * This clreplaced is used to contain standard internet message headers,
 * used for SMTP (RFC822) and HTTP (RFC2068) messages as well as for
 * MIME (RFC 2045) applications such as transferring typed data and
 * grouping related items in multipart message bodies.
 *
 * <P> Message headers, as specified in RFC822, include a field name
 * and a field body.  Order has no semantic significance, and several
 * fields with the same name may exist.  However, most fields do not
 * (and should not) exist more than once in a header.
 *
 * <P> Many kinds of field body must conform to a specified syntax,
 * including the standard parenthesized comment syntax.  This clreplaced
 * supports only two simple syntaxes, for dates and integers.
 *
 * <P> When processing headers, care must be taken to handle the case of
 * multiple same-name fields correctly.  The values of such fields are
 * only available as strings.  They may be accessed by index (treating
 * the header as an array of fields), or by name (returning an array
 * of string values).
 */
/* Headers are first parsed and stored in the order they are
   received. This is based on the fact that most servlets will not
   directly access all headers, and most headers are single-valued.
   ( the alternative - a hash or similar data structure - will add
   an overhead that is not needed in most cases )

   Apache seems to be using a similar method for storing and manipulating
   headers.

   Future enhancements:
   - hash the headers the first time a header is requested ( i.e. if the
   servlet needs direct access to headers).
   - scan "common" values ( length, cookies, etc ) during the parse
   ( addHeader hook )

*/
/**
 *  Memory-efficient repository for Mime Headers. When the object is recycled, it
 *  will keep the allocated headers[] and all the MimeHeaderField - no GC is generated.
 *
 *  For input headers it is possible to use the MessageByte for Fields - so no GC
 *  will be generated.
 *
 *  The only garbage is generated when using the String for header names/values -
 *  this can't be avoided when the servlet calls header methods, but is easy
 *  to avoid inside tomcat. The goal is to use _only_ MessageByte-based Fields,
 *  and reduce to 0 the memory overhead of tomcat.
 *
 *  TODO:
 *  XXX one-buffer parsing - for http ( other protocols don't need that )
 *  XXX remove unused methods
 *  XXX External enumerations, with 0 GC.
 *  XXX use HeaderName ID
 *
 * @author [email protected]
 * @author James Todd [[email protected]]
 * @author Costin Manolache
 * @author kevin seguin
 */
public clreplaced MimeHeaders {

    /**
     * Initial size - should be == average number of headers per request
     *  XXX  make it configurable ( fine-tuning of web-apps )
     */
    public static final int DEFAULT_HEADER_SIZE = 8;

    private static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.http");

    /**
     * The header fields.
     */
    private MimeHeaderField[] headers = new MimeHeaderField[DEFAULT_HEADER_SIZE];

    /**
     * The current number of header fields.
     */
    private int count;

    /**
     * The limit on the number of header fields.
     */
    private int limit = -1;

    /**
     * Creates a new MimeHeaders object using a default buffer size.
     */
    public MimeHeaders() {
    // NO-OP
    }

    /**
     * Set limit on the number of header fields.
     */
    public void setLimit(int limit) {
        this.limit = limit;
        if (limit > 0 && headers.length > limit && count < limit) {
            // shrink header list array
            MimeHeaderField[] tmp = new MimeHeaderField[limit];
            System.arraycopy(headers, 0, tmp, 0, count);
            headers = tmp;
        }
    }

    /**
     * Clears all header fields.
     */
    // [seguin] added for consistency -- most other objects have recycle().
    public void recycle() {
        clear();
    }

    /**
     * Clears all header fields.
     */
    public void clear() {
        for (int i = 0; i < count; i++) {
            headers[i].recycle();
        }
        count = 0;
    }

    /**
     * EXPENSIVE!!!  only for debugging.
     */
    @Override
    public String toString() {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        pw.println("=== MimeHeaders ===");
        Enumeration<String> e = names();
        while (e.hasMoreElements()) {
            String n = e.nextElement();
            Enumeration<String> ev = values(n);
            while (ev.hasMoreElements()) {
                pw.print(n);
                pw.print(" = ");
                pw.println(ev.nextElement());
            }
        }
        return sw.toString();
    }

    // -------------------- Idx access to headers ----------
    /**
     * Returns the current number of header fields.
     */
    public int size() {
        return count;
    }

    /**
     * Returns the Nth header name, or null if there is no such header.
     * This may be used to iterate through all header fields.
     */
    public MessageBytes getName(int n) {
        return n >= 0 && n < count ? headers[n].getName() : null;
    }

    /**
     * Returns the Nth header value, or null if there is no such header.
     * This may be used to iterate through all header fields.
     */
    public MessageBytes getValue(int n) {
        return n >= 0 && n < count ? headers[n].getValue() : null;
    }

    /**
     * Find the index of a header with the given name.
     */
    public int findHeader(String name, int starting) {
        // We can use a hash - but it's not clear how much
        // benefit you can get - there is an  overhead
        // and the number of headers is small (4-5 ?)
        // Another problem is that we'll pay the overhead
        // of constructing the hashtable
        // A custom search tree may be better
        for (int i = starting; i < count; i++) {
            if (headers[i].getName().equalsIgnoreCase(name)) {
                return i;
            }
        }
        return -1;
    }

    // -------------------- --------------------
    /**
     * Returns an enumeration of strings representing the header field names.
     * Field names may appear multiple times in this enumeration, indicating
     * that multiple fields with that name exist in this header.
     */
    public Enumeration<String> names() {
        return new NamesEnumerator(this);
    }

    public Enumeration<String> values(String name) {
        return new ValuesEnumerator(this, name);
    }

    // -------------------- Adding headers --------------------
    /**
     * Adds a partially constructed field to the header.  This
     * field has not had its name or value initialized.
     */
    private MimeHeaderField createHeader() {
        if (limit > -1 && count >= limit) {
            throw new IllegalStateException(sm.getString("headers.maxCountFail", Integer.valueOf(limit)));
        }
        MimeHeaderField mh;
        int len = headers.length;
        if (count >= len) {
            // expand header list array
            int newLength = count * 2;
            if (limit > 0 && newLength > limit) {
                newLength = limit;
            }
            MimeHeaderField[] tmp = new MimeHeaderField[newLength];
            System.arraycopy(headers, 0, tmp, 0, len);
            headers = tmp;
        }
        if ((mh = headers[count]) == null) {
            headers[count] = mh = new MimeHeaderField();
        }
        count++;
        return mh;
    }

    /**
     * Create a new named header , return the MessageBytes
     *        container for the new value
     */
    public MessageBytes addValue(String name) {
        MimeHeaderField mh = createHeader();
        mh.getName().setString(name);
        return mh.getValue();
    }

    /**
     * Create a new named header using un-translated byte[].
     *        The conversion to chars can be delayed until
     *        encoding is known.
     */
    public MessageBytes addValue(byte[] b, int startN, int len) {
        MimeHeaderField mhf = createHeader();
        mhf.getName().setBytes(b, startN, len);
        return mhf.getValue();
    }

    /**
     * Create a new named header using translated char[].
     */
    public MessageBytes addValue(char[] c, int startN, int len) {
        MimeHeaderField mhf = createHeader();
        mhf.getName().setChars(c, startN, len);
        return mhf.getValue();
    }

    /**
     * Allow "set" operations -
     *        return a MessageBytes container for the
     *        header value ( existing header or new
     *        if this .
     */
    public MessageBytes setValue(String name) {
        for (int i = 0; i < count; i++) {
            if (headers[i].getName().equalsIgnoreCase(name)) {
                for (int j = i + 1; j < count; j++) {
                    if (headers[j].getName().equalsIgnoreCase(name)) {
                        removeHeader(j--);
                    }
                }
                return headers[i].getValue();
            }
        }
        MimeHeaderField mh = createHeader();
        mh.getName().setString(name);
        return mh.getValue();
    }

    // -------------------- Getting headers --------------------
    /**
     * Finds and returns a header field with the given name.  If no such
     * field exists, null is returned.  If more than one such field is
     * in the header, an arbitrary one is returned.
     */
    public MessageBytes getValue(String name) {
        for (int i = 0; i < count; i++) {
            if (headers[i].getName().equalsIgnoreCase(name)) {
                return headers[i].getValue();
            }
        }
        return null;
    }

    /**
     * Finds and returns a unique header field with the given name. If no such
     * field exists, null is returned. If the specified header field is not
     * unique then an {@link IllegalArgumentException} is thrown.
     */
    public MessageBytes getUniqueValue(String name) {
        MessageBytes result = null;
        for (int i = 0; i < count; i++) {
            if (headers[i].getName().equalsIgnoreCase(name)) {
                if (result == null) {
                    result = headers[i].getValue();
                } else {
                    throw new IllegalArgumentException();
                }
            }
        }
        return result;
    }

    // bad shortcut - it'll convert to string ( too early probably,
    // encoding is guessed very late )
    public String getHeader(String name) {
        MessageBytes mh = getValue(name);
        return mh != null ? mh.toString() : null;
    }

    // -------------------- Removing --------------------
    /**
     * Removes a header field with the specified name.  Does nothing
     * if such a field could not be found.
     * @param name the name of the header field to be removed
     */
    public void removeHeader(String name) {
        // XXX
        // warning: rather sticky code; heavily tuned
        for (int i = 0; i < count; i++) {
            if (headers[i].getName().equalsIgnoreCase(name)) {
                removeHeader(i--);
            }
        }
    }

    /**
     * reset and swap with last header
     * @param idx the index of the header to remove.
     */
    private void removeHeader(int idx) {
        MimeHeaderField mh = headers[idx];
        mh.recycle();
        headers[idx] = headers[count - 1];
        headers[count - 1] = mh;
        count--;
    }
}

19 Source : ConfigFileLoader.java
with Apache License 2.0
from wangyingjie

/**
 * This clreplaced is used to obtain {@link InputStream}s for configuration files
 * from a given location String. This allows greater flexibility than these
 * files having to be loaded directly from a file system.
 */
public clreplaced ConfigFileLoader {

    private static final StringManager sm = StringManager.getManager(ConfigFileLoader.clreplaced.getPackage().getName());

    private static final File CATALINA_BASE_FILE;

    private static final URI CATALINA_BASE_URI;

    static {
        String catalinaBase = System.getProperty("catalina.base");
        if (catalinaBase != null) {
            CATALINA_BASE_FILE = new File(catalinaBase);
            CATALINA_BASE_URI = CATALINA_BASE_FILE.toURI();
        } else {
            CATALINA_BASE_FILE = null;
            CATALINA_BASE_URI = null;
        }
    }

    private ConfigFileLoader() {
    // Utility clreplaced. Hide the default constructor.
    }

    /**
     * Load the resource from the specified location.
     *
     * @param location The location for the resource of interest. The location
     *                 may be a URL or a file path. Relative paths will be
     *                 resolved against CATALINA_BASE.
     *
     * @return The InputStream for the given resource. The caller is responsible
     *         for closing this stream when it is no longer used.
     *
     * @throws IOException If an InputStream cannot be created using the
     *                     provided location
     */
    public static InputStream getInputStream(String location) throws IOException {
        // Absolute URIs will be left alone
        // Relative files will be resolved relative to catalina base
        // Absolute files will be converted to URIs
        // Location was originally always a file before URI support was added so
        // try file first.
        // First guess, an absolute file path
        File file = new File(location);
        if (!file.isAbsolute()) {
            // Second guess, a file path relative to CATALINA_BASE
            file = new File(CATALINA_BASE_FILE, location);
        }
        if (file.isFile()) {
            return new FileInputStream(file);
        }
        // Third and final guess, a URI
        URI uri;
        if (CATALINA_BASE_URI != null) {
            uri = CATALINA_BASE_URI.resolve(location);
        } else {
            uri = URI.create(location);
        }
        // Obtain the input stream we need
        try {
            return uri.toURL().openStream();
        } catch (IllegalArgumentException e) {
            throw new IOException(sm.getString("configFileLoader.cannotObtainURL", location), e);
        }
    }
}

19 Source : JreCompat.java
with Apache License 2.0
from wangyingjie

/**
 * This is the base implementation clreplaced for JRE compatibility and provides an
 * implementation based on Java 6. Sub-clreplacedes may extend this clreplaced and provide
 * alternative implementations for later JRE versions
 */
public clreplaced JreCompat {

    private static final JreCompat instance;

    private static StringManager sm = StringManager.getManager(JreCompat.clreplaced.getPackage().getName());

    private static final boolean jre9Available;

    private static final boolean jre8Available;

    private static final boolean jre7Available;

    static {
        // This is Tomcat 7 with a minimum Java version of Java 6. The latest
        // Java version the optional features require is Java 9.
        // Look for the highest supported JVM first
        if (Jre9Compat.isSupported()) {
            instance = new Jre9Compat();
            jre9Available = true;
            jre8Available = true;
            jre7Available = true;
        } else if (Jre8Compat.isSupported()) {
            instance = new Jre8Compat();
            jre9Available = false;
            jre8Available = true;
            jre7Available = true;
        } else if (Jre7Compat.isSupported()) {
            instance = new Jre7Compat();
            jre9Available = false;
            jre8Available = false;
            jre7Available = true;
        } else {
            instance = new JreCompat();
            jre9Available = false;
            jre8Available = false;
            jre7Available = false;
        }
    }

    public static JreCompat getInstance() {
        return instance;
    }

    // Java 6 implementation of Java 7 methods
    public static boolean isJre7Available() {
        return jre7Available;
    }

    public Locale forLanguageTag(String languageTag) {
        // Extract the language and country for this entry
        String language = null;
        String country = null;
        String variant = null;
        int dash = languageTag.indexOf('-');
        if (dash < 0) {
            language = languageTag;
            country = "";
            variant = "";
        } else {
            language = languageTag.substring(0, dash);
            country = languageTag.substring(dash + 1);
            int vDash = country.indexOf('-');
            if (vDash > 0) {
                String cTemp = country.substring(0, vDash);
                variant = country.substring(vDash + 1);
                country = cTemp;
            } else {
                variant = "";
            }
        }
        if (!isAlpha(language) || !isAlpha(country) || !isAlpha(variant)) {
            return null;
        }
        return new Locale(language, country, variant);
    }

    private static final boolean isAlpha(String value) {
        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);
            if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
                return false;
            }
        }
        return true;
    }

    // Java 6 implementation of Java 8 methods
    public static boolean isJre8Available() {
        return jre8Available;
    }

    @SuppressWarnings("unused")
    public void setUseServerCipherSuitesOrder(SSLServerSocket socket, boolean useCipherSuitesOrder) {
        throw new UnsupportedOperationException(sm.getString("jreCompat.noServerCipherSuiteOrder"));
    }

    @SuppressWarnings("unused")
    public void setUseServerCipherSuitesOrder(SSLEngine engine, boolean useCipherSuitesOrder) {
        throw new UnsupportedOperationException(sm.getString("jreCompat.noServerCipherSuiteOrder"));
    }

    // Java 6 implementation of Java 9 methods
    public static boolean isJre9Available() {
        return jre9Available;
    }

    /**
     * Test if the provided exception is an instance of
     * java.lang.reflect.InaccessibleObjectException.
     *
     * @param e The exception to test
     *
     * @return {@code true} if the exception is an instance of
     *         InaccessibleObjectException, otherwise {@code false}
     */
    public boolean isInstanceOfInaccessibleObjectException(Exception e) {
        // Exception does not exist prior to Java 9
        return false;
    }
}

19 Source : AbstractServletOutputStream.java
with Apache License 2.0
from wangyingjie

/**
 * Implements the new Servlet 3.1 methods for {@link ServletOutputStream}.
 */
public abstract clreplaced AbstractServletOutputStream extends ServletOutputStream {

    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    // Used to ensure that isReady() and onWritePossible() have a consistent
    // view of buffer and fireListener when determining if the listener should
    // fire.
    private final Object fireListenerLock = new Object();

    // Used to ensure that only one thread writes to the socket at a time and
    // that buffer is consistently updated with any unwritten data after the
    // write. Note it is not necessary to hold this lock when checking if buffer
    // contains data but, depending on how the result is used, some form of
    // synchronization may be required (see fireListenerLock for an example).
    private final Object writeLock = new Object();

    private volatile boolean closeRequired = false;

    // Start in blocking-mode
    private volatile WriteListener listener = null;

    // Guarded by fireListenerLock
    private volatile boolean fireListener = false;

    private volatile ClreplacedLoader applicationLoader = null;

    // Writes guarded by writeLock
    private volatile byte[] buffer;

    private volatile int bufferPos;

    private volatile int bufferLimit;

    private final int asyncWriteBufferSize;

    public AbstractServletOutputStream(int asyncWriteBufferSize) {
        this.asyncWriteBufferSize = asyncWriteBufferSize;
        buffer = new byte[asyncWriteBufferSize];
    }

    /**
     * New Servlet 3.1 method.
     */
    public final boolean isReady() {
        if (listener == null) {
            throw new IllegalStateException(sm.getString("upgrade.sos.canWrite.ise"));
        }
        // Make sure isReady() and onWritePossible() have a consistent view of
        // buffer and fireListener when determining if the listener should fire
        synchronized (fireListenerLock) {
            boolean result = (bufferLimit == 0);
            fireListener = !result;
            return result;
        }
    }

    /**
     * New Servlet 3.1 method.
     */
    public final void setWriteListener(WriteListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException(sm.getString("upgrade.sos.writeListener.null"));
        }
        if (this.listener != null) {
            throw new IllegalArgumentException(sm.getString("upgrade.sos.writeListener.set"));
        }
        this.listener = listener;
        this.applicationLoader = Thread.currentThread().getContextClreplacedLoader();
    }

    protected final boolean isCloseRequired() {
        return closeRequired;
    }

    @Override
    public void write(int b) throws IOException {
        synchronized (writeLock) {
            preWriteChecks();
            writeInternal(new byte[] { (byte) b }, 0, 1);
        }
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        synchronized (writeLock) {
            preWriteChecks();
            writeInternal(b, off, len);
        }
    }

    @Override
    public void close() throws IOException {
        closeRequired = true;
        doClose();
    }

    private void preWriteChecks() {
        if (bufferLimit != 0) {
            throw new IllegalStateException(sm.getString("upgrade.sis.write.ise"));
        }
    }

    /**
     * Must hold writeLock to call this method.
     */
    private void writeInternal(byte[] b, int off, int len) throws IOException {
        if (listener == null) {
            // Simple case - blocking IO
            doWrite(true, b, off, len);
        } else {
            // Non-blocking IO
            // If the non-blocking read does not complete, doWrite() will add
            // the socket back into the poller. The poller may trigger a new
            // write event before this method has finished updating buffer. The
            // writeLock sync makes sure that buffer is updated before the next
            // write executes.
            int written = doWrite(false, b, off, len);
            if (written < len) {
                if (b == buffer) {
                    // This is a partial write of the existing buffer. Just
                    // increment the current position
                    bufferPos += written;
                } else {
                    // This is a new partial write
                    int bytesLeft = len - written;
                    if (bytesLeft > buffer.length) {
                        buffer = new byte[bytesLeft];
                    } else if (bytesLeft < asyncWriteBufferSize && buffer.length > asyncWriteBufferSize) {
                        buffer = new byte[asyncWriteBufferSize];
                    }
                    bufferPos = 0;
                    bufferLimit = bytesLeft;
                    System.arraycopy(b, off + written, buffer, bufferPos, bufferLimit);
                }
            } else {
                bufferLimit = 0;
            }
        }
    }

    protected final void onWritePossible() throws IOException {
        try {
            synchronized (writeLock) {
                if (bufferLimit > 0) {
                    writeInternal(buffer, bufferPos, bufferLimit - bufferPos);
                }
            }
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            onError(t);
            if (t instanceof IOException) {
                throw (IOException) t;
            } else {
                throw new IOException(t);
            }
        }
        // Make sure isReady() and onWritePossible() have a consistent view of
        // buffer and fireListener when determining if the listener should fire
        boolean fire = false;
        synchronized (fireListenerLock) {
            if (bufferLimit == 0 && fireListener) {
                fireListener = false;
                fire = true;
            }
        }
        if (fire) {
            Thread thread = Thread.currentThread();
            ClreplacedLoader originalClreplacedLoader = thread.getContextClreplacedLoader();
            try {
                thread.setContextClreplacedLoader(applicationLoader);
                listener.onWritePossible();
            } finally {
                thread.setContextClreplacedLoader(originalClreplacedLoader);
            }
        }
    }

    protected final void onError(Throwable t) {
        if (listener == null) {
            return;
        }
        Thread thread = Thread.currentThread();
        ClreplacedLoader originalClreplacedLoader = thread.getContextClreplacedLoader();
        try {
            thread.setContextClreplacedLoader(applicationLoader);
            listener.onError(t);
        } finally {
            thread.setContextClreplacedLoader(originalClreplacedLoader);
        }
    }

    /**
     * Abstract method to be overridden by concrete implementations. The base
     * clreplaced will ensure that there are no concurrent calls to this method for
     * the same socket by ensuring that the writeLock is held when making any
     * calls to this method.
     */
    protected abstract int doWrite(boolean block, byte[] b, int off, int len) throws IOException;

    protected abstract void doFlush() throws IOException;

    protected abstract void doClose() throws IOException;
}

19 Source : AsyncStateMachine.java
with Apache License 2.0
from wangyingjie

/**
 * Manages the state transitions for async requests.
 *
 * <pre>
 * The internal states that are used are:
 * DISPATCHED       - Standard request. Not in Async mode.
 * STARTING         - ServletRequest.startAsync() has been called but the
 *                    request in which that call was made has not finished
 *                    processing.
 * STARTED          - ServletRequest.startAsync() has been called and the
 *                    request in which that call was made has finished
 *                    processing.
 * MUST_COMPLETE    - ServletRequest.startAsync() followed by complete() have
 *                    been called during a single Servlet.service() method. The
 *                    complete() will be processed as soon as the request
 *                    finishes.
 * COMPLETE_PENDING - ServletRequest.startAsync() has been called and before the
 *                    request in which that call was had finished processing,
 *                    complete() was called for a non-container thread. The
 *                    complete() will be processed as soon as the request
 *                    finishes. This is different to MUST_COMPLETE because of
 *                    differences required to avoid race conditions during error
 *                    handling.
 * COMPLETING       - The call to complete() was made once the request was in
 *                    the STARTED state. May or may not be triggered by a
 *                    container thread - depends if start(Runnable) was used.
 * TIMING_OUT       - The async request has timed out and is waiting for a call
 *                    to complete(). If that isn't made, the error state will
 *                    entered.
 * MUST_DISPATCH    - ServletRequest.startAsync() followed by dispatch() have
 *                    been called during a single Servlet.service() method. The
 *                    dispatch() will be processed as soon as the request
 *                    finishes.
 * DISPATCH_PENDING - ServletRequest.startAsync() has been called and before the
 *                    request in which that call was had finished processing,
 *                    dispatch() was called for a non-container thread. The
 *                    dispatch() will be processed as soon as the request
 *                    finishes. This is different to MUST_DISPATCH because of
 *                    differences required to avoid race conditions during error
 *                    handling.
 * DISPATCHING      - The dispatch is being processed.
 * ERROR            - Something went wrong.
 *
 * |----------------->------|
 * |                       \|/
 * |   |----------<-------ERROR<---------------------------<-------------------------------|
 * |   |      complete() /|\/|\\                                                           |
 * |   |                  |  |  \                                                          |
 * |   |    |----->-------|  |   \----------->----------|                                  |
 * |   |    |                |                          |dispatch()                        |
 * |   |    |                |                         \|/                                 |
 * |   |    |                |          |--|timeout()   |                                  |
 * |   |    |     post()     |          | \|/           |     post()                       |
 * |   |    |    |---------- | -->DISPATCHED<---------- | --------------COMPLETING<-----|  |
 * |   |    |    |           |   /|\/|\ |               |                | /|\ /|\      |  |
 * |   |    |    |    |--->- | ---|  |  |startAsync()   |       timeout()|--|   |       |  |
 * |   |    ^    ^    |      |       |  |               |                       |       |  ^
 * |   |    |    |    |   |-- \ -----|  |   complete()  |                       |post() |  |
 * |   |    |    |    |   |    \        |     /-->----- | ---COMPLETE_PENDING->-|       |  |
 * |   |    |    |    |   |     \       |    /          |                               |  |
 * |   |    |    |    |   ^      \      |   /           |                               |  |
 * |  \|/   |    |    |   |       \    \|/ /   post()   |                               |  |
 * | MUST_COMPLETE-<- | - | --<----STARTING-->--------- | -------------|                ^  |
 * |         /|\      |   |  complete()  | \            |              |     complete() |  |
 * |          |       |   |              |  \           |    post()    |     /----------|  |
 * |          |       ^   |    dispatch()|   \          |    |-----|   |    /              |
 * |          |       |   |              |    \         |    |     |   |   /               |
 * |          |       |   |             \|/    \        |    |    \|/ \|/ /                |
 * |          |       |   |--<--MUST_DISPATCH-----<-----|    |--<--STARTED--->-------------|
 * |          |       | dispatched() /|\   |     \                / |
 * |          |       |               |    |      \              /  |
 * |          |       |               |    |       \            /   |
 * |          |       |               |    |post()  \           |   |
 * ^          ^       |               |    |       \|/          |   |
 * |          |       ^               |    |  DISPATCH_PENDING  |   |
 * |          |       |               |    |  |post()           |   |
 * |          |       |               |    |  |      |----------|   |
 * |          |       |               |    |  |      |  dispatch()  |
 * |          |       |               |    |  |      |              |
 * |          |       |post()         |    |  |      |     timeout()|
 * |          |       |dispatched()   |   \|/\|/    \|/             |
 * |          |       |---<---------- | ---DISPATCHING              |
 * |          |                       |     |    ^                  |
 * |          |                       |     |----|                  |
 * |          |                       |    timeout()                |
 * |          |                       |                             |
 * |          |                       |       dispatch()           \|/
 * |          |                       |-----------<-----------TIMING_OUT
 * |          |                                                 |   |
 * |          |-------<----------------------------------<------|   |
 * |                              complete()                        |
 * |                                                                |
 * |<--------<-------------------<-------------------------------<--|
 *                                 error()
 * </pre>
 */
public clreplaced AsyncStateMachine<S> {

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    private static enum AsyncState {

        DISPATCHED(false, false, false, false),
        STARTING(true, true, false, false),
        STARTED(true, true, false, false),
        MUST_COMPLETE(true, true, true, false),
        COMPLETE_PENDING(true, true, false, false),
        COMPLETING(true, false, true, false),
        TIMING_OUT(true, true, false, false),
        MUST_DISPATCH(true, true, false, true),
        DISPATCH_PENDING(true, true, false, false),
        DISPATCHING(true, false, false, true),
        ERROR(true, true, false, false);

        private final boolean isAsync;

        private final boolean isStarted;

        private final boolean isCompleting;

        private final boolean isDispatching;

        private AsyncState(boolean isAsync, boolean isStarted, boolean isCompleting, boolean isDispatching) {
            this.isAsync = isAsync;
            this.isStarted = isStarted;
            this.isCompleting = isCompleting;
            this.isDispatching = isDispatching;
        }

        public boolean isAsync() {
            return isAsync;
        }

        public boolean isStarted() {
            return isStarted;
        }

        public boolean isDispatching() {
            return isDispatching;
        }

        public boolean isCompleting() {
            return isCompleting;
        }
    }

    private volatile AsyncState state = AsyncState.DISPATCHED;

    // Need this to fire listener on complete
    private AsyncContextCallback asyncCtxt = null;

    private Processor<S> processor;

    public AsyncStateMachine(Processor<S> processor) {
        this.processor = processor;
    }

    public boolean isAsync() {
        return state.isAsync();
    }

    public boolean isAsyncDispatching() {
        return state.isDispatching();
    }

    public boolean isAsyncStarted() {
        return state.isStarted();
    }

    public boolean isAsyncTimingOut() {
        return state == AsyncState.TIMING_OUT;
    }

    public boolean isAsyncError() {
        return state == AsyncState.ERROR;
    }

    public boolean isCompleting() {
        return state.isCompleting();
    }

    public synchronized void asyncStart(AsyncContextCallback asyncCtxt) {
        if (state == AsyncState.DISPATCHED) {
            state = AsyncState.STARTING;
            this.asyncCtxt = asyncCtxt;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncStart()", state));
        }
    }

    /*
     * Async has been processed. Whether or not to enter a long poll depends on
     * current state. For example, as per SRV.2.3.3.3 can now process calls to
     * complete() or dispatch().
     */
    public synchronized SocketState asyncPostProcess() {
        if (state == AsyncState.COMPLETE_PENDING) {
            doComplete();
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.DISPATCH_PENDING) {
            doDispatch();
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.STARTING) {
            state = AsyncState.STARTED;
            return SocketState.LONG;
        } else if (state == AsyncState.MUST_COMPLETE) {
            asyncCtxt.fireOnComplete();
            state = AsyncState.DISPATCHED;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.COMPLETING) {
            asyncCtxt.fireOnComplete();
            state = AsyncState.DISPATCHED;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.MUST_DISPATCH) {
            state = AsyncState.DISPATCHING;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.DISPATCHING) {
            state = AsyncState.DISPATCHED;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.STARTED) {
            // This can occur if an async listener does a dispatch to an async
            // servlet during onTimeout
            return SocketState.LONG;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncPostProcess()", state));
        }
    }

    public synchronized boolean asyncComplete() {
        if (!ContainerThreadMarker.isContainerThread() && state == AsyncState.STARTING) {
            state = AsyncState.COMPLETE_PENDING;
            return false;
        } else {
            return doComplete();
        }
    }

    private synchronized boolean doComplete() {
        boolean doComplete = false;
        if (state == AsyncState.STARTING) {
            state = AsyncState.MUST_COMPLETE;
        } else if (state == AsyncState.STARTED || state == AsyncState.COMPLETE_PENDING) {
            state = AsyncState.COMPLETING;
            doComplete = true;
        } else if (state == AsyncState.TIMING_OUT || state == AsyncState.ERROR) {
            state = AsyncState.MUST_COMPLETE;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncComplete()", state));
        }
        return doComplete;
    }

    public synchronized boolean asyncTimeout() {
        if (state == AsyncState.STARTED) {
            state = AsyncState.TIMING_OUT;
            return true;
        } else if (state == AsyncState.COMPLETING || state == AsyncState.DISPATCHING || state == AsyncState.DISPATCHED) {
            // NOOP - App called complete() or dispatch() between the the
            // timeout firing and execution reaching this point
            return false;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncTimeout()", state));
        }
    }

    public synchronized boolean asyncDispatch() {
        if (!ContainerThreadMarker.isContainerThread() && state == AsyncState.STARTING) {
            state = AsyncState.DISPATCH_PENDING;
            return false;
        } else {
            return doDispatch();
        }
    }

    private synchronized boolean doDispatch() {
        boolean doDispatch = false;
        if (state == AsyncState.STARTING || state == AsyncState.TIMING_OUT || state == AsyncState.ERROR) {
            // In these three cases processing is on a container thread so no
            // need to transfer processing to a new container thread
            state = AsyncState.MUST_DISPATCH;
        } else if (state == AsyncState.STARTED || state == AsyncState.DISPATCH_PENDING) {
            // A dispatch is always required.
            // If on a non-container thread, need to get back onto a container
            // thread to complete the processing.
            // If on a container thread the current request/response are not the
            // request/response replacedociated with the AsyncContext so need a new
            // container thread to process the different request/response.
            state = AsyncState.DISPATCHING;
            doDispatch = true;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncDispatch()", state));
        }
        return doDispatch;
    }

    public synchronized void asyncDispatched() {
        if (state == AsyncState.DISPATCHING || state == AsyncState.MUST_DISPATCH) {
            state = AsyncState.DISPATCHED;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncDispatched()", state));
        }
    }

    public synchronized boolean asyncError() {
        boolean doDispatch = false;
        if (state == AsyncState.STARTING || state == AsyncState.STARTED || state == AsyncState.DISPATCHED || state == AsyncState.TIMING_OUT || state == AsyncState.MUST_COMPLETE) {
            state = AsyncState.ERROR;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncError()", state));
        }
        return doDispatch;
    }

    public synchronized void asyncRun(Runnable runnable) {
        if (state == AsyncState.STARTING || state == AsyncState.STARTED) {
            // Execute the runnable using a container thread from the
            // Connector's thread pool. Use a wrapper to prevent a memory leak
            ClreplacedLoader oldCL;
            if (Constants.IS_SECURITY_ENABLED) {
                PrivilegedAction<ClreplacedLoader> pa = new PrivilegedGetTccl();
                oldCL = AccessController.doPrivileged(pa);
            } else {
                oldCL = Thread.currentThread().getContextClreplacedLoader();
            }
            try {
                if (Constants.IS_SECURITY_ENABLED) {
                    PrivilegedAction<Void> pa = new PrivilegedSetTccl(this.getClreplaced().getClreplacedLoader());
                    AccessController.doPrivileged(pa);
                } else {
                    Thread.currentThread().setContextClreplacedLoader(this.getClreplaced().getClreplacedLoader());
                }
                processor.getExecutor().execute(runnable);
            } finally {
                if (Constants.IS_SECURITY_ENABLED) {
                    PrivilegedAction<Void> pa = new PrivilegedSetTccl(oldCL);
                    AccessController.doPrivileged(pa);
                } else {
                    Thread.currentThread().setContextClreplacedLoader(oldCL);
                }
            }
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncRun()", state));
        }
    }

    public synchronized void recycle() {
        // Ensure in case of error that any non-container threads that have been
        // paused are unpaused.
        notifyAll();
        asyncCtxt = null;
        state = AsyncState.DISPATCHED;
    }
}

19 Source : AjpMessage.java
with Apache License 2.0
from wangyingjie

/**
 * A single packet for communication between the web server and the
 * container.  Designed to be reused many times with no creation of
 * garbage.  Understands the format of data types for these packets.
 * Can be used (somewhat confusingly) for both incoming and outgoing
 * packets.
 *
 * @author Henri Gomez
 * @author Dan Milstein
 * @author Keith Wannamaker
 * @author Kevin Seguin
 * @author Costin Manolache
 */
public clreplaced AjpMessage {

    private static final Log log = LogFactory.getLog(AjpMessage.clreplaced);

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    // ------------------------------------------------------------ Constructor
    public AjpMessage(int packetSize) {
        buf = new byte[packetSize];
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * Fixed size buffer.
     */
    protected byte[] buf = null;

    /**
     * The current read or write position in the buffer.
     */
    protected int pos;

    /**
     * This actually means different things depending on whether the
     * packet is read or write.  For read, it's the length of the
     * payload (excluding the header).  For write, it's the length of
     * the packet as a whole (counting the header).  Oh, well.
     */
    protected int len;

    // --------------------------------------------------------- Public Methods
    /**
     * Prepare this packet for acreplacedulating a message from the container to
     * the web server.  Set the write position to just after the header
     * (but leave the length unwritten, because it is as yet unknown).
     */
    public void reset() {
        len = 4;
        pos = 4;
    }

    /**
     * For a packet to be sent to the web server, finish the process of
     * acreplacedulating data and write the length of the data payload into
     * the header.
     */
    public void end() {
        len = pos;
        int dLen = len - 4;
        buf[0] = (byte) 0x41;
        buf[1] = (byte) 0x42;
        buf[2] = (byte) ((dLen >>> 8) & 0xFF);
        buf[3] = (byte) (dLen & 0xFF);
    }

    /**
     * Return the underlying byte buffer.
     */
    public byte[] getBuffer() {
        return buf;
    }

    /**
     * Return the current message length. For read, it's the length of the
     * payload (excluding the header).  For write, it's the length of
     * the packet as a whole (counting the header).
     */
    public int getLen() {
        return len;
    }

    /**
     * Add a short integer (2 bytes) to the message.
     */
    public void appendInt(int val) {
        buf[pos++] = (byte) ((val >>> 8) & 0xFF);
        buf[pos++] = (byte) (val & 0xFF);
    }

    /**
     * Append a byte (1 byte) to the message.
     */
    public void appendByte(int val) {
        buf[pos++] = (byte) val;
    }

    /**
     * Write a MessageBytes out at the current write position.
     * A null MessageBytes is encoded as a string with length 0.
     */
    public void appendBytes(MessageBytes mb) {
        if (mb == null) {
            log.error(sm.getString("ajpmessage.null"), new NullPointerException());
            appendInt(0);
            appendByte(0);
            return;
        }
        if (mb.getType() == MessageBytes.T_BYTES) {
            ByteChunk bc = mb.getByteChunk();
            appendByteChunk(bc);
        } else if (mb.getType() == MessageBytes.T_CHARS) {
            CharChunk cc = mb.getCharChunk();
            appendCharChunk(cc);
        } else {
            appendString(mb.toString());
        }
    }

    /**
     * Write a ByteChunk out at the current write position.
     * A null ByteChunk is encoded as a string with length 0.
     */
    public void appendByteChunk(ByteChunk bc) {
        if (bc == null) {
            log.error(sm.getString("ajpmessage.null"), new NullPointerException());
            appendInt(0);
            appendByte(0);
            return;
        }
        appendBytes(bc.getBytes(), bc.getStart(), bc.getLength());
    }

    /**
     * Write a CharChunk out at the current write position.
     * A null CharChunk is encoded as a string with length 0.
     */
    public void appendCharChunk(CharChunk cc) {
        if (cc == null) {
            log.error(sm.getString("ajpmessage.null"), new NullPointerException());
            appendInt(0);
            appendByte(0);
            return;
        }
        int start = cc.getStart();
        int end = cc.getEnd();
        appendInt(end - start);
        char[] cbuf = cc.getBuffer();
        for (int i = start; i < end; i++) {
            char c = cbuf[i];
            // Note:  This is clearly incorrect for many strings,
            // but is the only consistent approach within the current
            // servlet framework.  It must suffice until servlet output
            // streams properly encode their output.
            if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
                c = ' ';
            }
            appendByte(c);
        }
        appendByte(0);
    }

    /**
     * Write a String out at the current write position.  Strings are
     * encoded with the length in two bytes first, then the string, and
     * then a terminating \0 (which is <B>not</B> included in the
     * encoded length).  The terminator is for the convenience of the C
     * code, where it saves a round of copying.  A null string is
     * encoded as a string with length 0.
     */
    public void appendString(String str) {
        if (str == null) {
            log.error(sm.getString("ajpmessage.null"), new NullPointerException());
            appendInt(0);
            appendByte(0);
            return;
        }
        int len = str.length();
        appendInt(len);
        for (int i = 0; i < len; i++) {
            char c = str.charAt(i);
            // Note:  This is clearly incorrect for many strings,
            // but is the only consistent approach within the current
            // servlet framework.  It must suffice until servlet output
            // streams properly encode their output.
            if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
                c = ' ';
            }
            appendByte(c);
        }
        appendByte(0);
    }

    /**
     * Copy a chunk of bytes into the packet, starting at the current
     * write position.  The chunk of bytes is encoded with the length
     * in two bytes first, then the data itself, and finally a
     * terminating \0 (which is <B>not</B> included in the encoded
     * length).
     *
     * @param b The array from which to copy bytes.
     * @param off The offset into the array at which to start copying
     * @param numBytes The number of bytes to copy.
     */
    public void appendBytes(byte[] b, int off, int numBytes) {
        if (pos + numBytes + 3 > buf.length) {
            log.error(sm.getString("ajpmessage.overflow", "" + numBytes, "" + pos), new ArrayIndexOutOfBoundsException());
            if (log.isDebugEnabled()) {
                dump("Overflow/coBytes");
            }
            return;
        }
        appendInt(numBytes);
        System.arraycopy(b, off, buf, pos, numBytes);
        pos += numBytes;
        appendByte(0);
    }

    /**
     * Read an integer from packet, and advance the read position past
     * it.  Integers are encoded as two unsigned bytes with the
     * high-order byte first, and, as far as I can tell, in
     * little-endian order within each byte.
     */
    public int getInt() {
        int b1 = buf[pos++] & 0xFF;
        int b2 = buf[pos++] & 0xFF;
        validatePos(pos);
        return (b1 << 8) + b2;
    }

    public int peekInt() {
        validatePos(pos + 2);
        int b1 = buf[pos] & 0xFF;
        int b2 = buf[pos + 1] & 0xFF;
        return (b1 << 8) + b2;
    }

    public byte getByte() {
        byte res = buf[pos++];
        validatePos(pos);
        return res;
    }

    public void getBytes(MessageBytes mb) {
        doGetBytes(mb, true);
    }

    public void getBodyBytes(MessageBytes mb) {
        doGetBytes(mb, false);
    }

    private void doGetBytes(MessageBytes mb, boolean terminated) {
        int length = getInt();
        if ((length == 0xFFFF) || (length == -1)) {
            mb.recycle();
            return;
        }
        if (terminated) {
            validatePos(pos + length + 1);
        } else {
            validatePos(pos + length);
        }
        mb.setBytes(buf, pos, length);
        // not valid anymore
        mb.getCharChunk().recycle();
        pos += length;
        if (terminated) {
            // Skip the terminating \0
            pos++;
        }
    }

    /**
     * Read a 32 bits integer from packet, and advance the read position past
     * it.  Integers are encoded as four unsigned bytes with the
     * high-order byte first, and, as far as I can tell, in
     * little-endian order within each byte.
     */
    public int getLongInt() {
        // No swap, Java order
        int b1 = buf[pos++] & 0xFF;
        b1 <<= 8;
        b1 |= (buf[pos++] & 0xFF);
        b1 <<= 8;
        b1 |= (buf[pos++] & 0xFF);
        b1 <<= 8;
        b1 |= (buf[pos++] & 0xFF);
        validatePos(pos);
        return b1;
    }

    public int getHeaderLength() {
        return Constants.H_SIZE;
    }

    public int getPacketSize() {
        return buf.length;
    }

    @Deprecated
    public int processHeader() {
        return processHeader(true);
    }

    public int processHeader(boolean toContainer) {
        pos = 0;
        int mark = getInt();
        len = getInt();
        // Verify message signature
        if ((toContainer && mark != 0x1234) || (!toContainer && mark != 0x4142)) {
            log.error(sm.getString("ajpmessage.invalid", "" + mark));
            if (log.isDebugEnabled()) {
                dump("In: ");
            }
            return -1;
        }
        if (log.isDebugEnabled()) {
            log.debug("Received " + len + " " + buf[0]);
        }
        return len;
    }

    /**
     * Dump the contents of the message, prefixed with the given String.
     */
    public void dump(String msg) {
        if (log.isDebugEnabled()) {
            log.debug(msg + ": " + HexUtils.toHexString(buf) + " " + pos + "/" + (len + 4));
        }
        int max = pos;
        if (len + 4 > pos)
            max = len + 4;
        if (max > 1000)
            max = 1000;
        if (log.isDebugEnabled()) {
            for (int j = 0; j < max; j += 16) {
                log.debug(hexLine(buf, j, len));
            }
        }
    }

    private void validatePos(int posToTest) {
        if (posToTest > len + 4) {
            // Trying to read data beyond the end of the AJP message
            throw new ArrayIndexOutOfBoundsException(sm.getString("ajpMessage.invalidPos", Integer.valueOf(posToTest)));
        }
    }

    // ------------------------------------------------------ Protected Methods
    protected static String hexLine(byte[] buf, int start, int len) {
        StringBuilder sb = new StringBuilder();
        for (int i = start; i < start + 16; i++) {
            if (i < len + 4) {
                sb.append(hex(buf[i]) + " ");
            } else {
                sb.append("   ");
            }
        }
        sb.append(" | ");
        for (int i = start; i < start + 16 && i < len + 4; i++) {
            if (!Character.isISOControl((char) buf[i])) {
                sb.append(Character.valueOf((char) buf[i]));
            } else {
                sb.append(".");
            }
        }
        return sb.toString();
    }

    protected static String hex(int x) {
        String h = Integer.toHexString(x);
        if (h.length() == 1) {
            h = "0" + h;
        }
        return h.substring(h.length() - 2);
    }
}

19 Source : AbstractAjpProtocol.java
with Apache License 2.0
from wangyingjie

public abstract clreplaced AbstractAjpProtocol<S> extends AbstractProtocol<S> {

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    @Override
    protected String getProtocolName() {
        return "Ajp";
    }

    // ------------------------------------------------- AJP specific properties
    // ------------------------------------------ managed in the ProtocolHandler
    /**
     * Send AJP flush packet when flushing.
     * An flush packet is a zero byte AJP13 SEND_BODY_CHUNK
     * packet. mod_jk and mod_proxy_ajp interprete this as
     * a request to flush data to the client.
     * AJP always does flush at the and of the response, so if
     * it is not important, that the packets get streamed up to
     * the client, do not use extra flush packets.
     * For compatibility and to stay on the safe side, flush
     * packets are enabled by default.
     */
    protected boolean ajpFlush = true;

    public boolean getAjpFlush() {
        return ajpFlush;
    }

    public void setAjpFlush(boolean ajpFlush) {
        this.ajpFlush = ajpFlush;
    }

    /**
     * Should authentication be done in the native web server layer,
     * or in the Servlet container ?
     */
    protected boolean tomcatAuthentication = true;

    public boolean getTomcatAuthentication() {
        return tomcatAuthentication;
    }

    public void setTomcatAuthentication(boolean tomcatAuthentication) {
        this.tomcatAuthentication = tomcatAuthentication;
    }

    /**
     * Should authentication be done in the native web server layer and
     * authorization in the Servlet container?
     */
    private boolean tomcatAuthorization = false;

    public boolean getTomcatAuthorization() {
        return tomcatAuthorization;
    }

    public void setTomcatAuthorization(boolean tomcatAuthorization) {
        this.tomcatAuthorization = tomcatAuthorization;
    }

    /**
     * Required secret.
     */
    protected String requiredSecret = null;

    public void setRequiredSecret(String requiredSecret) {
        this.requiredSecret = requiredSecret;
    }

    /**
     * AJP packet size.
     */
    protected int packetSize = Constants.MAX_PACKET_SIZE;

    public int getPacketSize() {
        return packetSize;
    }

    public void setPacketSize(int packetSize) {
        if (packetSize < Constants.MAX_PACKET_SIZE) {
            this.packetSize = Constants.MAX_PACKET_SIZE;
        } else {
            this.packetSize = packetSize;
        }
    }

    protected abstract static clreplaced AbstractAjpConnectionHandler<S, P extends AbstractAjpProcessor<S>> extends AbstractConnectionHandler<S, P> {

        @Override
        protected void initSsl(SocketWrapper<S> socket, Processor<S> processor) {
        // NOOP for AJP
        }

        @Override
        protected void longPoll(SocketWrapper<S> socket, Processor<S> processor) {
            // Same requirements for all AJP connectors
            socket.setAsync(true);
        }

        /**
         * @deprecated  Will be removed in Tomcat 8.0.x.
         */
        @Deprecated
        @Override
        protected P createUpgradeProcessor(SocketWrapper<S> socket, org.apache.coyote.http11.upgrade.UpgradeInbound inbound) {
            // TODO should fail - throw IOE
            return null;
        }

        @Override
        protected P createUpgradeProcessor(SocketWrapper<S> socket, HttpUpgradeHandler httpUpgradeHandler) {
            // TODO should fail - throw IOE
            return null;
        }
    }
}

19 Source : AbstractProcessor.java
with Apache License 2.0
from wangyingjie

/**
 * Provides functionality and attributes common to all supported protocols
 * (currently HTTP and AJP).
 */
public abstract clreplaced AbstractProcessor<S> implements ActionHook, Processor<S> {

    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    protected Adapter adapter;

    protected AsyncStateMachine<S> asyncStateMachine;

    protected AbstractEndpoint<S> endpoint;

    protected Request request;

    protected Response response;

    protected SocketWrapper<S> socketWrapper = null;

    private int maxCookieCount = 200;

    /**
     * Error state for the request/response currently being processed.
     */
    private ErrorState errorState = ErrorState.NONE;

    /**
     * Intended for use by the Upgrade sub-clreplacedes that have no need to
     * initialise the request, response, etc.
     */
    protected AbstractProcessor() {
    // NOOP
    }

    public AbstractProcessor(AbstractEndpoint<S> endpoint) {
        this.endpoint = endpoint;
        asyncStateMachine = new AsyncStateMachine<S>(this);
        // 创建出 request、response 对象
        request = new Request();
        response = new Response();
        response.setHook(this);
        request.setResponse(response);
    }

    /**
     * Update the current error state to the new error state if the new error
     * state is more severe than the current error state.
     */
    protected void setErrorState(ErrorState errorState, Throwable t) {
        boolean blockIo = this.errorState.isIoAllowed() && !errorState.isIoAllowed();
        this.errorState = this.errorState.getMostSevere(errorState);
        if (blockIo && !ContainerThreadMarker.isContainerThread() && isAsync()) {
            // The error occurred on a non-container thread during async
            // processing which means not all of the necessary clean-up will
            // have been completed. Dispatch to a container thread to do the
            // clean-up. Need to do it this way to ensure that all the necessary
            // clean-up is performed.
            if (response.getStatus() < 400) {
                response.setStatus(500);
            }
            getLog().info(sm.getString("abstractProcessor.nonContainerThreadError"), t);
            // Set the request attribute so that the async onError() event is
            // fired when the error event is processed
            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
            getEndpoint().processSocketAsync(socketWrapper, SocketStatus.ERROR);
        }
    }

    protected void resetErrorState() {
        errorState = ErrorState.NONE;
    }

    protected ErrorState getErrorState() {
        return errorState;
    }

    /**
     * The endpoint receiving connections that are handled by this processor.
     */
    protected AbstractEndpoint<S> getEndpoint() {
        return endpoint;
    }

    /**
     * The request replacedociated with this processor.
     */
    @Override
    public Request getRequest() {
        return request;
    }

    /**
     * Set the replacedociated adapter.
     *
     * @param adapter the new adapter
     */
    public void setAdapter(Adapter adapter) {
        this.adapter = adapter;
    }

    /**
     * Get the replacedociated adapter.
     *
     * @return the replacedociated adapter
     */
    public Adapter getAdapter() {
        return adapter;
    }

    /**
     * Set the socket wrapper being used.
     */
    protected final void setSocketWrapper(SocketWrapper<S> socketWrapper) {
        this.socketWrapper = socketWrapper;
    }

    /**
     * Get the socket wrapper being used.
     */
    protected final SocketWrapper<S> getSocketWrapper() {
        return socketWrapper;
    }

    /**
     * Obtain the Executor used by the underlying endpoint.
     */
    @Override
    public Executor getExecutor() {
        return endpoint.getExecutor();
    }

    @Override
    public boolean isAsync() {
        return (asyncStateMachine != null && asyncStateMachine.isAsync());
    }

    @Override
    public SocketState asyncPostProcess() {
        return asyncStateMachine.asyncPostProcess();
    }

    @Override
    public void errorDispatch() {
        getAdapter().errorDispatch(request, response);
    }

    @Override
    public abstract boolean isComet();

    @Override
    public abstract boolean isUpgrade();

    /**
     * Process HTTP requests. All requests are treated as HTTP requests to start
     * with although they may change type during processing.
     */
    @Override
    public abstract SocketState process(SocketWrapper<S> socket) throws IOException;

    /**
     * Process in-progress Comet requests. These will start as HTTP requests.
     */
    @Override
    public abstract SocketState event(SocketStatus status) throws IOException;

    /**
     * Process in-progress Servlet 3.0 Async requests. These will start as HTTP
     * requests.
     */
    @Override
    public abstract SocketState asyncDispatch(SocketStatus status);

    /**
     * Processes data received on a connection that has been through an HTTP
     * upgrade.
     */
    @Override
    public abstract SocketState upgradeDispatch() throws IOException;

    public int getMaxCookieCount() {
        return maxCookieCount;
    }

    public void setMaxCookieCount(int maxCookieCount) {
        this.maxCookieCount = maxCookieCount;
    }

    /**
     * @deprecated  Will be removed in Tomcat 8.0.x.
     */
    @Deprecated
    @Override
    public abstract org.apache.coyote.http11.upgrade.UpgradeInbound getUpgradeInbound();

    protected abstract Log getLog();
}

19 Source : SessionIdGeneratorBase.java
with Apache License 2.0
from wangyingjie

public abstract clreplaced SessionIdGeneratorBase extends LifecycleBase implements SessionIdGenerator {

    private static final Log log = LogFactory.getLog(SessionIdGeneratorBase.clreplaced);

    private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");

    /**
     * Queue of random number generator objects to be used when creating session
     * identifiers. If the queue is empty when a random number generator is
     * required, a new random number generator object is created. This is
     * designed this way since random number generators use a sync to make them
     * thread-safe and the sync makes using a a single object slow(er).
     */
    private final Queue<SecureRandom> randoms = new ConcurrentLinkedQueue<SecureRandom>();

    /**
     * The Java clreplaced name of the secure random number generator clreplaced to be
     * used when generating session identifiers. The random number generator
     * clreplaced must be self-seeding and have a zero-argument constructor. If not
     * specified, an instance of {@link SecureRandom} will be generated.
     */
    private String secureRandomClreplaced = null;

    /**
     * The name of the algorithm to use to create instances of
     * {@link SecureRandom} which are used to generate session IDs. If no
     * algorithm is specified, SHA1PRNG is used. To use the platform default
     * (which may be SHA1PRNG), specify the empty string. If an invalid
     * algorithm and/or provider is specified the {@link SecureRandom} instances
     * will be created using the defaults. If that fails, the {@link
     * SecureRandom} instances will be created using platform defaults.
     */
    private String secureRandomAlgorithm = "SHA1PRNG";

    /**
     * The name of the provider to use to create instances of
     * {@link SecureRandom} which are used to generate session IDs. If
     * no algorithm is specified the of SHA1PRNG default is used. If an invalid
     * algorithm and/or provider is specified the {@link SecureRandom} instances
     * will be created using the defaults. If that fails, the {@link
     * SecureRandom} instances will be created using platform defaults.
     */
    private String secureRandomProvider = null;

    /**
     * Node identifier when in a cluster. Defaults to the empty string.
     */
    private String jvmRoute = "";

    /**
     * Number of bytes in a session ID. Defaults to 16.
     */
    private int sessionIdLength = 16;

    /**
     * Specify a non-default @{link {@link SecureRandom} implementation to use.
     *
     * @param secureRandomClreplaced The fully-qualified clreplaced name
     */
    public void setSecureRandomClreplaced(String secureRandomClreplaced) {
        this.secureRandomClreplaced = secureRandomClreplaced;
    }

    /**
     * Specify a non-default algorithm to use to generate random numbers.
     *
     * @param secureRandomAlgorithm The name of the algorithm
     */
    public void setSecureRandomAlgorithm(String secureRandomAlgorithm) {
        this.secureRandomAlgorithm = secureRandomAlgorithm;
    }

    /**
     * Specify a non-default provider to use to generate random numbers.
     *
     * @param secureRandomProvider  The name of the provider
     */
    public void setSecureRandomProvider(String secureRandomProvider) {
        this.secureRandomProvider = secureRandomProvider;
    }

    /**
     * Return the node identifier replacedociated with this node which will be
     * included in the generated session ID.
     */
    @Override
    public String getJvmRoute() {
        return jvmRoute;
    }

    /**
     * Specify the node identifier replacedociated with this node which will be
     * included in the generated session ID.
     *
     * @param jvmRoute  The node identifier
     */
    @Override
    public void setJvmRoute(String jvmRoute) {
        this.jvmRoute = jvmRoute;
    }

    /**
     * Return the number of bytes for a session ID
     */
    @Override
    public int getSessionIdLength() {
        return sessionIdLength;
    }

    /**
     * Specify the number of bytes for a session ID
     *
     * @param sessionIdLength   Number of bytes
     */
    @Override
    public void setSessionIdLength(int sessionIdLength) {
        this.sessionIdLength = sessionIdLength;
    }

    /**
     * Generate and return a new session identifier.
     */
    @Override
    public String generateSessionId() {
        return generateSessionId(jvmRoute);
    }

    protected void getRandomBytes(byte[] bytes) {
        SecureRandom random = randoms.poll();
        if (random == null) {
            random = createSecureRandom();
        }
        random.nextBytes(bytes);
        randoms.add(random);
    }

    /**
     * Create a new random number generator instance we should use for
     * generating session identifiers.
     */
    private SecureRandom createSecureRandom() {
        SecureRandom result = null;
        long t1 = System.currentTimeMillis();
        if (secureRandomClreplaced != null) {
            try {
                // Construct and seed a new random number generator
                Clreplaced<?> clazz = Clreplaced.forName(secureRandomClreplaced);
                result = (SecureRandom) clazz.newInstance();
            } catch (Exception e) {
                log.error(sm.getString("sessionIdGeneratorBase.random", secureRandomClreplaced), e);
            }
        }
        if (result == null) {
            // No secureRandomClreplaced or creation failed. Use SecureRandom.
            try {
                if (secureRandomProvider != null && secureRandomProvider.length() > 0) {
                    result = SecureRandom.getInstance(secureRandomAlgorithm, secureRandomProvider);
                } else if (secureRandomAlgorithm != null && secureRandomAlgorithm.length() > 0) {
                    result = SecureRandom.getInstance(secureRandomAlgorithm);
                }
            } catch (NoSuchAlgorithmException e) {
                log.error(sm.getString("sessionIdGeneratorBase.randomAlgorithm", secureRandomAlgorithm), e);
            } catch (NoSuchProviderException e) {
                log.error(sm.getString("sessionIdGeneratorBase.randomProvider", secureRandomProvider), e);
            }
        }
        if (result == null) {
            // Invalid provider / algorithm
            try {
                result = SecureRandom.getInstance("SHA1PRNG");
            } catch (NoSuchAlgorithmException e) {
                log.error(sm.getString("sessionIdGeneratorBase.randomAlgorithm", secureRandomAlgorithm), e);
            }
        }
        if (result == null) {
            // Nothing works - use platform default
            result = new SecureRandom();
        }
        // Force seeding to take place
        result.nextInt();
        long t2 = System.currentTimeMillis();
        if ((t2 - t1) > 100)
            log.info(sm.getString("sessionIdGeneratorBase.createRandom", result.getAlgorithm(), Long.valueOf(t2 - t1)));
        return result;
    }

    @Override
    protected void initInternal() throws LifecycleException {
    // NO-OP
    }

    @Override
    protected void startInternal() throws LifecycleException {
        // Ensure SecureRandom has been initialised
        generateSessionId();
        setState(LifecycleState.STARTING);
    }

    @Override
    protected void stopInternal() throws LifecycleException {
        setState(LifecycleState.STOPPING);
        randoms.clear();
    }

    @Override
    protected void destroyInternal() throws LifecycleException {
    // NO-OP
    }
}

19 Source : ResourceSet.java
with Apache License 2.0
from wangyingjie

/**
 * Extended implementation of <strong>HashSet</strong> that includes a
 * <code>locked</code> property.  This clreplaced can be used to safely expose
 * resource path sets to user clreplacedes without having to clone them in order
 * to avoid modifications.  When first created, a <code>ResourceMap</code>
 * is not locked.
 *
 * @author Craig R. McClanahan
 */
public final clreplaced ResourceSet<T> extends HashSet<T> {

    private static final long serialVersionUID = 1L;

    // ----------------------------------------------------------- Constructors
    /**
     * Construct a new, empty set with the default initial capacity and
     * load factor.
     */
    public ResourceSet() {
        super();
    }

    /**
     * Construct a new, empty set with the specified initial capacity and
     * default load factor.
     *
     * @param initialCapacity The initial capacity of this set
     */
    public ResourceSet(int initialCapacity) {
        super(initialCapacity);
    }

    /**
     * Construct a new, empty set with the specified initial capacity and
     * load factor.
     *
     * @param initialCapacity The initial capacity of this set
     * @param loadFactor The load factor of this set
     */
    public ResourceSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
    }

    /**
     * Construct a new set with the same contents as the existing collection.
     *
     * @param coll The collection whose contents we should copy
     */
    public ResourceSet(Collection<T> coll) {
        super(coll);
    }

    // ------------------------------------------------------------- Properties
    /**
     * The current lock state of this parameter map.
     */
    private boolean locked = false;

    /**
     * Return the locked state of this parameter map.
     */
    public boolean isLocked() {
        return (this.locked);
    }

    /**
     * Set the locked state of this parameter map.
     *
     * @param locked The new locked state
     */
    public void setLocked(boolean locked) {
        this.locked = locked;
    }

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");

    // --------------------------------------------------------- Public Methods
    /**
     * Add the specified element to this set if it is not already present.
     * Return <code>true</code> if the element was added.
     *
     * @param o The object to be added
     *
     * @exception IllegalStateException if this ResourceSet is locked
     */
    @Override
    public boolean add(T o) {
        if (locked)
            throw new IllegalStateException(sm.getString("resourceSet.locked"));
        return (super.add(o));
    }

    /**
     * Remove all of the elements from this set.
     *
     * @exception IllegalStateException if this ResourceSet is locked
     */
    @Override
    public void clear() {
        if (locked)
            throw new IllegalStateException(sm.getString("resourceSet.locked"));
        super.clear();
    }

    /**
     * Remove the given element from this set if it is present.
     * Return <code>true</code> if the element was removed.
     *
     * @param o The object to be removed
     *
     * @exception IllegalStateException if this ResourceSet is locked
     */
    @Override
    public boolean remove(Object o) {
        if (locked)
            throw new IllegalStateException(sm.getString("resourceSet.locked"));
        return (super.remove(o));
    }
}

19 Source : RequestUtil.java
with Apache License 2.0
from wangyingjie

/**
 * General purpose request parsing and encoding utility methods.
 *
 * @author Craig R. McClanahan
 * @author Tim Tye
 */
public final clreplaced RequestUtil {

    private static final Log log = LogFactory.getLog(RequestUtil.clreplaced);

    /**
     * The string resources for this package.
     */
    private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");

    /**
     * Filter the specified message string for characters that are sensitive
     * in HTML.  This avoids potential attacks caused by including JavaScript
     * codes in the request URL that is often reported in error messages.
     *
     * @param message The message string to be filtered
     */
    public static String filter(String message) {
        if (message == null)
            return (null);
        char[] content = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuilder result = new StringBuilder(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch(content[i]) {
                case '<':
                    result.append("<");
                    break;
                case '>':
                    result.append(">");
                    break;
                case '&':
                    result.append("&");
                    break;
                case '"':
                    result.append(""");
                    break;
                default:
                    result.append(content[i]);
            }
        }
        return (result.toString());
    }

    /**
     * Normalize a relative URI path that may have relative values ("/./",
     * "/../", and so on ) it it.  <strong>WARNING</strong> - This method is
     * useful only for normalizing application-generated paths.  It does not
     * try to perform security checks for malicious input.
     *
     * @param path Relative path to be normalized
     *
     * @deprecated Deprecated to resolve a circular package dependency and will
     *             be removed in Tomcat 8.0.x. Use {@link
     *             org.apache.tomcat.util.http.RequestUtil#normalize(String)} as
     *             a replacement.
     */
    @Deprecated
    public static String normalize(String path) {
        return org.apache.tomcat.util.http.RequestUtil.normalize(path);
    }

    /**
     * Normalize a relative URI path that may have relative values ("/./",
     * "/../", and so on ) it it.  <strong>WARNING</strong> - This method is
     * useful only for normalizing application-generated paths.  It does not
     * try to perform security checks for malicious input.
     *
     * @param path Relative path to be normalized
     * @param replaceBackSlash Should '\\' be replaced with '/'
     *
     * @deprecated Deprecated to resolve a circular package dependency and will
     *             be removed in Tomcat 8.0.x. Use {@link
     *             org.apache.tomcat.util.http.RequestUtil#normalize(String,
     *             boolean)} as a replacement.
     */
    @Deprecated
    public static String normalize(String path, boolean replaceBackSlash) {
        return org.apache.tomcat.util.http.RequestUtil.normalize(path, replaceBackSlash);
    }

    /**
     * Append request parameters from the specified String to the specified
     * Map.  It is presumed that the specified Map is not accessed from any
     * other thread, so no synchronization is performed.
     * <p>
     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
     * individually on the parsed name and value elements, rather than on
     * the entire query string ahead of time, to properly deal with the case
     * where the name or value includes an encoded "=" or "&" character
     * that would otherwise be interpreted as a delimiter.
     *
     * @param map Map that acreplacedulates the resulting parameters
     * @param data Input string containing request parameters
     * @param encoding The encoding to use; encoding must not be null.
     * If an unsupported encoding is specified the parameters will not be
     * parsed and the map will not be modified
     */
    public static void parseParameters(Map<String, String[]> map, String data, String encoding) {
        if ((data != null) && (data.length() > 0)) {
            // use the specified encoding to extract bytes out of the
            // given string so that the encoding is not lost.
            byte[] bytes = null;
            try {
                bytes = data.getBytes(B2CConverter.getCharset(encoding));
                parseParameters(map, bytes, encoding);
            } catch (UnsupportedEncodingException uee) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("requestUtil.parseParameters.uee", encoding), uee);
                }
            }
        }
    }

    /**
     * Decode and return the specified URL-encoded String.
     * When the byte array is converted to a string, the system default
     * character encoding is used...  This may be different than some other
     * servers. It is replacedumed the string is not a query string.
     *
     * @param str The url-encoded string
     *
     * @exception IllegalArgumentException if a '%' character is not followed
     * by a valid 2-digit hexadecimal number
     */
    public static String URLDecode(String str) {
        return URLDecode(str, null);
    }

    /**
     * Decode and return the specified URL-encoded String. It is replacedumed the
     * string is not a query string.
     *
     * @param str The url-encoded string
     * @param enc The encoding to use; if null, the default encoding is used. If
     * an unsupported encoding is specified null will be returned
     * @exception IllegalArgumentException if a '%' character is not followed
     * by a valid 2-digit hexadecimal number
     */
    public static String URLDecode(String str, String enc) {
        return URLDecode(str, enc, false);
    }

    /**
     * Decode and return the specified URL-encoded String.
     *
     * @param str The url-encoded string
     * @param enc The encoding to use; if null, the default encoding is used. If
     * an unsupported encoding is specified null will be returned
     * @param isQuery Is this a query string being processed
     * @exception IllegalArgumentException if a '%' character is not followed
     * by a valid 2-digit hexadecimal number
     */
    public static String URLDecode(String str, String enc, boolean isQuery) {
        if (str == null)
            return (null);
        // use the specified encoding to extract bytes out of the
        // given string so that the encoding is not lost. If an
        // encoding is not specified, let it use platform default
        byte[] bytes = null;
        try {
            if (enc == null) {
                bytes = str.getBytes(Charset.defaultCharset());
            } else {
                bytes = str.getBytes(B2CConverter.getCharset(enc));
            }
        } catch (UnsupportedEncodingException uee) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("requestUtil.urlDecode.uee", enc), uee);
            }
        }
        return URLDecode(bytes, enc, isQuery);
    }

    /**
     * Decode and return the specified URL-encoded byte array. It is replacedumed
     * the string is not a query string.
     *
     * @param bytes The url-encoded byte array
     * @exception IllegalArgumentException if a '%' character is not followed
     * by a valid 2-digit hexadecimal number
     */
    public static String URLDecode(byte[] bytes) {
        return URLDecode(bytes, null);
    }

    /**
     * Decode and return the specified URL-encoded byte array. It is replacedumed
     * the string is not a query string.
     *
     * @param bytes The url-encoded byte array
     * @param enc The encoding to use; if null, the default encoding is used
     * @exception IllegalArgumentException if a '%' character is not followed
     * by a valid 2-digit hexadecimal number
     *
     * @deprecated  Unused - will be removed in 8.0.x
     */
    @Deprecated
    public static String URLDecode(byte[] bytes, String enc) {
        return URLDecode(bytes, enc, false);
    }

    /**
     * Decode and return the specified URL-encoded byte array.
     *
     * @param bytes The url-encoded byte array
     * @param enc The encoding to use; if null, the default encoding is used. If
     * an unsupported encoding is specified null will be returned
     * @param isQuery Is this a query string being processed
     * @exception IllegalArgumentException if a '%' character is not followed
     * by a valid 2-digit hexadecimal number
     */
    public static String URLDecode(byte[] bytes, String enc, boolean isQuery) {
        if (bytes == null)
            return null;
        int len = bytes.length;
        int ix = 0;
        int ox = 0;
        while (ix < len) {
            // Get byte to test
            byte b = bytes[ix++];
            if (b == '+' && isQuery) {
                b = (byte) ' ';
            } else if (b == '%') {
                if (ix + 2 > len) {
                    throw new IllegalArgumentException(sm.getString("requestUtil.urlDecode.missingDigit"));
                }
                b = (byte) ((convertHexDigit(bytes[ix++]) << 4) + convertHexDigit(bytes[ix++]));
            }
            bytes[ox++] = b;
        }
        if (enc != null) {
            try {
                return new String(bytes, 0, ox, B2CConverter.getCharset(enc));
            } catch (UnsupportedEncodingException uee) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("requestUtil.urlDecode.uee", enc), uee);
                }
                return null;
            }
        }
        return new String(bytes, 0, ox);
    }

    /**
     * Convert a byte character value to hexadecimal digit value.
     *
     * @param b the character value byte
     */
    private static byte convertHexDigit(byte b) {
        if ((b >= '0') && (b <= '9'))
            return (byte) (b - '0');
        if ((b >= 'a') && (b <= 'f'))
            return (byte) (b - 'a' + 10);
        if ((b >= 'A') && (b <= 'F'))
            return (byte) (b - 'A' + 10);
        throw new IllegalArgumentException(sm.getString("requestUtil.convertHexDigit.notHex", Character.valueOf((char) b)));
    }

    /**
     * Put name and value pair in map.  When name already exist, add value
     * to array of values.
     *
     * @param map The map to populate
     * @param name The parameter name
     * @param value The parameter value
     */
    private static void putMapEntry(Map<String, String[]> map, String name, String value) {
        String[] newValues = null;
        String[] oldValues = map.get(name);
        if (oldValues == null) {
            newValues = new String[1];
            newValues[0] = value;
        } else {
            newValues = new String[oldValues.length + 1];
            System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
            newValues[oldValues.length] = value;
        }
        map.put(name, newValues);
    }

    /**
     * Append request parameters from the specified String to the specified
     * Map.  It is presumed that the specified Map is not accessed from any
     * other thread, so no synchronization is performed.
     * <p>
     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
     * individually on the parsed name and value elements, rather than on
     * the entire query string ahead of time, to properly deal with the case
     * where the name or value includes an encoded "=" or "&" character
     * that would otherwise be interpreted as a delimiter.
     *
     * NOTE: byte array data is modified by this method.  Caller beware.
     *
     * @param map Map that acreplacedulates the resulting parameters
     * @param data Input string containing request parameters
     * @param encoding The encoding to use; if null, the default encoding is
     * used
     *
     * @exception UnsupportedEncodingException if the requested encoding is not
     * supported.
     */
    public static void parseParameters(Map<String, String[]> map, byte[] data, String encoding) throws UnsupportedEncodingException {
        Charset charset = B2CConverter.getCharset(encoding);
        if (data != null && data.length > 0) {
            int ix = 0;
            int ox = 0;
            String key = null;
            String value = null;
            while (ix < data.length) {
                byte c = data[ix++];
                switch((char) c) {
                    case '&':
                        value = new String(data, 0, ox, charset);
                        if (key != null) {
                            putMapEntry(map, key, value);
                            key = null;
                        }
                        ox = 0;
                        break;
                    case '=':
                        if (key == null) {
                            key = new String(data, 0, ox, charset);
                            ox = 0;
                        } else {
                            data[ox++] = c;
                        }
                        break;
                    case '+':
                        data[ox++] = (byte) ' ';
                        break;
                    case '%':
                        data[ox++] = (byte) ((convertHexDigit(data[ix++]) << 4) + convertHexDigit(data[ix++]));
                        break;
                    default:
                        data[ox++] = c;
                }
            }
            // The last value does not end in '&'.  So save it now.
            if (key != null) {
                value = new String(data, 0, ox, charset);
                putMapEntry(map, key, value);
            }
        }
    }
}

19 Source : ParameterMap.java
with Apache License 2.0
from wangyingjie

/**
 * Extended implementation of <strong>HashMap</strong> that includes a
 * <code>locked</code> property.  This clreplaced can be used to safely expose
 * Catalina internal parameter map objects to user clreplacedes without having
 * to clone them in order to avoid modifications.  When first created, a
 * <code>ParmaeterMap</code> instance is not locked.
 *
 * @author Craig R. McClanahan
 */
public final clreplaced ParameterMap<K, V> extends LinkedHashMap<K, V> {

    private static final long serialVersionUID = 1L;

    // ----------------------------------------------------------- Constructors
    /**
     * Construct a new, empty map with the default initial capacity and
     * load factor.
     */
    public ParameterMap() {
        super();
    }

    /**
     * Construct a new, empty map with the specified initial capacity and
     * default load factor.
     *
     * @param initialCapacity The initial capacity of this map
     */
    public ParameterMap(int initialCapacity) {
        super(initialCapacity);
    }

    /**
     * Construct a new, empty map with the specified initial capacity and
     * load factor.
     *
     * @param initialCapacity The initial capacity of this map
     * @param loadFactor The load factor of this map
     */
    public ParameterMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
    }

    /**
     * Construct a new map with the same mappings as the given map.
     *
     * @param map Map whose contents are duplicated in the new map
     */
    public ParameterMap(Map<K, V> map) {
        super(map);
    }

    // ------------------------------------------------------------- Properties
    /**
     * The current lock state of this parameter map.
     */
    private boolean locked = false;

    /**
     * Return the locked state of this parameter map.
     */
    public boolean isLocked() {
        return (this.locked);
    }

    /**
     * Set the locked state of this parameter map.
     *
     * @param locked The new locked state
     */
    public void setLocked(boolean locked) {
        this.locked = locked;
    }

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");

    // --------------------------------------------------------- Public Methods
    /**
     * Remove all mappings from this map.
     *
     * @exception IllegalStateException if this map is currently locked
     */
    @Override
    public void clear() {
        if (locked)
            throw new IllegalStateException(sm.getString("parameterMap.locked"));
        super.clear();
    }

    /**
     * replacedociate the specified value with the specified key in this map.  If
     * the map previously contained a mapping for this key, the old value is
     * replaced.
     *
     * @param key Key with which the specified value is to be replacedociated
     * @param value Value to be replacedociated with the specified key
     *
     * @return The previous value replacedociated with the specified key, or
     *  <code>null</code> if there was no mapping for key
     *
     * @exception IllegalStateException if this map is currently locked
     */
    @Override
    public V put(K key, V value) {
        if (locked)
            throw new IllegalStateException(sm.getString("parameterMap.locked"));
        return (super.put(key, value));
    }

    /**
     * Copy all of the mappings from the specified map to this one.  These
     * mappings replace any mappings that this map had for any of the keys
     * currently in the specified Map.
     *
     * @param map Mappings to be stored into this map
     *
     * @exception IllegalStateException if this map is currently locked
     */
    @Override
    public void putAll(Map<? extends K, ? extends V> map) {
        if (locked)
            throw new IllegalStateException(sm.getString("parameterMap.locked"));
        super.putAll(map);
    }

    /**
     * Remove the mapping for this key from the map if present.
     *
     * @param key Key whose mapping is to be removed from the map
     *
     * @return The previous value replacedociated with the specified key, or
     *  <code>null</code> if there was no mapping for that key
     *
     * @exception IllegalStateException if this map is currently locked
     */
    @Override
    public V remove(Object key) {
        if (locked)
            throw new IllegalStateException(sm.getString("parameterMap.locked"));
        return (super.remove(key));
    }
}

19 Source : Introspection.java
with Apache License 2.0
from wangyingjie

/**
 * Provides introspection utilities that either require knowledge of Tomcat
 * internals or are solely used by Tomcat internals.
 */
public clreplaced Introspection {

    private static StringManager sm = StringManager.getManager("org.apache.catalina.util");

    /**
     * Extract the Java Bean property name from the setter name.
     *
     * Note: This method replacedumes that the method name has already been checked
     *       for correctness.
     */
    public static String getPropertyName(Method setter) {
        return Introspector.decapitalize(setter.getName().substring(3));
    }

    /**
     * Determines if a method has a valid name and signature for a Java Bean
     * setter.
     *
     * @param method    The method to test
     *
     * @return  <code>true</code> if the method does have a valid name and
     *          signature, else <code>false</code>
     */
    public static boolean isValidSetter(Method method) {
        if (method.getName().startsWith("set") && method.getName().length() > 3 && method.getParameterTypes().length == 1 && method.getReturnType().getName().equals("void")) {
            return true;
        }
        return false;
    }

    /**
     * Determines if a method is a valid lifecycle callback method.
     *
     * @param method
     *            The method to test
     *
     * @return <code>true</code> if the method is a valid lifecycle callback
     *         method, else <code>false</code>
     */
    public static boolean isValidLifecycleCallback(Method method) {
        if (method.getParameterTypes().length != 0 || Modifier.isStatic(method.getModifiers()) || method.getExceptionTypes().length > 0 || !method.getReturnType().getName().equals("void")) {
            return false;
        }
        return true;
    }

    /**
     * Obtain the declared fields for a clreplaced taking account of any security
     * manager that may be configured.
     */
    public static Field[] getDeclaredFields(final Clreplaced<?> clazz) {
        Field[] fields = null;
        if (Globals.IS_SECURITY_ENABLED) {
            fields = AccessController.doPrivileged(new PrivilegedAction<Field[]>() {

                @Override
                public Field[] run() {
                    return clazz.getDeclaredFields();
                }
            });
        } else {
            fields = clazz.getDeclaredFields();
        }
        return fields;
    }

    /**
     * Obtain the declared methods for a clreplaced taking account of any security
     * manager that may be configured.
     */
    public static Method[] getDeclaredMethods(final Clreplaced<?> clazz) {
        Method[] methods = null;
        if (Globals.IS_SECURITY_ENABLED) {
            methods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {

                @Override
                public Method[] run() {
                    return clazz.getDeclaredMethods();
                }
            });
        } else {
            methods = clazz.getDeclaredMethods();
        }
        return methods;
    }

    /**
     * Attempt to load a clreplaced using the given Container's clreplaced loader. If the
     * clreplaced cannot be loaded, a debug level log message will be written to the
     * Container's log and null will be returned.
     */
    public static Clreplaced<?> loadClreplaced(Container container, String clreplacedName) {
        ClreplacedLoader cl = container.getLoader().getClreplacedLoader();
        Log log = container.getLogger();
        Clreplaced<?> clazz = null;
        try {
            clazz = cl.loadClreplaced(clreplacedName);
        } catch (ClreplacedNotFoundException e) {
            log.debug(sm.getString("introspection.clreplacedLoadFailed", clreplacedName), e);
        } catch (NoClreplacedDefFoundError e) {
            log.debug(sm.getString("introspection.clreplacedLoadFailed", clreplacedName), e);
        } catch (ClreplacedFormatError e) {
            log.debug(sm.getString("introspection.clreplacedLoadFailed", clreplacedName), e);
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            log.debug(sm.getString("introspection.clreplacedLoadFailed", clreplacedName), t);
        }
        return clazz;
    }

    /**
     * Converts the primitive type to its corresponding wrapper.
     *
     * @param clazz
     *            Clreplaced that will be evaluated
     * @return if the parameter is a primitive type returns its wrapper;
     *         otherwise returns the same clreplaced
     */
    public static Clreplaced<?> convertPrimitiveType(Clreplaced<?> clazz) {
        if (clazz.equals(char.clreplaced)) {
            return Character.clreplaced;
        } else if (clazz.equals(int.clreplaced)) {
            return Integer.clreplaced;
        } else if (clazz.equals(boolean.clreplaced)) {
            return Boolean.clreplaced;
        } else if (clazz.equals(double.clreplaced)) {
            return Double.clreplaced;
        } else if (clazz.equals(byte.clreplaced)) {
            return Byte.clreplaced;
        } else if (clazz.equals(short.clreplaced)) {
            return Short.clreplaced;
        } else if (clazz.equals(long.clreplaced)) {
            return Long.clreplaced;
        } else if (clazz.equals(float.clreplaced)) {
            return Float.clreplaced;
        } else {
            return clazz;
        }
    }
}

19 Source : ExtensionValidator.java
with Apache License 2.0
from wangyingjie

/**
 * Ensures that all extension dependencies are resolved for a WEB application
 * are met. This clreplaced builds a master list of extensions available to an
 * application and then validates those extensions.
 *
 * See http://docs.oracle.com/javase/1.4.2/docs/guide/extensions/spec.html
 * for a detailed explanation of the extension mechanism in Java.
 *
 * @author Greg Murray
 * @author Justyna Horwat
 */
public final clreplaced ExtensionValidator {

    private static final org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(ExtensionValidator.clreplaced);

    /**
     * The string resources for this package.
     */
    private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");

    private static volatile ArrayList<Extension> containerAvailableExtensions = null;

    private static ArrayList<ManifestResource> containerManifestResources = new ArrayList<ManifestResource>();

    // ----------------------------------------------------- Static Initializer
    /**
     *  This static initializer loads the container level extensions that are
     *  available to all web applications. This method scans all extension
     *  directories available via the "java.ext.dirs" System property.
     *
     *  The System Clreplaced-Path is also scanned for jar files that may contain
     *  available extensions.
     */
    static {
        // check for container level optional packages
        String systemClreplacedpath = System.getProperty("java.clreplaced.path");
        StringTokenizer strTok = new StringTokenizer(systemClreplacedpath, File.pathSeparator);
        // build a list of jar files in the clreplacedpath
        while (strTok.hasMoreTokens()) {
            String clreplacedpathItem = strTok.nextToken();
            if (clreplacedpathItem.toLowerCase(Locale.ENGLISH).endsWith(".jar")) {
                File item = new File(clreplacedpathItem);
                if (item.isFile()) {
                    try {
                        addSystemResource(item);
                    } catch (IOException e) {
                        log.error(sm.getString("extensionValidator.failload", item), e);
                    }
                }
            }
        }
        // add specified folders to the list
        addFolderList("java.ext.dirs");
    }

    // --------------------------------------------------------- Public Methods
    /**
     * Runtime validation of a Web Application.
     *
     * This method uses JNDI to look up the resources located under a
     * <code>DirContext</code>. It locates Web Application MANIFEST.MF
     * file in the /META-INF/ directory of the application and all
     * MANIFEST.MF files in each JAR file located in the WEB-INF/lib
     * directory and creates an <code>ArrayList</code> of
     * <code>ManifestResorce<code> objects. These objects are then preplaceded
     * to the validateManifestResources method for validation.
     *
     * @param dirContext The JNDI root of the Web Application
     * @param context The context from which the Logger and path to the
     *                application
     *
     * @return true if all required extensions satisfied
     */
    public static synchronized boolean validateApplication(DirContext dirContext, Context context) throws IOException {
        String appName = context.getName();
        ArrayList<ManifestResource> appManifestResources = new ArrayList<ManifestResource>();
        // If the application context is null it does not exist and
        // therefore is not valid
        if (dirContext == null)
            return false;
        // Find the Manifest for the Web Application
        InputStream inputStream = null;
        try {
            NamingEnumeration<Binding> wne = dirContext.listBindings("/META-INF/");
            Binding binding = wne.nextElement();
            if (binding.getName().toUpperCase(Locale.ENGLISH).equals("MANIFEST.MF")) {
                Resource resource = (Resource) dirContext.lookup("/META-INF/" + binding.getName());
                inputStream = resource.streamContent();
                Manifest manifest = new Manifest(inputStream);
                inputStream.close();
                inputStream = null;
                ManifestResource mre = new ManifestResource(sm.getString("extensionValidator.web-application-manifest"), manifest, ManifestResource.WAR);
                appManifestResources.add(mre);
            }
        } catch (NamingException nex) {
        // Application does not contain a MANIFEST.MF file
        } catch (NoSuchElementException nse) {
        // Application does not contain a MANIFEST.MF file
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                }
            }
        }
        // Locate the Manifests for all bundled JARs
        NamingEnumeration<Binding> ne = null;
        // Primarily used for error reporting
        String jarName = null;
        try {
            ne = dirContext.listBindings("WEB-INF/lib/");
            while ((ne != null) && ne.hasMoreElements()) {
                Binding binding = ne.nextElement();
                jarName = binding.getName();
                if (!jarName.toLowerCase(Locale.ENGLISH).endsWith(".jar")) {
                    continue;
                }
                Object obj = dirContext.lookup("/WEB-INF/lib/" + jarName);
                if (!(obj instanceof Resource)) {
                    // Probably a directory named xxx.jar - ignore it
                    continue;
                }
                Resource resource = (Resource) obj;
                inputStream = resource.streamContent();
                Manifest jmanifest = getManifest(inputStream);
                if (jmanifest != null) {
                    ManifestResource mre = new ManifestResource(jarName, jmanifest, ManifestResource.APPLICATION);
                    appManifestResources.add(mre);
                }
            }
        } catch (NamingException nex) {
        // Jump out of the check for this application because it
        // has no resources
        } catch (IOException ioe) {
            throw new IOException("Jar: " + jarName, ioe);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                }
            }
        }
        return validateManifestResources(appName, appManifestResources);
    }

    /**
     * Checks to see if the given system JAR file contains a MANIFEST, and adds
     * it to the container's manifest resources.
     *
     * @param jarFile The system JAR whose manifest to add
     */
    public static void addSystemResource(File jarFile) throws IOException {
        InputStream is = null;
        try {
            is = new FileInputStream(jarFile);
            Manifest manifest = getManifest(is);
            if (manifest != null) {
                ManifestResource mre = new ManifestResource(jarFile.getAbsolutePath(), manifest, ManifestResource.SYSTEM);
                containerManifestResources.add(mre);
            }
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
        }
    }

    // -------------------------------------------------------- Private Methods
    /**
     * Validates a <code>ArrayList</code> of <code>ManifestResource</code>
     * objects. This method requires an application name (which is the
     * context root of the application at runtime).
     *
     * <code>false</false> is returned if the extension dependencies
     * represented by any given <code>ManifestResource</code> objects
     * is not met.
     *
     * This method should also provide static validation of a Web Application
     * if provided with the necessary parameters.
     *
     * @param appName The name of the Application that will appear in the
     *                error messages
     * @param resources A list of <code>ManifestResource</code> objects
     *                  to be validated.
     *
     * @return true if manifest resource file requirements are met
     */
    private static boolean validateManifestResources(String appName, ArrayList<ManifestResource> resources) {
        boolean preplacedes = true;
        int failureCount = 0;
        ArrayList<Extension> availableExtensions = null;
        Iterator<ManifestResource> it = resources.iterator();
        while (it.hasNext()) {
            ManifestResource mre = it.next();
            ArrayList<Extension> requiredList = mre.getRequiredExtensions();
            if (requiredList == null) {
                continue;
            }
            // build the list of available extensions if necessary
            if (availableExtensions == null) {
                availableExtensions = buildAvailableExtensionsList(resources);
            }
            // load the container level resource map if it has not been built
            // yet
            if (containerAvailableExtensions == null) {
                containerAvailableExtensions = buildAvailableExtensionsList(containerManifestResources);
            }
            // iterate through the list of required extensions
            Iterator<Extension> rit = requiredList.iterator();
            while (rit.hasNext()) {
                boolean found = false;
                Extension requiredExt = rit.next();
                // check the application itself for the extension
                if (availableExtensions != null) {
                    Iterator<Extension> ait = availableExtensions.iterator();
                    while (ait.hasNext()) {
                        Extension targetExt = ait.next();
                        if (targetExt.isCompatibleWith(requiredExt)) {
                            requiredExt.setFulfilled(true);
                            found = true;
                            break;
                        }
                    }
                }
                // check the container level list for the extension
                if (!found && containerAvailableExtensions != null) {
                    Iterator<Extension> cit = containerAvailableExtensions.iterator();
                    while (cit.hasNext()) {
                        Extension targetExt = cit.next();
                        if (targetExt.isCompatibleWith(requiredExt)) {
                            requiredExt.setFulfilled(true);
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    // Failure
                    log.info(sm.getString("extensionValidator.extension-not-found-error", appName, mre.getResourceName(), requiredExt.getExtensionName()));
                    preplacedes = false;
                    failureCount++;
                }
            }
        }
        if (!preplacedes) {
            log.info(sm.getString("extensionValidator.extension-validation-error", appName, failureCount + ""));
        }
        return preplacedes;
    }

    /* 
    * Build this list of available extensions so that we do not have to 
    * re-build this list every time we iterate through the list of required 
    * extensions. All available extensions in all of the 
    * <code>MainfestResource</code> objects will be added to a 
    * <code>HashMap</code> which is returned on the first dependency list
    * processing preplaced. 
    *
    * The key is the name + implementation version.
    *
    * NOTE: A list is built only if there is a dependency that needs 
    * to be checked (performance optimization).
    *
    * @param resources A list of <code>ManifestResource</code> objects
    *
    * @return HashMap Map of available extensions
    */
    private static ArrayList<Extension> buildAvailableExtensionsList(ArrayList<ManifestResource> resources) {
        ArrayList<Extension> availableList = null;
        Iterator<ManifestResource> it = resources.iterator();
        while (it.hasNext()) {
            ManifestResource mre = it.next();
            ArrayList<Extension> list = mre.getAvailableExtensions();
            if (list != null) {
                Iterator<Extension> values = list.iterator();
                while (values.hasNext()) {
                    Extension ext = values.next();
                    if (availableList == null) {
                        availableList = new ArrayList<Extension>();
                        availableList.add(ext);
                    } else {
                        availableList.add(ext);
                    }
                }
            }
        }
        return availableList;
    }

    /**
     * Return the Manifest from a jar file or war file
     *
     * @param inStream Input stream to a WAR or JAR file
     * @return The WAR's or JAR's manifest
     */
    private static Manifest getManifest(InputStream inStream) throws IOException {
        Manifest manifest = null;
        JarInputStream jin = null;
        try {
            jin = new JarInputStream(inStream);
            manifest = jin.getManifest();
            jin.close();
            jin = null;
        } finally {
            if (jin != null) {
                try {
                    jin.close();
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                }
            }
        }
        return manifest;
    }

    /**
     * Add the JARs specified to the extension list.
     */
    private static void addFolderList(String property) {
        // get the files in the extensions directory
        String extensionsDir = System.getProperty(property);
        if (extensionsDir != null) {
            StringTokenizer extensionsTok = new StringTokenizer(extensionsDir, File.pathSeparator);
            while (extensionsTok.hasMoreTokens()) {
                File targetDir = new File(extensionsTok.nextToken());
                if (!targetDir.isDirectory()) {
                    continue;
                }
                File[] files = targetDir.listFiles();
                if (files == null) {
                    continue;
                }
                for (int i = 0; i < files.length; i++) {
                    if (files[i].getName().toLowerCase(Locale.ENGLISH).endsWith(".jar") && files[i].isFile()) {
                        try {
                            addSystemResource(files[i]);
                        } catch (IOException e) {
                            log.error(sm.getString("extensionValidator.failload", files[i]), e);
                        }
                    }
                }
            }
        }
    }
}

19 Source : WebAnnotationSet.java
with Apache License 2.0
from wangyingjie

/**
 * <p><strong>AnnotationSet</strong> for processing the annotations of the web application
 * clreplacedes (<code>/WEB-INF/clreplacedes</code> and <code>/WEB-INF/lib</code>).</p>
 *
 * @author Fabien Carrion
 */
public clreplaced WebAnnotationSet {

    private static final String SEPARATOR = "/";

    /**
     * The string resources for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    // --------------------------------------------------------- Public Methods
    /**
     * Process the annotations on a context.
     */
    public static void loadApplicationAnnotations(Context context) {
        loadApplicationListenerAnnotations(context);
        loadApplicationFilterAnnotations(context);
        loadApplicationServletAnnotations(context);
    }

    // -------------------------------------------------------- protected Methods
    /**
     * Process the annotations for the listeners.
     */
    protected static void loadApplicationListenerAnnotations(Context context) {
        Clreplaced<?> clreplacedClreplaced = null;
        String[] applicationListeners = context.findApplicationListeners();
        for (int i = 0; i < applicationListeners.length; i++) {
            clreplacedClreplaced = Introspection.loadClreplaced(context, applicationListeners[i]);
            if (clreplacedClreplaced == null) {
                continue;
            }
            loadClreplacedAnnotation(context, clreplacedClreplaced);
            loadFieldsAnnotation(context, clreplacedClreplaced);
            loadMethodsAnnotation(context, clreplacedClreplaced);
        }
    }

    /**
     * Process the annotations for the filters.
     */
    protected static void loadApplicationFilterAnnotations(Context context) {
        Clreplaced<?> clreplacedClreplaced = null;
        FilterDef[] filterDefs = context.findFilterDefs();
        for (int i = 0; i < filterDefs.length; i++) {
            clreplacedClreplaced = Introspection.loadClreplaced(context, (filterDefs[i]).getFilterClreplaced());
            if (clreplacedClreplaced == null) {
                continue;
            }
            loadClreplacedAnnotation(context, clreplacedClreplaced);
            loadFieldsAnnotation(context, clreplacedClreplaced);
            loadMethodsAnnotation(context, clreplacedClreplaced);
        }
    }

    /**
     * Process the annotations for the servlets.
     */
    protected static void loadApplicationServletAnnotations(Context context) {
        Wrapper wrapper = null;
        Clreplaced<?> clreplacedClreplaced = null;
        Container[] children = context.findChildren();
        for (int i = 0; i < children.length; i++) {
            if (children[i] instanceof Wrapper) {
                wrapper = (Wrapper) children[i];
                if (wrapper.getServletClreplaced() == null) {
                    continue;
                }
                clreplacedClreplaced = Introspection.loadClreplaced(context, wrapper.getServletClreplaced());
                if (clreplacedClreplaced == null) {
                    continue;
                }
                loadClreplacedAnnotation(context, clreplacedClreplaced);
                loadFieldsAnnotation(context, clreplacedClreplaced);
                loadMethodsAnnotation(context, clreplacedClreplaced);
                /* Process RunAs annotation which can be only on servlets.
                 * Ref JSR 250, equivalent to the run-as element in
                 * the deployment descriptor
                 */
                RunAs annotation = clreplacedClreplaced.getAnnotation(RunAs.clreplaced);
                if (annotation != null) {
                    wrapper.setRunAs(annotation.value());
                }
            }
        }
    }

    /**
     * Process the annotations on a context for a given clreplacedName.
     */
    protected static void loadClreplacedAnnotation(Context context, Clreplaced<?> clreplacedClreplaced) {
        /* Process Resource annotation.
         * Ref JSR 250
         */
        {
            Resource annotation = clreplacedClreplaced.getAnnotation(Resource.clreplaced);
            if (annotation != null) {
                addResource(context, annotation);
            }
        }
        /* Process Resources annotation.
         * Ref JSR 250
         */
        {
            Resources annotation = clreplacedClreplaced.getAnnotation(Resources.clreplaced);
            if (annotation != null && annotation.value() != null) {
                for (Resource resource : annotation.value()) {
                    addResource(context, resource);
                }
            }
        }
        /* Process EJB annotation.
         * Ref JSR 224, equivalent to the ejb-ref or ejb-local-ref
         * element in the deployment descriptor.
        {
            EJB annotation = clreplacedClreplaced.getAnnotation(EJB.clreplaced);
            if (annotation != null) {

                if ((annotation.mappedName().length() == 0)
                        || annotation.mappedName().equals("Local")) {

                    ContextLocalEjb ejb = new ContextLocalEjb();

                    ejb.setName(annotation.name());
                    ejb.setType(annotation.beanInterface().getCanonicalName());
                    ejb.setDescription(annotation.description());

                    ejb.setHome(annotation.beanName());

                    context.getNamingResources().addLocalEjb(ejb);

                } else if (annotation.mappedName().equals("Remote")) {

                    ContextEjb ejb = new ContextEjb();

                    ejb.setName(annotation.name());
                    ejb.setType(annotation.beanInterface().getCanonicalName());
                    ejb.setDescription(annotation.description());

                    ejb.setHome(annotation.beanName());

                    context.getNamingResources().addEjb(ejb);

                }
            }
        }
        */
        /* Process WebServiceRef annotation.
         * Ref JSR 224, equivalent to the service-ref element in 
         * the deployment descriptor.
         * The service-ref registration is not implemented
        {
            WebServiceRef annotation = clreplacedClreplaced
                    .getAnnotation(WebServiceRef.clreplaced);
            if (annotation != null) {
                ContextService service = new ContextService();

                service.setName(annotation.name());
                service.setWsdlfile(annotation.wsdlLocation());

                service.setType(annotation.type().getCanonicalName());

                if (annotation.value() == null)
                    service.setServiceinterface(annotation.type()
                            .getCanonicalName());

                if (annotation.type().getCanonicalName().equals("Service"))
                    service.setServiceinterface(annotation.type()
                            .getCanonicalName());

                if (annotation.value().getCanonicalName().equals("Endpoint"))
                    service.setServiceendpoint(annotation.type()
                            .getCanonicalName());

                service.setPortlink(annotation.type().getCanonicalName());

                context.getNamingResources().addService(service);
            }
        }
        */
        /* Process DeclareRoles annotation.
         * Ref JSR 250, equivalent to the security-role element in
         * the deployment descriptor
         */
        {
            DeclareRoles annotation = clreplacedClreplaced.getAnnotation(DeclareRoles.clreplaced);
            if (annotation != null && annotation.value() != null) {
                for (String role : annotation.value()) {
                    context.addSecurityRole(role);
                }
            }
        }
    }

    protected static void loadFieldsAnnotation(Context context, Clreplaced<?> clreplacedClreplaced) {
        // Initialize the annotations
        Field[] fields = Introspection.getDeclaredFields(clreplacedClreplaced);
        if (fields != null && fields.length > 0) {
            for (Field field : fields) {
                Resource annotation = field.getAnnotation(Resource.clreplaced);
                if (annotation != null) {
                    String defaultName = clreplacedClreplaced.getName() + SEPARATOR + field.getName();
                    Clreplaced<?> defaultType = field.getType();
                    addResource(context, annotation, defaultName, defaultType);
                }
            }
        }
    }

    protected static void loadMethodsAnnotation(Context context, Clreplaced<?> clreplacedClreplaced) {
        // Initialize the annotations
        Method[] methods = Introspection.getDeclaredMethods(clreplacedClreplaced);
        if (methods != null && methods.length > 0) {
            for (Method method : methods) {
                Resource annotation = method.getAnnotation(Resource.clreplaced);
                if (annotation != null) {
                    if (!Introspection.isValidSetter(method)) {
                        throw new IllegalArgumentException(sm.getString("webAnnotationSet.invalidInjection"));
                    }
                    String defaultName = clreplacedClreplaced.getName() + SEPARATOR + Introspection.getPropertyName(method);
                    Clreplaced<?> defaultType = (method.getParameterTypes()[0]);
                    addResource(context, annotation, defaultName, defaultType);
                }
            }
        }
    }

    /**
     * Process a Resource annotation to set up a Resource.
     * Ref JSR 250, equivalent to the resource-ref,
     * message-destination-ref, env-ref, resource-env-ref
     * or service-ref element in the deployment descriptor.
     */
    protected static void addResource(Context context, Resource annotation) {
        addResource(context, annotation, null, null);
    }

    protected static void addResource(Context context, Resource annotation, String defaultName, Clreplaced<?> defaultType) {
        String name = getName(annotation, defaultName);
        String type = getType(annotation, defaultType);
        if (type.equals("java.lang.String") || type.equals("java.lang.Character") || type.equals("java.lang.Integer") || type.equals("java.lang.Boolean") || type.equals("java.lang.Double") || type.equals("java.lang.Byte") || type.equals("java.lang.Short") || type.equals("java.lang.Long") || type.equals("java.lang.Float")) {
            // env-ref element
            ContextEnvironment resource = new ContextEnvironment();
            resource.setName(name);
            resource.setType(type);
            resource.setDescription(annotation.description());
            resource.setValue(annotation.mappedName());
            context.getNamingResources().addEnvironment(resource);
        } else if (type.equals("javax.xml.rpc.Service")) {
            // service-ref element
            ContextService service = new ContextService();
            service.setName(name);
            service.setWsdlfile(annotation.mappedName());
            service.setType(type);
            service.setDescription(annotation.description());
            context.getNamingResources().addService(service);
        } else if (type.equals("javax.sql.DataSource") || type.equals("javax.jms.ConnectionFactory") || type.equals("javax.jms.QueueConnectionFactory") || type.equals("javax.jms.TopicConnectionFactory") || type.equals("javax.mail.Session") || type.equals("java.net.URL") || type.equals("javax.resource.cci.ConnectionFactory") || type.equals("org.omg.CORBA_2_3.ORB") || type.endsWith("ConnectionFactory")) {
            // resource-ref element
            ContextResource resource = new ContextResource();
            resource.setName(name);
            resource.setType(type);
            if (annotation.authenticationType() == Resource.AuthenticationType.CONTAINER) {
                resource.setAuth("Container");
            } else if (annotation.authenticationType() == Resource.AuthenticationType.APPLICATION) {
                resource.setAuth("Application");
            }
            resource.setScope(annotation.shareable() ? "Shareable" : "Unshareable");
            resource.setProperty("mappedName", annotation.mappedName());
            resource.setDescription(annotation.description());
            context.getNamingResources().addResource(resource);
        } else if (type.equals("javax.jms.Queue") || type.equals("javax.jms.Topic")) {
            // message-destination-ref
            MessageDestinationRef resource = new MessageDestinationRef();
            resource.setName(name);
            resource.setType(type);
            resource.setUsage(annotation.mappedName());
            resource.setDescription(annotation.description());
            context.getNamingResources().addMessageDestinationRef(resource);
        } else if (type.equals("javax.resource.cci.InteractionSpec") || type.equals("javax.transaction.UserTransaction") || true) {
            // resource-env-ref
            ContextResourceEnvRef resource = new ContextResourceEnvRef();
            resource.setName(name);
            resource.setType(type);
            resource.setProperty("mappedName", annotation.mappedName());
            resource.setDescription(annotation.description());
            context.getNamingResources().addResourceEnvRef(resource);
        }
    }

    private static String getType(Resource annotation, Clreplaced<?> defaultType) {
        Clreplaced<?> type = annotation.type();
        if (type == null || type.equals(Object.clreplaced)) {
            if (defaultType != null) {
                type = defaultType;
            }
        }
        return Introspection.convertPrimitiveType(type).getCanonicalName();
    }

    private static String getName(Resource annotation, String defaultName) {
        String name = annotation.name();
        if (name == null || name.equals("")) {
            if (defaultName != null) {
                name = defaultName;
            }
        }
        return name;
    }
}

19 Source : VersionLoggerListener.java
with Apache License 2.0
from wangyingjie

/**
 * Logs version information on startup.
 */
public clreplaced VersionLoggerListener implements LifecycleListener {

    private static final Log log = LogFactory.getLog(VersionLoggerListener.clreplaced);

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    private boolean logArgs = true;

    private boolean logEnv = false;

    private boolean logProps = false;

    public boolean getLogArgs() {
        return logArgs;
    }

    public void setLogArgs(boolean logArgs) {
        this.logArgs = logArgs;
    }

    public boolean getLogEnv() {
        return logEnv;
    }

    public void setLogEnv(boolean logEnv) {
        this.logEnv = logEnv;
    }

    public boolean getLogProps() {
        return logProps;
    }

    public void setLogProps(boolean logProps) {
        this.logProps = logProps;
    }

    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
            log();
        }
    }

    private void log() {
        log.info(sm.getString("versionLoggerListener.serverInfo.server.version", ServerInfo.getServerInfo()));
        log.info(sm.getString("versionLoggerListener.serverInfo.server.built", ServerInfo.getServerBuilt()));
        log.info(sm.getString("versionLoggerListener.serverInfo.server.number", ServerInfo.getServerNumber()));
        log.info(sm.getString("versionLoggerListener.os.name", System.getProperty("os.name")));
        log.info(sm.getString("versionLoggerListener.os.version", System.getProperty("os.version")));
        log.info(sm.getString("versionLoggerListener.os.arch", System.getProperty("os.arch")));
        log.info(sm.getString("versionLoggerListener.java.home", System.getProperty("java.home")));
        log.info(sm.getString("versionLoggerListener.vm.version", System.getProperty("java.runtime.version")));
        log.info(sm.getString("versionLoggerListener.vm.vendor", System.getProperty("java.vm.vendor")));
        log.info(sm.getString("versionLoggerListener.catalina.base", System.getProperty("catalina.base")));
        log.info(sm.getString("versionLoggerListener.catalina.home", System.getProperty("catalina.home")));
        if (logArgs) {
            List<String> args = ManagementFactory.getRuntimeMXBean().getInputArguments();
            for (String arg : args) {
                log.info(sm.getString("versionLoggerListener.arg", arg));
            }
        }
        if (logEnv) {
            SortedMap<String, String> sortedMap = new TreeMap<String, String>(System.getenv());
            for (Map.Entry<String, String> e : sortedMap.entrySet()) {
                log.info(sm.getString("versionLoggerListener.env", e.getKey(), e.getValue()));
            }
        }
        if (logProps) {
            SortedMap<String, String> sortedMap = new TreeMap<String, String>();
            for (Map.Entry<Object, Object> e : System.getProperties().entrySet()) {
                sortedMap.put(String.valueOf(e.getKey()), String.valueOf(e.getValue()));
            }
            for (Map.Entry<String, String> e : sortedMap.entrySet()) {
                log.info(sm.getString("versionLoggerListener.prop", e.getKey(), e.getValue()));
            }
        }
    }
}

19 Source : ExpandWar.java
with Apache License 2.0
from wangyingjie

/**
 * Expand out a WAR in a Host's appBase.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 * @author Glenn L. Nielsen
 */
public clreplaced ExpandWar {

    private static final Log log = LogFactory.getLog(ExpandWar.clreplaced);

    /**
     * The string resources for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    /**
     * Expand the WAR file found at the specified URL into an unpacked
     * directory structure, and return the absolute pathname to the expanded
     * directory.
     *
     * @param host Host war is being installed for
     * @param war URL of the web application archive to be expanded
     *  (must start with "jar:")
     * @param pathname Context path name for web application
     *
     * @exception IllegalArgumentException if this is not a "jar:" URL or if the
     *            WAR file is invalid
     * @exception IOException if an input/output error was encountered
     *  during expansion
     */
    public static String expand(Host host, URL war, String pathname) throws IOException {
        // Make sure that there is no such directory already existing
        File appBase = new File(host.getAppBase());
        if (!appBase.isAbsolute()) {
            appBase = new File(System.getProperty(Globals.CATALINA_BASE_PROP), host.getAppBase());
        }
        if (!appBase.exists() || !appBase.isDirectory()) {
            throw new IOException(sm.getString("hostConfig.appBase", appBase.getAbsolutePath()));
        }
        File docBase = new File(appBase, pathname);
        if (docBase.exists()) {
            // War file is already installed
            return (docBase.getAbsolutePath());
        }
        // Create the new doreplacedent base directory
        if (!docBase.mkdir() && !docBase.isDirectory())
            throw new IOException(sm.getString("expandWar.createFailed", docBase));
        // Expand the WAR into the new doreplacedent base directory
        String canonicalDocBasePrefix = docBase.getCanonicalPath();
        if (!canonicalDocBasePrefix.endsWith(File.separator)) {
            canonicalDocBasePrefix += File.separator;
        }
        JarURLConnection juc = (JarURLConnection) war.openConnection();
        juc.setUseCaches(false);
        JarFile jarFile = null;
        InputStream input = null;
        boolean success = false;
        try {
            jarFile = juc.getJarFile();
            Enumeration<JarEntry> jarEntries = jarFile.entries();
            while (jarEntries.hasMoreElements()) {
                JarEntry jarEntry = jarEntries.nextElement();
                String name = jarEntry.getName();
                File expandedFile = new File(docBase, name);
                if (!expandedFile.getCanonicalPath().startsWith(canonicalDocBasePrefix)) {
                    // Trying to expand outside the docBase
                    // Throw an exception to stop the deployment
                    throw new IllegalArgumentException(sm.getString("expandWar.illegalPath", war, name, expandedFile.getCanonicalPath(), canonicalDocBasePrefix));
                }
                int last = name.lastIndexOf('/');
                if (last >= 0) {
                    File parent = new File(docBase, name.substring(0, last));
                    if (!parent.mkdirs() && !parent.isDirectory()) {
                        throw new IOException(sm.getString("expandWar.createFailed", parent));
                    }
                }
                if (name.endsWith("/")) {
                    continue;
                }
                input = jarFile.getInputStream(jarEntry);
                if (null == input)
                    throw new ZipException(sm.getString("expandWar.missingJarEntry", jarEntry.getName()));
                // Bugzilla 33636
                expand(input, expandedFile);
                long lastModified = jarEntry.getTime();
                if ((lastModified != -1) && (lastModified != 0)) {
                    expandedFile.setLastModified(lastModified);
                }
                input.close();
                input = null;
            }
            success = true;
        } catch (IOException e) {
            throw e;
        } finally {
            if (!success) {
                // If something went wrong, delete expanded dir to keep things
                // clean
                deleteDir(docBase);
            }
            if (input != null) {
                try {
                    input.close();
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                }
                input = null;
            }
            if (jarFile != null) {
                try {
                    jarFile.close();
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                }
                jarFile = null;
            }
        }
        // Return the absolute path to our new doreplacedent base directory
        return (docBase.getAbsolutePath());
    }

    /**
     * Validate the WAR file found at the specified URL.
     *
     * @param host Host war is being installed for
     * @param war URL of the web application archive to be validated
     *  (must start with "jar:")
     * @param pathname Context path name for web application
     *
     * @exception IllegalArgumentException if this is not a "jar:" URL or if the
     *            WAR file is invalid
     * @exception IOException if an input/output error was encountered
     *            during validation
     */
    public static void validate(Host host, URL war, String pathname) throws IOException {
        // Make the appBase absolute
        File appBase = new File(host.getAppBase());
        if (!appBase.isAbsolute()) {
            appBase = new File(System.getProperty(Globals.CATALINA_BASE_PROP), host.getAppBase());
        }
        File docBase = new File(appBase, pathname);
        // Calculate the doreplacedent base directory
        String canonicalDocBasePrefix = docBase.getCanonicalPath();
        if (!canonicalDocBasePrefix.endsWith(File.separator)) {
            canonicalDocBasePrefix += File.separator;
        }
        JarURLConnection juc = (JarURLConnection) war.openConnection();
        juc.setUseCaches(false);
        JarFile jarFile = null;
        try {
            jarFile = juc.getJarFile();
            Enumeration<JarEntry> jarEntries = jarFile.entries();
            while (jarEntries.hasMoreElements()) {
                JarEntry jarEntry = jarEntries.nextElement();
                String name = jarEntry.getName();
                File expandedFile = new File(docBase, name);
                if (!expandedFile.getCanonicalPath().startsWith(canonicalDocBasePrefix)) {
                    // Entry located outside the docBase
                    // Throw an exception to stop the deployment
                    throw new IllegalArgumentException(sm.getString("expandWar.illegalPath", war, name, expandedFile.getCanonicalPath(), canonicalDocBasePrefix));
                }
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (jarFile != null) {
                try {
                    jarFile.close();
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                }
                jarFile = null;
            }
        }
    }

    /**
     * Copy the specified file or directory to the destination.
     *
     * @param src File object representing the source
     * @param dest File object representing the destination
     */
    public static boolean copy(File src, File dest) {
        boolean result = true;
        String[] files = null;
        if (src.isDirectory()) {
            files = src.list();
            result = dest.mkdir();
        } else {
            files = new String[1];
            files[0] = "";
        }
        if (files == null) {
            files = new String[0];
        }
        for (int i = 0; (i < files.length) && result; i++) {
            File fileSrc = new File(src, files[i]);
            File fileDest = new File(dest, files[i]);
            if (fileSrc.isDirectory()) {
                result = copy(fileSrc, fileDest);
            } else {
                FileChannel ic = null;
                FileChannel oc = null;
                try {
                    ic = (new FileInputStream(fileSrc)).getChannel();
                    oc = (new FileOutputStream(fileDest)).getChannel();
                    ic.transferTo(0, ic.size(), oc);
                } catch (IOException e) {
                    log.error(sm.getString("expandWar.copy", fileSrc, fileDest), e);
                    result = false;
                } finally {
                    if (ic != null) {
                        try {
                            ic.close();
                        } catch (IOException e) {
                        }
                    }
                    if (oc != null) {
                        try {
                            oc.close();
                        } catch (IOException e) {
                        }
                    }
                }
            }
        }
        return result;
    }

    /**
     * Delete the specified directory, including all of its contents and
     * sub-directories recursively. Any failure will be logged.
     *
     * @param dir File object representing the directory to be deleted
     */
    public static boolean delete(File dir) {
        // Log failure by default
        return delete(dir, true);
    }

    /**
     * Delete the specified directory, including all of its contents and
     * sub-directories recursively.
     *
     * @param dir File object representing the directory to be deleted
     * @param logFailure <code>true</code> if failure to delete the resource
     *                   should be logged
     */
    public static boolean delete(File dir, boolean logFailure) {
        boolean result;
        if (dir.isDirectory()) {
            result = deleteDir(dir, logFailure);
        } else {
            if (dir.exists()) {
                result = dir.delete();
            } else {
                result = true;
            }
        }
        if (logFailure && !result) {
            log.error(sm.getString("expandWar.deleteFailed", dir.getAbsolutePath()));
        }
        return result;
    }

    /**
     * Delete the specified directory, including all of its contents and
     * sub-directories recursively. Any failure will be logged.
     *
     * @param dir File object representing the directory to be deleted
     */
    public static boolean deleteDir(File dir) {
        return deleteDir(dir, true);
    }

    /**
     * Delete the specified directory, including all of its contents and
     * sub-directories recursively.
     *
     * @param dir File object representing the directory to be deleted
     * @param logFailure <code>true</code> if failure to delete the resource
     *                   should be logged
     */
    public static boolean deleteDir(File dir, boolean logFailure) {
        String[] files = dir.list();
        if (files == null) {
            files = new String[0];
        }
        for (int i = 0; i < files.length; i++) {
            File file = new File(dir, files[i]);
            if (file.isDirectory()) {
                deleteDir(file, logFailure);
            } else {
                file.delete();
            }
        }
        boolean result;
        if (dir.exists()) {
            result = dir.delete();
        } else {
            result = true;
        }
        if (logFailure && !result) {
            log.error(sm.getString("expandWar.deleteFailed", dir.getAbsolutePath()));
        }
        return result;
    }

    /**
     * Expand the specified input stream into the specified file.
     *
     * @param input InputStream to be copied
     * @param file The file to be created
     *
     * @exception IOException if an input/output error occurs
     */
    private static void expand(InputStream input, File file) throws IOException {
        BufferedOutputStream output = null;
        try {
            output = new BufferedOutputStream(new FileOutputStream(file));
            byte[] buffer = new byte[2048];
            while (true) {
                int n = input.read(buffer);
                if (n <= 0)
                    break;
                output.write(buffer, 0, n);
            }
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                // Ignore
                }
            }
        }
    }
}

19 Source : EngineConfig.java
with Apache License 2.0
from wangyingjie

/**
 * Startup event listener for a <b>Engine</b> that configures the properties
 * of that Engine, and the replacedociated defined contexts.
 *
 * @author Craig R. McClanahan
 */
public clreplaced EngineConfig implements LifecycleListener {

    private static final Log log = LogFactory.getLog(EngineConfig.clreplaced);

    // ----------------------------------------------------- Instance Variables
    /**
     * The Engine we are replacedociated with.
     */
    protected Engine engine = null;

    /**
     * The string resources for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    // --------------------------------------------------------- Public Methods
    /**
     * Process the START event for an replacedociated Engine.
     *
     * @param event The lifecycle event that has occurred
     */
    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        // Identify the engine we are replacedociated with
        try {
            engine = (Engine) event.getLifecycle();
        } catch (ClreplacedCastException e) {
            log.error(sm.getString("engineConfig.cce", event.getLifecycle()), e);
            return;
        }
        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.START_EVENT))
            start();
        else if (event.getType().equals(Lifecycle.STOP_EVENT))
            stop();
    }

    // -------------------------------------------------------- Protected Methods
    /**
     * Process a "start" event for this Engine.
     */
    protected void start() {
        if (engine.getLogger().isDebugEnabled())
            engine.getLogger().debug(sm.getString("engineConfig.start"));
    }

    /**
     * Process a "stop" event for this Engine.
     */
    protected void stop() {
        if (engine.getLogger().isDebugEnabled())
            engine.getLogger().debug(sm.getString("engineConfig.stop"));
    }
}

19 Source : JAASCallbackHandler.java
with Apache License 2.0
from wangyingjie

/**
 * <p>Implementation of the JAAS <code>CallbackHandler</code> interface,
 * used to negotiate delivery of the username and credentials that were
 * specified to our constructor.  No interaction with the user is required
 * (or possible).</p>
 *
 * <p>This <code>CallbackHandler</code> will pre-digest the supplied
 * preplacedword, if required by the <code><Realm></code> element in
 * <code>server.xml</code>.</p>
 * <p>At present, <code>JAASCallbackHandler</code> knows how to handle callbacks of
 * type <code>javax.security.auth.callback.NameCallback</code> and
 * <code>javax.security.auth.callback.PreplacedwordCallback</code>.</p>
 *
 * @author Craig R. McClanahan
 * @author Andrew R. Jaquith
 */
public clreplaced JAASCallbackHandler implements CallbackHandler {

    // ------------------------------------------------------------ Constructor
    /**
     * Construct a callback handler configured with the specified values.
     * Note that if the <code>JAASRealm</code> instance specifies digested preplacedwords,
     * the <code>preplacedword</code> parameter will be pre-digested here.
     *
     * @param realm Our replacedociated JAASRealm instance
     * @param username Username to be authenticated with
     * @param preplacedword Preplacedword to be authenticated with
     */
    public JAASCallbackHandler(JAASRealm realm, String username, String preplacedword) {
        super();
        this.realm = realm;
        this.username = username;
        if (realm.hasMessageDigest()) {
            this.preplacedword = realm.digest(preplacedword);
        } else {
            this.preplacedword = preplacedword;
        }
    }

    /**
     * Construct a callback handler for DIGEST authentication.
     *
     * @param realm         Our replacedociated JAASRealm instance
     * @param username      Username to be authenticated with
     * @param preplacedword      Preplacedword to be authenticated with
     * @param nonce         Server generated nonce
     * @param nc            Nonce count
     * @param cnonce        Client generated nonce
     * @param qop           Quality of protection applied to the message
     * @param realmName     Realm name
     * @param md5a2         Second MD5 digest used to calculate the digest
     *                      MD5(Method + ":" + uri)
     * @param authMethod    The authentication method in use
     */
    public JAASCallbackHandler(JAASRealm realm, String username, String preplacedword, String nonce, String nc, String cnonce, String qop, String realmName, String md5a2, String authMethod) {
        this(realm, username, preplacedword);
        this.nonce = nonce;
        this.nc = nc;
        this.cnonce = cnonce;
        this.qop = qop;
        this.realmName = realmName;
        this.md5a2 = md5a2;
        this.authMethod = authMethod;
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    /**
     * The preplacedword to be authenticated with.
     */
    protected String preplacedword = null;

    /**
     * The replacedociated <code>JAASRealm</code> instance.
     */
    protected JAASRealm realm = null;

    /**
     * The username to be authenticated with.
     */
    protected String username = null;

    /**
     * Server generated nonce.
     */
    protected String nonce = null;

    /**
     * Nonce count.
     */
    protected String nc = null;

    /**
     * Client generated nonce.
     */
    protected String cnonce = null;

    /**
     * Quality of protection applied to the message.
     */
    protected String qop;

    /**
     * Realm name.
     */
    protected String realmName;

    /**
     * Second MD5 digest.
     */
    protected String md5a2;

    /**
     * The authentication method to be used. If null, replacedume BASIC/FORM.
     */
    protected String authMethod;

    // --------------------------------------------------------- Public Methods
    /**
     * Retrieve the information requested in the provided <code>Callbacks</code>.
     * This implementation only recognizes {@link NameCallback},
     * {@link PreplacedwordCallback} and {@link TextInputCallback}.
     * {@link TextInputCallback} is used to preplaced the various additional
     * parameters required for DIGEST authentication.
     *
     * @param callbacks The set of <code>Callback</code>s to be processed
     *
     * @exception IOException if an input/output error occurs
     * @exception UnsupportedCallbackException if the login method requests
     *  an unsupported callback type
     */
    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
            if (callbacks[i] instanceof NameCallback) {
                if (realm.getContainer().getLogger().isTraceEnabled())
                    realm.getContainer().getLogger().trace(sm.getString("jaasCallback.username", username));
                ((NameCallback) callbacks[i]).setName(username);
            } else if (callbacks[i] instanceof PreplacedwordCallback) {
                final char[] preplacedwordcontents;
                if (preplacedword != null) {
                    preplacedwordcontents = preplacedword.toCharArray();
                } else {
                    preplacedwordcontents = new char[0];
                }
                ((PreplacedwordCallback) callbacks[i]).setPreplacedword(preplacedwordcontents);
            } else if (callbacks[i] instanceof TextInputCallback) {
                TextInputCallback cb = ((TextInputCallback) callbacks[i]);
                if (cb.getPrompt().equals("nonce")) {
                    cb.setText(nonce);
                } else if (cb.getPrompt().equals("nc")) {
                    cb.setText(nc);
                } else if (cb.getPrompt().equals("cnonce")) {
                    cb.setText(cnonce);
                } else if (cb.getPrompt().equals("qop")) {
                    cb.setText(qop);
                } else if (cb.getPrompt().equals("realmName")) {
                    cb.setText(realmName);
                } else if (cb.getPrompt().equals("md5a2")) {
                    cb.setText(md5a2);
                } else if (cb.getPrompt().equals("authMethod")) {
                    cb.setText(authMethod);
                } else {
                    throw new UnsupportedCallbackException(callbacks[i]);
                }
            } else {
                throw new UnsupportedCallbackException(callbacks[i]);
            }
        }
    }
}

19 Source : JmxRemoteLifecycleListener.java
with Apache License 2.0
from wangyingjie

/**
 * This listener fixes the port used by JMX/RMI Server making things much
 * simpler if you need to connect jconsole or similar to a remote Tomcat
 * instance that is running behind a firewall. Only the ports are configured via
 * the listener. The remainder of the configuration is via the standard system
 * properties for configuring JMX.
 */
public clreplaced JmxRemoteLifecycleListener implements LifecycleListener {

    private static final Log log = LogFactory.getLog(JmxRemoteLifecycleListener.clreplaced);

    protected static final StringManager sm = StringManager.getManager(JmxRemoteLifecycleListener.clreplaced);

    protected String rmiBindAddress = null;

    protected int rmiRegistryPortPlatform = -1;

    protected int rmiServerPortPlatform = -1;

    protected boolean rmiRegistrySSL = true;

    protected boolean rmiServerSSL = true;

    protected String[] ciphers = null;

    protected String[] protocols = null;

    protected boolean clientAuth = true;

    protected boolean authenticate = true;

    protected String preplacedwordFile = null;

    protected String loginModuleName = null;

    protected String accessFile = null;

    protected boolean useLocalPorts = false;

    protected JMXConnectorServer csPlatform = null;

    /**
     * Get the inet address on which the Platform RMI server is exported.
     * @return The textual representation of inet address
     */
    public String getRmiBindAddress() {
        return rmiBindAddress;
    }

    /**
     * Set the inet address on which the Platform RMI server is exported.
     * @param theRmiBindAddress The textual representation of inet address
     */
    public void setRmiBindAddress(String theRmiBindAddress) {
        rmiBindAddress = theRmiBindAddress;
    }

    /**
     * Get the port on which the Platform RMI server is exported. This is the
     * port that is normally chosen by the RMI stack.
     * @return The port number
     */
    public int getRmiServerPortPlatform() {
        return rmiServerPortPlatform;
    }

    /**
     * Set the port on which the Platform RMI server is exported. This is the
     * port that is normally chosen by the RMI stack.
     * @param theRmiServerPortPlatform The port number
     */
    public void setRmiServerPortPlatform(int theRmiServerPortPlatform) {
        rmiServerPortPlatform = theRmiServerPortPlatform;
    }

    /**
     * Get the port on which the Platform RMI registry is exported.
     * @return The port number
     */
    public int getRmiRegistryPortPlatform() {
        return rmiRegistryPortPlatform;
    }

    /**
     * Set the port on which the Platform RMI registry is exported.
     * @param theRmiRegistryPortPlatform The port number
     */
    public void setRmiRegistryPortPlatform(int theRmiRegistryPortPlatform) {
        rmiRegistryPortPlatform = theRmiRegistryPortPlatform;
    }

    /**
     * Get the flag that indicates that local ports should be used for all
     * connections. If using SSH tunnels, or similar, this should be set to
     * true to ensure the RMI client uses the tunnel.
     * @return <code>true</code> if local ports should be used
     */
    public boolean getUseLocalPorts() {
        return useLocalPorts;
    }

    /**
     * Set the flag that indicates that local ports should be used for all
     * connections. If using SSH tunnels, or similar, this should be set to
     * true to ensure the RMI client uses the tunnel.
     * @param useLocalPorts Set to <code>true</code> if local ports should be
     *                      used
     */
    public void setUseLocalPorts(boolean useLocalPorts) {
        this.useLocalPorts = useLocalPorts;
    }

    private void init() {
        // Get all the other parameters required from the standard system
        // properties. Only need to get the parameters that affect the creation
        // of the server port.
        String rmiRegistrySSLValue = System.getProperty("com.sun.management.jmxremote.registry.ssl", "false");
        rmiRegistrySSL = Boolean.parseBoolean(rmiRegistrySSLValue);
        String rmiServerSSLValue = System.getProperty("com.sun.management.jmxremote.ssl", "true");
        rmiServerSSL = Boolean.parseBoolean(rmiServerSSLValue);
        String protocolsValue = System.getProperty("com.sun.management.jmxremote.ssl.enabled.protocols");
        if (protocolsValue != null) {
            protocols = protocolsValue.split(",");
        }
        String ciphersValue = System.getProperty("com.sun.management.jmxremote.ssl.enabled.cipher.suites");
        if (ciphersValue != null) {
            ciphers = ciphersValue.split(",");
        }
        String clientAuthValue = System.getProperty("com.sun.management.jmxremote.ssl.need.client.auth", "true");
        clientAuth = Boolean.parseBoolean(clientAuthValue);
        String authenticateValue = System.getProperty("com.sun.management.jmxremote.authenticate", "true");
        authenticate = Boolean.parseBoolean(authenticateValue);
        preplacedwordFile = System.getProperty("com.sun.management.jmxremote.preplacedword.file", "jmxremote.preplacedword");
        accessFile = System.getProperty("com.sun.management.jmxremote.access.file", "jmxremote.access");
        loginModuleName = System.getProperty("com.sun.management.jmxremote.login.config");
    }

    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        // When the server starts, configure JMX/RMI
        if (Lifecycle.START_EVENT.equals(event.getType())) {
            // Configure using standard jmx system properties
            init();
            // Prevent an attacker guessing the RMI object ID
            System.setProperty("java.rmi.server.randomIDs", "true");
            // Create the environment
            HashMap<String, Object> env = new HashMap<String, Object>();
            RMIClientSocketFactory registryCsf = null;
            RMIServerSocketFactory registrySsf = null;
            RMIClientSocketFactory serverCsf = null;
            RMIServerSocketFactory serverSsf = null;
            // Configure registry socket factories
            if (rmiRegistrySSL) {
                registryCsf = new SslRMIClientSocketFactory();
                if (rmiBindAddress == null) {
                    registrySsf = new SslRMIServerSocketFactory(ciphers, protocols, clientAuth);
                } else {
                    registrySsf = new SslRmiServerBindSocketFactory(ciphers, protocols, clientAuth, rmiBindAddress);
                }
            } else {
                if (rmiBindAddress != null) {
                    registrySsf = new RmiServerBindSocketFactory(rmiBindAddress);
                }
            }
            // Configure server socket factories
            if (rmiServerSSL) {
                serverCsf = new SslRMIClientSocketFactory();
                if (rmiBindAddress == null) {
                    serverSsf = new SslRMIServerSocketFactory(ciphers, protocols, clientAuth);
                } else {
                    serverSsf = new SslRmiServerBindSocketFactory(ciphers, protocols, clientAuth, rmiBindAddress);
                }
            } else {
                if (rmiBindAddress != null) {
                    serverSsf = new RmiServerBindSocketFactory(rmiBindAddress);
                }
            }
            // By default, the registry will pick an address to listen on.
            // Setting this property overrides that and ensures it listens on
            // the configured address.
            if (rmiBindAddress != null) {
                System.setProperty("java.rmi.server.hostname", rmiBindAddress);
            }
            // Force the use of local ports if required
            if (useLocalPorts) {
                registryCsf = new RmiClientLocalhostSocketFactory(registryCsf);
                serverCsf = new RmiClientLocalhostSocketFactory(serverCsf);
            }
            env.put("jmx.remote.rmi.server.credential.types", new String[] { String[].clreplaced.getName(), String.clreplaced.getName() });
            // Populate the env properties used to create the server
            if (serverCsf != null) {
                env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, serverCsf);
                env.put("com.sun.jndi.rmi.factory.socket", registryCsf);
            }
            if (serverSsf != null) {
                env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverSsf);
            }
            // Configure authentication
            if (authenticate) {
                env.put("jmx.remote.x.preplacedword.file", preplacedwordFile);
                env.put("jmx.remote.x.access.file", accessFile);
                env.put("jmx.remote.x.login.config", loginModuleName);
            }
            // Create the Platform server
            csPlatform = createServer("Platform", rmiBindAddress, rmiRegistryPortPlatform, rmiServerPortPlatform, env, registryCsf, registrySsf, serverCsf, serverSsf);
        } else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
            destroyServer("Platform", csPlatform);
        }
    }

    private JMXConnectorServer createServer(String serverName, String bindAddress, int theRmiRegistryPort, int theRmiServerPort, HashMap<String, Object> theEnv, RMIClientSocketFactory registryCsf, RMIServerSocketFactory registrySsf, RMIClientSocketFactory serverCsf, RMIServerSocketFactory serverSsf) {
        // Create the RMI registry
        Registry registry;
        try {
            registry = LocateRegistry.createRegistry(theRmiRegistryPort, registryCsf, registrySsf);
        } catch (RemoteException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.createRegistryFailed", serverName, Integer.toString(theRmiRegistryPort)), e);
            return null;
        }
        if (bindAddress == null) {
            bindAddress = "localhost";
        }
        String url = "service:jmx:rmi://" + bindAddress;
        JMXServiceURL serviceUrl;
        try {
            serviceUrl = new JMXServiceURL(url);
        } catch (MalformedURLException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.invalidURL", serverName, url), e);
            return null;
        }
        RMIConnectorServer cs = null;
        try {
            RMIJRMPServerImpl server = new RMIJRMPServerImpl(rmiServerPortPlatform, serverCsf, serverSsf, theEnv);
            cs = new RMIConnectorServer(serviceUrl, theEnv, server, ManagementFactory.getPlatformMBeanServer());
            cs.start();
            registry.bind("jmxrmi", server.toStub());
            log.info(sm.getString("jmxRemoteLifecycleListener.start", Integer.toString(theRmiRegistryPort), Integer.toString(theRmiServerPort), serverName));
        } catch (IOException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.createServerFailed", serverName), e);
        } catch (AlreadyBoundException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.createServerFailed", serverName), e);
        }
        return cs;
    }

    private void destroyServer(String serverName, JMXConnectorServer theConnectorServer) {
        if (theConnectorServer != null) {
            try {
                theConnectorServer.stop();
            } catch (IOException e) {
                log.error(sm.getString("jmxRemoteLifecycleListener.destroyServerFailed", serverName), e);
            }
        }
    }

    public static clreplaced RmiClientLocalhostSocketFactory implements RMIClientSocketFactory, Serializable {

        private static final long serialVersionUID = 1L;

        private static final String FORCED_HOST = "localhost";

        private final RMIClientSocketFactory factory;

        public RmiClientLocalhostSocketFactory(RMIClientSocketFactory theFactory) {
            factory = theFactory;
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException {
            if (factory == null) {
                return new Socket(FORCED_HOST, port);
            } else {
                return factory.createSocket(FORCED_HOST, port);
            }
        }
    }

    public static clreplaced RmiServerBindSocketFactory implements RMIServerSocketFactory {

        private final InetAddress bindAddress;

        public RmiServerBindSocketFactory(String address) {
            InetAddress bindAddress = null;
            try {
                bindAddress = InetAddress.getByName(address);
            } catch (UnknownHostException e) {
                log.error(sm.getString("jmxRemoteLifecycleListener.invalidRmiBindAddress", address), e);
            // bind address will be null which means any/all local addresses
            // which should be safe
            }
            this.bindAddress = bindAddress;
        }

        @Override
        public ServerSocket createServerSocket(int port) throws IOException {
            return new ServerSocket(port, 0, bindAddress);
        }
    }

    public static clreplaced SslRmiServerBindSocketFactory extends SslRMIServerSocketFactory {

        private static final SSLServerSocketFactory sslServerSocketFactory;

        private static final String[] defaultProtocols;

        static {
            SSLContext sslContext;
            try {
                sslContext = SSLContext.getDefault();
            } catch (NoSuchAlgorithmException e) {
                // Can't continue. Force a failure.
                throw new IllegalStateException(e);
            }
            sslServerSocketFactory = sslContext.getServerSocketFactory();
            String[] protocols = sslContext.getDefaultSSLParameters().getProtocols();
            List<String> filteredProtocols = new ArrayList<String>(protocols.length);
            for (String protocol : protocols) {
                if (protocol.toUpperCase(Locale.ENGLISH).contains("SSL")) {
                    continue;
                }
                filteredProtocols.add(protocol);
            }
            defaultProtocols = filteredProtocols.toArray(new String[filteredProtocols.size()]);
        }

        private final InetAddress bindAddress;

        public SslRmiServerBindSocketFactory(String[] enabledCipherSuites, String[] enabledProtocols, boolean needClientAuth, String address) {
            super(enabledCipherSuites, enabledProtocols, needClientAuth);
            InetAddress bindAddress = null;
            try {
                bindAddress = InetAddress.getByName(address);
            } catch (UnknownHostException e) {
                log.error(sm.getString("jmxRemoteLifecycleListener.invalidRmiBindAddress", address), e);
            // bind address will be null which means any/all local addresses
            // which should be safe
            }
            this.bindAddress = bindAddress;
        }

        @Override
        public ServerSocket createServerSocket(int port) throws IOException {
            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port, 0, bindAddress);
            if (getEnabledCipherSuites() != null) {
                sslServerSocket.setEnabledCipherSuites(getEnabledCipherSuites());
            }
            if (getEnabledProtocols() == null) {
                sslServerSocket.setEnabledProtocols(defaultProtocols);
            } else {
                sslServerSocket.setEnabledProtocols(getEnabledProtocols());
            }
            sslServerSocket.setNeedClientAuth(getNeedClientAuth());
            return sslServerSocket;
        }
    }
}

19 Source : DeltaRequest.java
with Apache License 2.0
from wangyingjie

public clreplaced DeltaRequest implements Externalizable {

    public static final org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(DeltaRequest.clreplaced);

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    public static final int TYPE_ATTRIBUTE = 0;

    public static final int TYPE_PRINCIPAL = 1;

    public static final int TYPE_ISNEW = 2;

    public static final int TYPE_MAXINTERVAL = 3;

    public static final int TYPE_AUTHTYPE = 4;

    public static final int TYPE_LISTENER = 5;

    public static final int ACTION_SET = 0;

    public static final int ACTION_REMOVE = 1;

    public static final String NAME_PRINCIPAL = "__SET__PRINCIPAL__";

    public static final String NAME_MAXINTERVAL = "__SET__MAXINTERVAL__";

    public static final String NAME_ISNEW = "__SET__ISNEW__";

    public static final String NAME_AUTHTYPE = "__SET__AUTHTYPE__";

    public static final String NAME_LISTENER = "__SET__LISTENER__";

    private String sessionId;

    private LinkedList<AttributeInfo> actions = new LinkedList<AttributeInfo>();

    private LinkedList<AttributeInfo> actionPool = new LinkedList<AttributeInfo>();

    private boolean recordAllActions = false;

    public DeltaRequest() {
    }

    public DeltaRequest(String sessionId, boolean recordAllActions) {
        this.recordAllActions = recordAllActions;
        if (sessionId != null)
            setSessionId(sessionId);
    }

    public void setAttribute(String name, Object value) {
        int action = (value == null) ? ACTION_REMOVE : ACTION_SET;
        addAction(TYPE_ATTRIBUTE, action, name, value);
    }

    public void removeAttribute(String name) {
        int action = ACTION_REMOVE;
        addAction(TYPE_ATTRIBUTE, action, name, null);
    }

    public void setMaxInactiveInterval(int interval) {
        int action = ACTION_SET;
        addAction(TYPE_MAXINTERVAL, action, NAME_MAXINTERVAL, Integer.valueOf(interval));
    }

    /**
     * convert principal at SerializablePrincipal for backup nodes.
     * Only support principals from type {@link GenericPrincipal GenericPrincipal}
     * @param p Session principal
     * @see GenericPrincipal
     */
    public void setPrincipal(Principal p) {
        int action = (p == null) ? ACTION_REMOVE : ACTION_SET;
        SerializablePrincipal sp = null;
        if (p != null) {
            if (p instanceof GenericPrincipal) {
                sp = SerializablePrincipal.createPrincipal((GenericPrincipal) p);
                if (log.isDebugEnabled())
                    log.debug(sm.getString("deltaRequest.showPrincipal", p.getName(), getSessionId()));
            } else
                log.error(sm.getString("deltaRequest.wrongPrincipalClreplaced", p.getClreplaced().getName()));
        }
        addAction(TYPE_PRINCIPAL, action, NAME_PRINCIPAL, sp);
    }

    public void setNew(boolean n) {
        int action = ACTION_SET;
        addAction(TYPE_ISNEW, action, NAME_ISNEW, Boolean.valueOf(n));
    }

    public void setAuthType(String authType) {
        int action = (authType == null) ? ACTION_REMOVE : ACTION_SET;
        addAction(TYPE_AUTHTYPE, action, NAME_AUTHTYPE, authType);
    }

    public void addSessionListener(SessionListener listener) {
        addAction(TYPE_LISTENER, ACTION_SET, NAME_LISTENER, listener);
    }

    public void removeSessionListener(SessionListener listener) {
        addAction(TYPE_LISTENER, ACTION_REMOVE, NAME_LISTENER, listener);
    }

    protected void addAction(int type, int action, String name, Object value) {
        AttributeInfo info = null;
        if (this.actionPool.size() > 0) {
            try {
                info = actionPool.removeFirst();
            } catch (Exception x) {
                log.error("Unable to remove element:", x);
                info = new AttributeInfo(type, action, name, value);
            }
            info.init(type, action, name, value);
        } else {
            info = new AttributeInfo(type, action, name, value);
        }
        // if we have already done something to this attribute, make sure
        // we don't send multiple actions across the wire
        if (!recordAllActions) {
            try {
                actions.remove(info);
            } catch (java.util.NoSuchElementException x) {
            // do nothing, we wanted to remove it anyway
            }
        }
        // add the action
        actions.addLast(info);
    }

    public void execute(DeltaSession session, boolean notifyListeners) {
        if (!this.sessionId.equals(session.getId()))
            throw new java.lang.IllegalArgumentException("Session id mismatch, not executing the delta request");
        session.access();
        for (int i = 0; i < actions.size(); i++) {
            AttributeInfo info = actions.get(i);
            switch(info.getType()) {
                case TYPE_ATTRIBUTE:
                    if (info.getAction() == ACTION_SET) {
                        if (log.isTraceEnabled())
                            log.trace("Session.setAttribute('" + info.getName() + "', '" + info.getValue() + "')");
                        session.setAttribute(info.getName(), info.getValue(), notifyListeners, false);
                    } else {
                        if (log.isTraceEnabled())
                            log.trace("Session.removeAttribute('" + info.getName() + "')");
                        session.removeAttribute(info.getName(), notifyListeners, false);
                    }
                    break;
                case TYPE_ISNEW:
                    if (log.isTraceEnabled())
                        log.trace("Session.setNew('" + info.getValue() + "')");
                    session.setNew(((Boolean) info.getValue()).booleanValue(), false);
                    break;
                case TYPE_MAXINTERVAL:
                    if (log.isTraceEnabled())
                        log.trace("Session.setMaxInactiveInterval('" + info.getValue() + "')");
                    session.setMaxInactiveInterval(((Integer) info.getValue()).intValue(), false);
                    break;
                case TYPE_PRINCIPAL:
                    Principal p = null;
                    if (info.getAction() == ACTION_SET) {
                        SerializablePrincipal sp = (SerializablePrincipal) info.getValue();
                        p = sp.getPrincipal();
                    }
                    session.setPrincipal(p, false);
                    break;
                case TYPE_AUTHTYPE:
                    String authType = null;
                    if (info.getAction() == ACTION_SET) {
                        authType = (String) info.getValue();
                    }
                    session.setAuthType(authType, false);
                    break;
                case TYPE_LISTENER:
                    SessionListener listener = (SessionListener) info.getValue();
                    if (info.getAction() == ACTION_SET) {
                        session.addSessionListener(listener, false);
                    } else {
                        session.removeSessionListener(listener, false);
                    }
                    break;
                default:
                    throw new java.lang.IllegalArgumentException("Invalid attribute info type=" + info);
            }
        // switch
        }
        // for
        session.endAccess();
        reset();
    }

    public void reset() {
        while (actions.size() > 0) {
            try {
                AttributeInfo info = actions.removeFirst();
                info.recycle();
                actionPool.addLast(info);
            } catch (Exception x) {
                log.error("Unable to remove element", x);
            }
        }
        actions.clear();
    }

    public String getSessionId() {
        return sessionId;
    }

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
        if (sessionId == null) {
            new Exception("Session Id is null for setSessionId").fillInStackTrace().printStackTrace();
        }
    }

    public int getSize() {
        return actions.size();
    }

    public void clear() {
        actions.clear();
        actionPool.clear();
    }

    @Override
    public void readExternal(java.io.ObjectInput in) throws IOException, ClreplacedNotFoundException {
        // sessionId - String
        // recordAll - boolean
        // size - int
        // AttributeInfo - in an array
        reset();
        sessionId = in.readUTF();
        recordAllActions = in.readBoolean();
        int cnt = in.readInt();
        if (actions == null)
            actions = new LinkedList<AttributeInfo>();
        else
            actions.clear();
        for (int i = 0; i < cnt; i++) {
            AttributeInfo info = null;
            if (this.actionPool.size() > 0) {
                try {
                    info = actionPool.removeFirst();
                } catch (Exception x) {
                    log.error("Unable to remove element", x);
                    info = new AttributeInfo();
                }
            } else {
                info = new AttributeInfo();
            }
            info.readExternal(in);
            actions.addLast(info);
        }
    // for
    }

    @Override
    public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
        // sessionId - String
        // recordAll - boolean
        // size - int
        // AttributeInfo - in an array
        out.writeUTF(getSessionId());
        out.writeBoolean(recordAllActions);
        out.writeInt(getSize());
        for (int i = 0; i < getSize(); i++) {
            AttributeInfo info = actions.get(i);
            info.writeExternal(out);
        }
    }

    /**
     * serialize DeltaRequest
     * @see DeltaRequest#writeExternal(java.io.ObjectOutput)
     *
     * @return serialized delta request
     * @throws IOException
     */
    protected byte[] serialize() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        writeExternal(oos);
        oos.flush();
        oos.close();
        return bos.toByteArray();
    }

    private static clreplaced AttributeInfo implements java.io.Externalizable {

        private String name = null;

        private Object value = null;

        private int action;

        private int type;

        public AttributeInfo() {
            this(-1, -1, null, null);
        }

        public AttributeInfo(int type, int action, String name, Object value) {
            super();
            init(type, action, name, value);
        }

        public void init(int type, int action, String name, Object value) {
            this.name = name;
            this.value = value;
            this.action = action;
            this.type = type;
        }

        public int getType() {
            return type;
        }

        public int getAction() {
            return action;
        }

        public Object getValue() {
            return value;
        }

        @Override
        public int hashCode() {
            return name.hashCode();
        }

        public String getName() {
            return name;
        }

        public void recycle() {
            name = null;
            value = null;
            type = -1;
            action = -1;
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof AttributeInfo))
                return false;
            AttributeInfo other = (AttributeInfo) o;
            return other.getName().equals(this.getName());
        }

        @Override
        public void readExternal(java.io.ObjectInput in) throws IOException, ClreplacedNotFoundException {
            // type - int
            // action - int
            // name - String
            // hasvalue - boolean
            // value - object
            type = in.readInt();
            action = in.readInt();
            name = in.readUTF();
            boolean hasValue = in.readBoolean();
            if (hasValue)
                value = in.readObject();
        }

        @Override
        public void writeExternal(java.io.ObjectOutput out) throws IOException {
            // type - int
            // action - int
            // name - String
            // hasvalue - boolean
            // value - object
            out.writeInt(getType());
            out.writeInt(getAction());
            out.writeUTF(getName());
            out.writeBoolean(getValue() != null);
            if (getValue() != null)
                out.writeObject(getValue());
        }

        @Override
        public String toString() {
            StringBuilder buf = new StringBuilder("AttributeInfo[type=");
            buf.append(getType()).append(", action=").append(getAction());
            buf.append(", name=").append(getName()).append(", value=").append(getValue());
            buf.append(", addr=").append(super.toString()).append("]");
            return buf.toString();
        }
    }
}

19 Source : FilterBase.java
with Apache License 2.0
from wangyingjie

/**
 * Base clreplaced for filters that provides generic initialisation and a simple
 * no-op destruction.
 *
 * @author xxd
 */
public abstract clreplaced FilterBase implements Filter {

    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    protected abstract Log getLogger();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Enumeration<String> paramNames = filterConfig.getInitParameterNames();
        while (paramNames.hasMoreElements()) {
            String paramName = paramNames.nextElement();
            if (!IntrospectionUtils.setProperty(this, paramName, filterConfig.getInitParameter(paramName))) {
                String msg = sm.getString("filterbase.noSuchProperty", paramName, this.getClreplaced().getName());
                if (isConfigProblemFatal()) {
                    throw new ServletException(msg);
                } else {
                    getLogger().warn(msg);
                }
            }
        }
    }

    @Override
    public void destroy() {
    // NOOP
    }

    /**
     * Determines if an exception when calling a setter or an unknown
     * configuration attribute triggers the failure of the this filter which in
     * turn will prevent the web application from starting.
     *
     * @return <code>true</code> if a problem should trigger the failure of this
     *         filter, else <code>false</code>
     */
    protected boolean isConfigProblemFatal() {
        return false;
    }
}

19 Source : ThreadLocalLeakPreventionListener.java
with Apache License 2.0
from wangyingjie

/**
 * <p>
 * A {@link LifecycleListener} that triggers the renewal of threads in Executor
 * pools when a {@link Context} is being stopped to avoid thread-local related
 * memory leaks.
 * </p>
 * <p>
 * Note : active threads will be renewed one by one when they come back to the
 * pool after executing their task, see
 * {@link org.apache.tomcat.util.threads.ThreadPoolExecutor}.afterExecute().
 * </p>
 *
 * This listener must be declared in server.xml to be active.
 */
public clreplaced ThreadLocalLeakPreventionListener implements LifecycleListener, ContainerListener {

    private static final Log log = LogFactory.getLog(ThreadLocalLeakPreventionListener.clreplaced);

    private volatile boolean serverStopping = false;

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    /**
     * Listens for {@link LifecycleEvent} for the start of the {@link Server} to
     * initialize itself and then for after_stop events of each {@link Context}.
     */
    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        try {
            Lifecycle lifecycle = event.getLifecycle();
            if (Lifecycle.AFTER_START_EVENT.equals(event.getType()) && lifecycle instanceof Server) {
                // when the server starts, we register ourself as listener for
                // all context
                // as well as container event listener so that we know when new
                // Context are deployed
                Server server = (Server) lifecycle;
                registerListenersForServer(server);
            }
            if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType()) && lifecycle instanceof Server) {
                // Server is shutting down, so thread pools will be shut down so
                // there is no need to clean the threads
                serverStopping = true;
            }
            if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType()) && lifecycle instanceof Context) {
                stopIdleThreads((Context) lifecycle);
            }
        } catch (Exception e) {
            String msg = sm.getString("threadLocalLeakPreventionListener.lifecycleEvent.error", event);
            log.error(msg, e);
        }
    }

    @Override
    public void containerEvent(ContainerEvent event) {
        try {
            String type = event.getType();
            if (Container.ADD_CHILD_EVENT.equals(type)) {
                processContainerAddChild(event.getContainer(), (Container) event.getData());
            } else if (Container.REMOVE_CHILD_EVENT.equals(type)) {
                processContainerRemoveChild(event.getContainer(), (Container) event.getData());
            }
        } catch (Exception e) {
            String msg = sm.getString("threadLocalLeakPreventionListener.containerEvent.error", event);
            log.error(msg, e);
        }
    }

    private void registerListenersForServer(Server server) {
        for (Service service : server.findServices()) {
            Engine engine = (Engine) service.getContainer();
            engine.addContainerListener(this);
            registerListenersForEngine(engine);
        }
    }

    private void registerListenersForEngine(Engine engine) {
        for (Container hostContainer : engine.findChildren()) {
            Host host = (Host) hostContainer;
            host.addContainerListener(this);
            registerListenersForHost(host);
        }
    }

    private void registerListenersForHost(Host host) {
        for (Container contextContainer : host.findChildren()) {
            Context context = (Context) contextContainer;
            registerContextListener(context);
        }
    }

    private void registerContextListener(Context context) {
        context.addLifecycleListener(this);
    }

    protected void processContainerAddChild(Container parent, Container child) {
        if (log.isDebugEnabled())
            log.debug("Process addChild[parent=" + parent + ",child=" + child + "]");
        if (child instanceof Context) {
            registerContextListener((Context) child);
        } else if (child instanceof Engine) {
            registerListenersForEngine((Engine) child);
        } else if (child instanceof Host) {
            registerListenersForHost((Host) child);
        }
    }

    protected void processContainerRemoveChild(Container parent, Container child) {
        if (log.isDebugEnabled())
            log.debug("Process removeChild[parent=" + parent + ",child=" + child + "]");
        if (child instanceof Context) {
            Context context = (Context) child;
            context.removeLifecycleListener(this);
        } else if (child instanceof Host || child instanceof Engine) {
            child.removeContainerListener(this);
        }
    }

    /**
     * Updates each ThreadPoolExecutor with the current time, which is the time
     * when a context is being stopped.
     *
     * @param context
     *            the context being stopped, used to discover all the Connectors
     *            of its parent Service.
     */
    private void stopIdleThreads(Context context) {
        if (serverStopping)
            return;
        if (!(context instanceof StandardContext) || !((StandardContext) context).getRenewThreadsWhenStoppingContext()) {
            log.debug("Not renewing threads when the context is stopping. " + "It is not configured to do it.");
            return;
        }
        Engine engine = (Engine) context.getParent().getParent();
        Service service = engine.getService();
        Connector[] connectors = service.findConnectors();
        if (connectors != null) {
            for (Connector connector : connectors) {
                ProtocolHandler handler = connector.getProtocolHandler();
                Executor executor = null;
                if (handler != null) {
                    executor = handler.getExecutor();
                }
                if (executor instanceof ThreadPoolExecutor) {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                    threadPoolExecutor.contextStopping();
                } else if (executor instanceof StandardThreadExecutor) {
                    StandardThreadExecutor stdThreadExecutor = (StandardThreadExecutor) executor;
                    stdThreadExecutor.contextStopping();
                }
            }
        }
    }
}

19 Source : StandardWrapperValve.java
with Apache License 2.0
from wangyingjie

/**
 * Valve that implements the default basic behavior for the
 * <code>StandardWrapper</code> container implementation.
 *
 * @author Craig R. McClanahan
 */
final clreplaced StandardWrapperValve extends ValveBase {

    // ------------------------------------------------------ Constructor
    public StandardWrapperValve() {
        super(true);
    }

    // ----------------------------------------------------- Instance Variables
    // Some JMX statistics. This valve is replacedociated with a StandardWrapper.
    // We expose the StandardWrapper as JMX ( j2eeType=Servlet ). The fields
    // are here for performance.
    private volatile long processingTime;

    private volatile long maxTime;

    private volatile long minTime = Long.MAX_VALUE;

    private volatile int requestCount;

    private volatile int errorCount;

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    // --------------------------------------------------------- Public Methods
    /**
     * Invoke the servlet we are managing, respecting the rules regarding
     * servlet lifecycle and SingleThreadModel support.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     *
     * Wrapper 里面就包装了 Servlet 的相关信息,最终会调用的 servlet 的 service 的处理接口
     */
    @Override
    public final void invoke(Request request, Response response) throws IOException, ServletException {
        // Initialize local variables we may need
        boolean unavailable = false;
        Throwable throwable = null;
        // This should be a Request attribute...
        long t1 = System.currentTimeMillis();
        requestCount++;
        // 获取容器
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        Servlet servlet = null;
        // 获取Context
        Context context = (Context) wrapper.getParent();
        // Check for the application being marked unavailable
        if (!context.getState().isAvailable()) {
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardContext.isUnavailable"));
            unavailable = true;
        }
        // Check for the servlet being marked unavailable
        if (!unavailable && wrapper.isUnavailable()) {
            // set  response  的部分属性
            container.getLogger().info(sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE)) {
                response.setDateHeader("Retry-After", available);
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            } else if (available == Long.MAX_VALUE) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
            }
            unavailable = true;
        }
        // Allocate a servlet instance to process this request
        try {
            if (!unavailable) {
                // allocate ['æləkeɪt] vt. 分配;拨出;使坐落于
                // TODO 获取 WEB 容器的 servlet 处理对象
                servlet = wrapper.allocate();
            }
        } catch (UnavailableException e) {
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE)) {
                response.setDateHeader("Retry-After", available);
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            } else if (available == Long.MAX_VALUE) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
            }
        } catch (ServletException e) {
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e));
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
            servlet = null;
        }
        // Identify if the request is Comet related now that the servlet has been allocated
        boolean comet = false;
        if (servlet instanceof CometProcessor && Boolean.TRUE.equals(request.getAttribute(Globals.COMET_SUPPORTED_ATTR))) {
            comet = true;
            request.setComet(true);
        }
        MessageBytes requestPathMB = request.getRequestPathMB();
        DispatcherType dispatcherType = DispatcherType.REQUEST;
        if (request.getDispatcherType() == DispatcherType.ASYNC)
            dispatcherType = DispatcherType.ASYNC;
        request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, dispatcherType);
        request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
        // Create the filter chain for this request
        ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
        // TODO 创建过滤链
        ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);
        // Reset comet flag value after creating the filter chain
        request.setComet(false);
        // Call the filter chain for this request
        // NOTE: This also calls the servlet's service() method
        try {
            if ((servlet != null) && (filterChain != null)) {
                // todo 调用 Filter 过滤链 、Servlet 处理流程
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        if (request.isAsyncDispatching()) {
                            request.getAsyncContextInternal().doInternalDispatch();
                        } else if (comet) {
                            filterChain.doFilterEvent(request.getEvent());
                            request.setComet(true);
                        } else {
                            // todo 执行filter
                            filterChain.doFilter(request.getRequest(), response.getResponse());
                        }
                    } finally {
                        String log = SystemLogHandler.stopCapture();
                        if (log != null && log.length() > 0) {
                            context.getLogger().info(log);
                        }
                    }
                } else {
                    if (request.isAsyncDispatching()) {
                        request.getAsyncContextInternal().doInternalDispatch();
                    } else if (comet) {
                        request.setComet(true);
                        filterChain.doFilterEvent(request.getEvent());
                    } else {
                        // todo 执行filter
                        filterChain.doFilter(request.getRequest(), response.getResponse());
                    }
                }
            }
        } catch (ClientAbortException e) {
            throwable = e;
            exception(request, response, e);
        } catch (IOException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        } catch (UnavailableException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            // throwable = e;
            // exception(request, response, e);
            wrapper.unavailable(e);
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE)) {
                response.setDateHeader("Retry-After", available);
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            } else if (available == Long.MAX_VALUE) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
            }
        // Do not save exception in 'throwable', because we
        // do not want to do exception(request, response, e) processing
        } catch (ServletException e) {
            Throwable rootCause = StandardWrapper.getRootCause(e);
            if (!(rootCause instanceof ClientAbortException)) {
                container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(), context.getName(), e.getMessage()), rootCause);
            }
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        }
        // Release the filter chain (if any) for this request
        if (filterChain != null) {
            if (request.isComet()) {
                // If this is a Comet request, then the same chain will be used for the
                // processing of all subsequent events.
                filterChain.reuse();
            } else {
                filterChain.release();
            }
        }
        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                wrapper.deallocate(servlet);
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        // If this servlet has been marked permanently unavailable,
        // unload it and release this instance
        try {
            if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {
                wrapper.unload();
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        long t2 = System.currentTimeMillis();
        long time = t2 - t1;
        processingTime += time;
        if (time > maxTime)
            maxTime = time;
        if (time < minTime)
            minTime = time;
    }

    /**
     * Process a Comet event. The main differences here are to not use sendError
     * (the response is committed), to avoid creating a new filter chain
     * (which would work but be pointless), and a few very minor tweaks.
     *
     * @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
     */
    @Override
    public void event(Request request, Response response, CometEvent event) throws IOException, ServletException {
        // Initialize local variables we may need
        Throwable throwable = null;
        // This should be a Request attribute...
        long t1 = System.currentTimeMillis();
        // FIXME: Add a flag to count the total amount of events processed ? requestCount++;
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        if (wrapper == null) {
            // Context has been shutdown. Nothing to do here.
            return;
        }
        Servlet servlet = null;
        Context context = (Context) wrapper.getParent();
        // Check for the application being marked unavailable
        boolean unavailable = !context.getState().isAvailable() || wrapper.isUnavailable();
        // Allocate a servlet instance to process this request
        try {
            if (!unavailable) {
                servlet = wrapper.allocate();
            }
        } catch (UnavailableException e) {
        // The response is already committed, so it's not possible to do anything
        } catch (ServletException e) {
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e));
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
            servlet = null;
        }
        MessageBytes requestPathMB = request.getRequestPathMB();
        request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.REQUEST);
        request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
        // Get the current (unchanged) filter chain for this request
        ApplicationFilterChain filterChain = (ApplicationFilterChain) request.getFilterChain();
        // Call the filter chain for this request
        // NOTE: This also calls the servlet's event() method
        try {
            if ((servlet != null) && (filterChain != null)) {
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        filterChain.doFilterEvent(request.getEvent());
                    } finally {
                        String log = SystemLogHandler.stopCapture();
                        if (log != null && log.length() > 0) {
                            context.getLogger().info(log);
                        }
                    }
                } else {
                    filterChain.doFilterEvent(request.getEvent());
                }
            }
        } catch (ClientAbortException e) {
            throwable = e;
            exception(request, response, e);
        } catch (IOException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        } catch (UnavailableException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        // Do not save exception in 'throwable', because we
        // do not want to do exception(request, response, e) processing
        } catch (ServletException e) {
            Throwable rootCause = StandardWrapper.getRootCause(e);
            if (!(rootCause instanceof ClientAbortException)) {
                container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(), context.getName(), e.getMessage()), rootCause);
            }
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        }
        // Release the filter chain (if any) for this request
        if (filterChain != null) {
            filterChain.reuse();
        }
        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                wrapper.deallocate(servlet);
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        // If this servlet has been marked permanently unavailable,
        // unload it and release this instance
        try {
            if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {
                wrapper.unload();
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        long t2 = System.currentTimeMillis();
        long time = t2 - t1;
        processingTime += time;
        if (time > maxTime)
            maxTime = time;
        if (time < minTime)
            minTime = time;
    }

    // -------------------------------------------------------- Private Methods
    /**
     * Handle the specified ServletException encountered while processing
     * the specified Request to produce the specified Response.  Any
     * exceptions that occur during generation of the exception report are
     * logged and swallowed.
     *
     * @param request The request being processed
     * @param response The response being generated
     * @param exception The exception that occurred (which possibly wraps
     *  a root cause exception
     */
    private void exception(Request request, Response response, Throwable exception) {
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, exception);
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        response.setError();
    }

    public long getProcessingTime() {
        return processingTime;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setProcessingTime(long processingTime) {
        this.processingTime = processingTime;
    }

    public long getMaxTime() {
        return maxTime;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setMaxTime(long maxTime) {
        this.maxTime = maxTime;
    }

    public long getMinTime() {
        return minTime;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setMinTime(long minTime) {
        this.minTime = minTime;
    }

    public int getRequestCount() {
        return requestCount;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setRequestCount(int requestCount) {
        this.requestCount = requestCount;
    }

    public int getErrorCount() {
        return errorCount;
    }

    public void incrementErrorCount() {
        errorCount++;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setErrorCount(int errorCount) {
        this.errorCount = errorCount;
    }

    @Override
    protected void initInternal() throws LifecycleException {
    // NOOP - Don't register this Valve in JMX
    }
}

19 Source : StandardHostValve.java
with Apache License 2.0
from wangyingjie

/**
 * Valve that implements the default basic behavior for the
 * <code>StandardHost</code> container implementation.
 * <p>
 * <b>USAGE CONSTRAINT</b>:  This implementation is likely to be useful only
 * when processing HTTP requests.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 */
final clreplaced StandardHostValve extends ValveBase {

    private static final Log log = LogFactory.getLog(StandardHostValve.clreplaced);

    static final boolean STRICT_SERVLET_COMPLIANCE;

    static final boolean ACCESS_SESSION;

    static {
        STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
        String accessSession = System.getProperty("org.apache.catalina.core.StandardHostValve.ACCESS_SESSION");
        if (accessSession == null) {
            ACCESS_SESSION = STRICT_SERVLET_COMPLIANCE;
        } else {
            ACCESS_SESSION = Boolean.parseBoolean(accessSession);
        }
    }

    // ------------------------------------------------------ Constructor
    public StandardHostValve() {
        super(true);
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * The descriptive information related to this implementation.
     */
    private static final String info = "org.apache.catalina.core.StandardHostValve/1.0";

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    // ------------------------------------------------------------- Properties
    /**
     * Return descriptive information about this Valve implementation.
     */
    @Override
    public String getInfo() {
        return (info);
    }

    // --------------------------------------------------------- Public Methods
    /**
     * Select the appropriate child Context to process this request,
     * based on the specified request URI.  If no matching Context can
     * be found, return an appropriate HTTP error.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void invoke(Request request, Response response) throws IOException, ServletException {
        // Select the Context to be used for this Request
        Context context = request.getContext();
        if (context == null) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getString("standardHost.noContext"));
            return;
        }
        // Bind the context CL to the current thread
        if (context.getLoader() != null) {
            // Not started - it should check for availability first
            // This should eventually move to Engine, it's generic.
            if (Globals.IS_SECURITY_ENABLED) {
                PrivilegedAction<Void> pa = new PrivilegedSetTccl(context.getLoader().getClreplacedLoader());
                AccessController.doPrivileged(pa);
            } else {
                Thread.currentThread().setContextClreplacedLoader(context.getLoader().getClreplacedLoader());
            }
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(context.getPipeline().isAsyncSupported());
        }
        boolean asyncAtStart = request.isAsync();
        boolean asyncDispatching = request.isAsyncDispatching();
        if (asyncAtStart || context.fireRequestInitEvent(request)) {
            // Ask this Context to process this request. Requests that are in
            // async mode and are not being dispatched to this resource must be
            // in error and have been routed here to check for application
            // defined error pages.
            try {
                if (!asyncAtStart || asyncDispatching) {
                    // 责任链模式:将请求传递给 context 管道
                    // 从请求对象中取出该请求关联的context (默认情况下是org.apache.catalina.core.StandardContext对象),
                    // StandardContext对象 初始化的时候会设置基础阀 StandardContextValve
                    context.getPipeline().getFirst().invoke(request, response);
                } else {
                    // Make sure this request/response is here because an error
                    // report is required.
                    if (!response.isErrorReportRequired()) {
                        throw new IllegalStateException(sm.getString("standardHost.asyncStateError"));
                    }
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
                // If a new error occurred while trying to report a previous
                // error allow the original error to be reported.
                if (!response.isErrorReportRequired()) {
                    request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
                    throwable(request, response, t);
                }
            }
            // Now that the request/response pair is back under container
            // control lift the suspension so that the error handling can
            // complete and/or the container can flush any remaining data
            response.setSuspended(false);
            Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
            // Protect against NPEs if the context was destroyed during a
            // long running request.
            if (!context.getState().isAvailable()) {
                return;
            }
            // Look for (and render if found) an application level error page
            if (response.isErrorReportRequired()) {
                if (t != null) {
                    throwable(request, response, t);
                } else {
                    status(request, response);
                }
            }
            if (!request.isAsync() && (!asyncAtStart || !response.isErrorReportRequired())) {
                context.fireRequestDestroyEvent(request);
            }
        }
        // Access a session (if present) to update last accessed time, based on a
        // strict interpretation of the specification
        if (ACCESS_SESSION) {
            request.getSession(false);
        }
        // Restore the context clreplacedloader
        if (Globals.IS_SECURITY_ENABLED) {
            PrivilegedAction<Void> pa = new PrivilegedSetTccl(StandardHostValve.clreplaced.getClreplacedLoader());
            AccessController.doPrivileged(pa);
        } else {
            Thread.currentThread().setContextClreplacedLoader(StandardHostValve.clreplaced.getClreplacedLoader());
        }
    }

    /**
     * Process Comet event.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     * @param event the event
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void event(Request request, Response response, CometEvent event) throws IOException, ServletException {
        // Select the Context to be used for this Request
        Context context = request.getContext();
        // Bind the context CL to the current thread
        if (context.getLoader() != null) {
            // Not started - it should check for availability first
            // This should eventually move to Engine, it's generic.
            Thread.currentThread().setContextClreplacedLoader(context.getLoader().getClreplacedLoader());
        }
        // Ask this Context to process this request
        context.getPipeline().getFirst().event(request, response, event);
        // Error page processing
        response.setSuspended(false);
        Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
        if (t != null) {
            throwable(request, response, t);
        } else {
            status(request, response);
        }
        // Access a session (if present) to update last accessed time, based on a
        // strict interpretation of the specification
        if (ACCESS_SESSION) {
            request.getSession(false);
        }
        // Restore the context clreplacedloader
        Thread.currentThread().setContextClreplacedLoader(StandardHostValve.clreplaced.getClreplacedLoader());
    }

    // -------------------------------------------------------- Private Methods
    /**
     * Handle the HTTP status code (and corresponding message) generated
     * while processing the specified Request to produce the specified
     * Response.  Any exceptions that occur during generation of the error
     * report are logged and swallowed.
     *
     * @param request The request being processed
     * @param response The response being generated
     */
    private void status(Request request, Response response) {
        int statusCode = response.getStatus();
        // Handle a custom error page for this status code
        Context context = request.getContext();
        if (context == null)
            return;
        /* Only look for error pages when isError() is set.
         * isError() is set when response.sendError() is invoked. This
         * allows custom error pages without relying on default from
         * web.xml.
         */
        if (!response.isError())
            return;
        ErrorPage errorPage = context.findErrorPage(statusCode);
        if (errorPage == null) {
            // Look for a default error page
            errorPage = context.findErrorPage(0);
        }
        if (errorPage != null && response.isErrorReportRequired()) {
            response.setAppCommitted(false);
            request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, Integer.valueOf(statusCode));
            String message = response.getMessage();
            if (message == null)
                message = "";
            request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
            request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
            request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);
            Wrapper wrapper = request.getWrapper();
            if (wrapper != null)
                request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
            request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
            if (custom(request, response, errorPage)) {
                response.setErrorReported();
                try {
                    response.finishResponse();
                } catch (ClientAbortException e) {
                // Ignore
                } catch (IOException e) {
                    container.getLogger().warn("Exception Processing " + errorPage, e);
                }
            }
        }
    }

    /**
     * Handle the specified Throwable encountered while processing
     * the specified Request to produce the specified Response.  Any
     * exceptions that occur during generation of the exception report are
     * logged and swallowed.
     *
     * @param request The request being processed
     * @param response The response being generated
     * @param throwable The exception that occurred (which possibly wraps
     *  a root cause exception
     */
    protected void throwable(Request request, Response response, Throwable throwable) {
        Context context = request.getContext();
        if (context == null)
            return;
        Throwable realError = throwable;
        if (realError instanceof ServletException) {
            realError = ((ServletException) realError).getRootCause();
            if (realError == null) {
                realError = throwable;
            }
        }
        // If this is an aborted request from a client just log it and return
        if (realError instanceof ClientAbortException) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("standardHost.clientAbort", realError.getCause().getMessage()));
            }
            return;
        }
        ErrorPage errorPage = findErrorPage(context, throwable);
        if ((errorPage == null) && (realError != throwable)) {
            errorPage = findErrorPage(context, realError);
        }
        if (errorPage != null) {
            if (response.setErrorReported()) {
                response.setAppCommitted(false);
                request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
                request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);
                request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, Integer.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
                request.setAttribute(RequestDispatcher.ERROR_MESSAGE, throwable.getMessage());
                request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, realError);
                Wrapper wrapper = request.getWrapper();
                if (wrapper != null)
                    request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
                request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
                request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, realError.getClreplaced());
                if (custom(request, response, errorPage)) {
                    try {
                        response.finishResponse();
                    } catch (IOException e) {
                        container.getLogger().warn("Exception Processing " + errorPage, e);
                    }
                }
            }
        } else {
            // A custom error-page has not been defined for the exception
            // that was thrown during request processing. Check if an
            // error-page for error code 500 was specified and if so,
            // send that page back as the response.
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            // The response is an error
            response.setError();
            status(request, response);
        }
    }

    /**
     * Handle an HTTP status code or Java exception by forwarding control
     * to the location included in the specified errorPage object.  It is
     * replacedumed that the caller has already recorded any request attributes
     * that are to be forwarded to this page.  Return <code>true</code> if
     * we successfully utilized the specified error page location, or
     * <code>false</code> if the default error report should be rendered.
     *
     * @param request The request being processed
     * @param response The response being generated
     * @param errorPage The errorPage directive we are obeying
     */
    private boolean custom(Request request, Response response, ErrorPage errorPage) {
        if (container.getLogger().isDebugEnabled())
            container.getLogger().debug("Processing " + errorPage);
        try {
            // Forward control to the specified location
            ServletContext servletContext = request.getContext().getServletContext();
            RequestDispatcher rd = servletContext.getRequestDispatcher(errorPage.getLocation());
            if (rd == null) {
                container.getLogger().error(sm.getString("standardHostValue.customStatusFailed", errorPage.getLocation()));
                return false;
            }
            if (response.isCommitted()) {
                // Response is committed - including the error page is the
                // best we can do
                rd.include(request.getRequest(), response.getResponse());
            } else {
                // Reset the response (keeping the real error code and message)
                response.resetBuffer(true);
                response.setContentLength(-1);
                rd.forward(request.getRequest(), response.getResponse());
                // If we forward, the response is suspended again
                response.setSuspended(false);
            }
            // Indicate that we have successfully processed this custom page
            return (true);
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            // Report our failure to process this custom page
            container.getLogger().error("Exception Processing " + errorPage, t);
            return (false);
        }
    }

    /**
     * Find and return the ErrorPage instance for the specified exception's
     * clreplaced, or an ErrorPage instance for the closest superclreplaced for which
     * there is such a definition.  If no replacedociated ErrorPage instance is
     * found, return <code>null</code>.
     *
     * @param context The Context in which to search
     * @param exception The exception for which to find an ErrorPage
     */
    private static ErrorPage findErrorPage(Context context, Throwable exception) {
        if (exception == null)
            return (null);
        Clreplaced<?> clazz = exception.getClreplaced();
        String name = clazz.getName();
        while (!Object.clreplaced.equals(clazz)) {
            ErrorPage errorPage = context.findErrorPage(name);
            if (errorPage != null)
                return (errorPage);
            clazz = clazz.getSuperclreplaced();
            if (clazz == null)
                break;
            name = clazz.getName();
        }
        return (null);
    }
}

19 Source : StandardEngineValve.java
with Apache License 2.0
from wangyingjie

/**
 * Valve that implements the default basic behavior for the
 * <code>StandardEngine</code> container implementation.
 * <p>
 * <b>USAGE CONSTRAINT</b>:  This implementation is likely to be useful only
 * when processing HTTP requests.
 *
 * @author Craig R. McClanahan
 */
final clreplaced StandardEngineValve extends ValveBase {

    // ------------------------------------------------------ Constructor
    public StandardEngineValve() {
        super(true);
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * The descriptive information related to this implementation.
     */
    private static final String info = "org.apache.catalina.core.StandardEngineValve/1.0";

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    // ------------------------------------------------------------- Properties
    /**
     * Return descriptive information about this Valve implementation.
     */
    @Override
    public String getInfo() {
        return (info);
    }

    // --------------------------------------------------------- Public Methods
    /**
     * Select the appropriate child Host to process this request,
     * based on the requested server name.  If no matching Host can
     * be found, return an appropriate HTTP error.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void invoke(Request request, Response response) throws IOException, ServletException {
        // Select the Host to be used for this Request
        Host host = request.getHost();
        if (host == null) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString("standardEngine.noHost", request.getServerName()));
            return;
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(host.getPipeline().isAsyncSupported());
        }
        // 责任链模式:将请求传递给 Host 管道
        // 从请求对象中取出该请求关联的Host(默认情况下是org.apache.catalina.core.StandardHost对象),
        // StandardHost 初始化的时候会设置基础阀 StandardHostValue
        // Ask this Host to process this request
        host.getPipeline().getFirst().invoke(request, response);
    }

    /**
     * Process Comet event.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     * @param event the event
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void event(Request request, Response response, CometEvent event) throws IOException, ServletException {
        // Ask this Host to process this request
        request.getHost().getPipeline().getFirst().event(request, response, event);
    }
}

19 Source : JreMemoryLeakPreventionListener.java
with Apache License 2.0
from wangyingjie

/**
 * Provide a workaround for known places where the Java Runtime environment can
 * cause a memory leak or lock files.
 * <p>
 * Memory leaks occur when JRE code uses
 * the context clreplaced loader to load a singleton as this will cause a memory leak
 * if a web application clreplaced loader happens to be the context clreplaced loader at
 * the time. The work-around is to initialise these singletons when Tomcat's
 * common clreplaced loader is the context clreplaced loader.
 * <p>
 * Locked files usually occur when a resource inside a JAR is accessed without
 * first disabling Jar URL connection caching. The workaround is to disable this
 * caching by default.
 */
public clreplaced JreMemoryLeakPreventionListener implements LifecycleListener {

    private static final Log log = LogFactory.getLog(JreMemoryLeakPreventionListener.clreplaced);

    private static final StringManager sm = StringManager.getManager(Constants.Package);

    private static final boolean IS_JAVA_7_OR_LATER;

    static {
        boolean isJava7OrLater;
        try {
            Clreplaced.forName("java.util.Objects");
            isJava7OrLater = true;
        } catch (ClreplacedNotFoundException e) {
            isJava7OrLater = false;
        }
        IS_JAVA_7_OR_LATER = isJava7OrLater;
    }

    /**
     * Protect against the memory leak caused when the first call to
     * <code>sun.awt.AppContext.getAppContext()</code> is triggered by a web
     * application. Defaults to <code>true</code> for Java 6 and earlier (since
     * it is used by {@link java.beans.Introspector#flushCaches()}) but defaults
     * to <code>false</code> for Java 7 and later since
     * {@link java.beans.Introspector#flushCaches()} no longer uses AppContext
     * from 1.7.0_02 onwards. Also, from 1.7.0_25 onwards, calling this method
     * requires a graphical environment and starts an AWT thread.
     */
    private boolean appContextProtection = !IS_JAVA_7_OR_LATER;

    public boolean isAppContextProtection() {
        return appContextProtection;
    }

    public void setAppContextProtection(boolean appContextProtection) {
        this.appContextProtection = appContextProtection;
    }

    /**
     * Protect against the memory leak caused when the first call to
     * <code>java.awt.Toolkit.getDefaultToolkit()</code> is triggered
     * by a web application. Defaults to <code>false</code> because a new
     * Thread is launched.
     */
    private boolean awtThreadProtection = false;

    public boolean isAWTThreadProtection() {
        return awtThreadProtection;
    }

    public void setAWTThreadProtection(boolean awtThreadProtection) {
        this.awtThreadProtection = awtThreadProtection;
    }

    /**
     * Protect against the memory leak caused when the
     * <code>sun.java2d.Disposer</code> clreplaced is loaded by a web application.
     * Defaults to <code>false</code> because a new Thread is launched.
     */
    private boolean java2dDisposerProtection = false;

    public boolean isJava2DDisposerProtection() {
        return java2dDisposerProtection;
    }

    public void setJava2DDisposerProtection(boolean java2dDisposerProtection) {
        this.java2dDisposerProtection = java2dDisposerProtection;
    }

    /**
     * Protect against the memory leak caused when the first call to
     * <code>sun.misc.GC.requestLatency(long)</code> is triggered by a web
     * application. This first call will start a GC Daemon thread with the
     * thread's context clreplaced loader configured to be the web application clreplaced
     * loader. Defaults to <code>true</code>.
     */
    private boolean gcDaemonProtection = true;

    public boolean isGcDaemonProtection() {
        return gcDaemonProtection;
    }

    public void setGcDaemonProtection(boolean gcDaemonProtection) {
        this.gcDaemonProtection = gcDaemonProtection;
    }

    /**
     * Protect against the memory leak caused when the first call to
     * <code>javax.security.auth.Policy</code> is triggered by a web
     * application. This first call populate a static variable with a reference
     * to the context clreplaced loader. Defaults to <code>true</code>.
     */
    private boolean securityPolicyProtection = true;

    public boolean isSecurityPolicyProtection() {
        return securityPolicyProtection;
    }

    public void setSecurityPolicyProtection(boolean securityPolicyProtection) {
        this.securityPolicyProtection = securityPolicyProtection;
    }

    /**
     * Protects against the memory leak caused when the first call to
     * <code>javax.security.auth.login.Configuration</code> is triggered by a
     * web application. This first call populate a static variable with a
     * reference to the context clreplaced loader. Defaults to <code>true</code>.
     */
    private boolean securityLoginConfigurationProtection = true;

    public boolean isSecurityLoginConfigurationProtection() {
        return securityLoginConfigurationProtection;
    }

    public void setSecurityLoginConfigurationProtection(boolean securityLoginConfigurationProtection) {
        this.securityLoginConfigurationProtection = securityLoginConfigurationProtection;
    }

    /**
     * Protect against the memory leak, when the initialization of the
     * Java Cryptography Architecture is triggered by initializing
     * a MessageDigest during web application deployment.
     * This will occasionally start a Token Poller thread with the thread's
     * context clreplaced loader equal to the web application clreplaced loader.
     * Instead we initialize JCA early.
     * Defaults to <code>true</code>.
     */
    private boolean tokenPollerProtection = true;

    public boolean isTokenPollerProtection() {
        return tokenPollerProtection;
    }

    public void setTokenPollerProtection(boolean tokenPollerProtection) {
        this.tokenPollerProtection = tokenPollerProtection;
    }

    /**
     * Protect against resources being read for JAR files and, as a side-effect,
     * the JAR file becoming locked. Note this disables caching for all
     * {@link URLConnection}s, regardless of type. Defaults to
     * <code>true</code>.
     */
    private boolean urlCacheProtection = true;

    public boolean isUrlCacheProtection() {
        return urlCacheProtection;
    }

    public void setUrlCacheProtection(boolean urlCacheProtection) {
        this.urlCacheProtection = urlCacheProtection;
    }

    /**
     * XML parsing can pin a web application clreplaced loader in memory. There are
     * multiple root causes for this. Some of these are particularly nasty as
     * profilers may not identify any GC roots related to the leak. For example,
     * with YourKit you need to ensure that HPROF format memory snapshots are
     * used to be able to trace some of the leaks.
     */
    private boolean xmlParsingProtection = true;

    public boolean isXmlParsingProtection() {
        return xmlParsingProtection;
    }

    public void setXmlParsingProtection(boolean xmlParsingProtection) {
        this.xmlParsingProtection = xmlParsingProtection;
    }

    /**
     * <code>com.sun.jndi.ldap.LdapPoolManager</code> clreplaced spawns a thread when
     * it is initialized if the system property
     * <code>com.sun.jndi.ldap.connect.pool.timeout</code> is greater than 0.
     * That thread inherits the context clreplaced loader of the current thread, so
     * that there may be a web application clreplaced loader leak if the web app
     * is the first to use <code>LdapPoolManager</code>.
     */
    private boolean ldapPoolProtection = true;

    public boolean isLdapPoolProtection() {
        return ldapPoolProtection;
    }

    public void setLdapPoolProtection(boolean ldapPoolProtection) {
        this.ldapPoolProtection = ldapPoolProtection;
    }

    /**
     * The first access to {@link DriverManager} will trigger the loading of
     * all {@link java.sql.Driver}s in the the current clreplaced loader. The web
     * application level memory leak protection can take care of this in most
     * cases but triggering the loading here has fewer side-effects.
     */
    private boolean driverManagerProtection = true;

    public boolean isDriverManagerProtection() {
        return driverManagerProtection;
    }

    public void setDriverManagerProtection(boolean driverManagerProtection) {
        this.driverManagerProtection = driverManagerProtection;
    }

    /**
     * List of comma-separated fully qualified clreplaced names to load and initialize during
     * the startup of this Listener. This allows to pre-load clreplacedes that are known to
     * provoke clreplacedloader leaks if they are loaded during a request processing.
     */
    private String clreplacedesToInitialize = null;

    public String getClreplacedesToInitialize() {
        return clreplacedesToInitialize;
    }

    public void setClreplacedesToInitialize(String clreplacedesToInitialize) {
        this.clreplacedesToInitialize = clreplacedesToInitialize;
    }

    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        // Initialise these clreplacedes when Tomcat starts
        if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
            ClreplacedLoader loader = Thread.currentThread().getContextClreplacedLoader();
            try {
                // Use the system clreplacedloader as the victim for all this
                // ClreplacedLoader pinning we're about to do.
                Thread.currentThread().setContextClreplacedLoader(ClreplacedLoader.getSystemClreplacedLoader());
                /*
                 * First call to this loads all drivers in the current clreplaced
                 * loader
                 */
                if (driverManagerProtection) {
                    DriverManager.getDrivers();
                }
                /*
                 * Several components end up calling:
                 * sun.awt.AppContext.getAppContext()
                 * 
                 * Those libraries / components known to trigger memory leaks
                 * due to eventual calls to getAppContext() are:
                 * - Google Web Toolkit via its use of javax.imageio
                 * - Tomcat via its use of java.beans.Introspector.flushCaches()
                 *   in 1.6.0_15 to 1.7.0_01. From 1.7.0_02 onwards use of
                 *   AppContext by Introspector.flushCaches() was replaced with
                 *   ThreadGroupContext
                 * - others TBD
                 *
                 * From 1.7.0_25 onwards, a call to
                 * sun.awt.AppContext.getAppContext() results in a thread being
                 * started named AWT-AppKit that requires a graphic environment
                 * to be available.
                 */
                // Trigger a call to sun.awt.AppContext.getAppContext(). This
                // will pin the system clreplaced loader in memory but that shouldn't
                // be an issue.
                if (appContextProtection) {
                    ImageIO.getCacheDirectory();
                }
                // Trigger the creation of the AWT (AWT-Windows, AWT-XAWT,
                // etc.) thread
                if (awtThreadProtection) {
                    java.awt.Toolkit.getDefaultToolkit();
                }
                // Trigger the creation of the "Java2D Disposer" thread.
                // See https://bz.apache.org/bugzilla/show_bug.cgi?id=51687
                if (java2dDisposerProtection) {
                    try {
                        Clreplaced.forName("sun.java2d.Disposer");
                    } catch (ClreplacedNotFoundException cnfe) {
                    // Ignore this case: we must be running on a
                    // non-Sun-based JRE.
                    }
                }
                /*
                 * Several components end up calling
                 * sun.misc.GC.requestLatency(long) which creates a daemon
                 * thread without setting the TCCL.
                 * 
                 * Those libraries / components known to trigger memory leaks
                 * due to eventual calls to requestLatency(long) are:
                 * - javax.management.remote.rmi.RMIConnectorServer.start()
                 *
                 * Note: Long.MAX_VALUE is a special case that causes the thread
                 *       to terminate
                 *
                 */
                if (gcDaemonProtection) {
                    try {
                        Clreplaced<?> clazz = Clreplaced.forName("sun.misc.GC");
                        Method method = clazz.getDeclaredMethod("requestLatency", new Clreplaced[] { long.clreplaced });
                        method.invoke(null, Long.valueOf(Long.MAX_VALUE - 1));
                    } catch (ClreplacedNotFoundException e) {
                        if (JreVendor.IS_ORACLE_JVM) {
                            log.error(sm.getString("jreLeakListener.gcDaemonFail"), e);
                        } else {
                            log.debug(sm.getString("jreLeakListener.gcDaemonFail"), e);
                        }
                    } catch (SecurityException e) {
                        log.error(sm.getString("jreLeakListener.gcDaemonFail"), e);
                    } catch (NoSuchMethodException e) {
                        log.error(sm.getString("jreLeakListener.gcDaemonFail"), e);
                    } catch (IllegalArgumentException e) {
                        log.error(sm.getString("jreLeakListener.gcDaemonFail"), e);
                    } catch (IllegalAccessException e) {
                        log.error(sm.getString("jreLeakListener.gcDaemonFail"), e);
                    } catch (InvocationTargetException e) {
                        ExceptionUtils.handleThrowable(e.getCause());
                        log.error(sm.getString("jreLeakListener.gcDaemonFail"), e);
                    }
                }
                /*
                 * Calling getPolicy retains a static reference to the context 
                 * clreplaced loader.
                 */
                if (securityPolicyProtection) {
                    try {
                        // Policy.getPolicy();
                        Clreplaced<?> policyClreplaced = Clreplaced.forName("javax.security.auth.Policy");
                        Method method = policyClreplaced.getMethod("getPolicy");
                        method.invoke(null);
                    } catch (ClreplacedNotFoundException e) {
                    // Ignore. The clreplaced is deprecated.
                    } catch (SecurityException e) {
                    // Ignore. Don't need call to getPolicy() to be
                    // successful, just need to trigger static initializer.
                    } catch (NoSuchMethodException e) {
                        log.warn(sm.getString("jreLeakListener.authPolicyFail"), e);
                    } catch (IllegalArgumentException e) {
                        log.warn(sm.getString("jreLeakListener.authPolicyFail"), e);
                    } catch (IllegalAccessException e) {
                        log.warn(sm.getString("jreLeakListener.authPolicyFail"), e);
                    } catch (InvocationTargetException e) {
                        ExceptionUtils.handleThrowable(e.getCause());
                        log.warn(sm.getString("jreLeakListener.authPolicyFail"), e);
                    }
                }
                /*
                 * Initializing javax.security.auth.login.Configuration retains a static reference to the context 
                 * clreplaced loader.
                 */
                if (securityLoginConfigurationProtection) {
                    try {
                        Clreplaced.forName("javax.security.auth.login.Configuration", true, ClreplacedLoader.getSystemClreplacedLoader());
                    } catch (ClreplacedNotFoundException e) {
                    // Ignore
                    }
                }
                /*
                 * Creating a MessageDigest during web application startup
                 * initializes the Java Cryptography Architecture. Under certain
                 * conditions this starts a Token poller thread with TCCL equal
                 * to the web application clreplaced loader.
                 * 
                 * Instead we initialize JCA right now.
                 */
                if (tokenPollerProtection) {
                    java.security.Security.getProviders();
                }
                /*
                 * Several components end up opening JarURLConnections without
                 * first disabling caching. This effectively locks the file.
                 * Whilst more noticeable and harder to ignore on Windows, it
                 * affects all operating systems.
                 * 
                 * Those libraries/components known to trigger this issue
                 * include:
                 * - log4j versions 1.2.15 and earlier
                 * - javax.xml.bind.JAXBContext.newInstance()
                 */
                // Set the default URL caching policy to not to cache
                if (urlCacheProtection) {
                    try {
                        // Doesn't matter that this JAR doesn't exist - just as
                        // long as the URL is well-formed
                        URL url = new URL("jar:file://dummy.jar!/");
                        URLConnection uConn = url.openConnection();
                        uConn.setDefaultUseCaches(false);
                    } catch (MalformedURLException e) {
                        log.error(sm.getString("jreLeakListener.jarUrlConnCacheFail"), e);
                    } catch (IOException e) {
                        log.error(sm.getString("jreLeakListener.jarUrlConnCacheFail"), e);
                    }
                }
                /*
                 * Various leaks related to the use of XML parsing.
                 */
                if (xmlParsingProtection) {
                    // There are three known issues with XML parsing
                    // 1. DoreplacedentBuilderFactory.newInstance().newDoreplacedentBuilder();
                    // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6916498
                    // This issue is fixed in Java 7 onwards
                    DoreplacedentBuilderFactory factory = DoreplacedentBuilderFactory.newInstance();
                    try {
                        DoreplacedentBuilder doreplacedentBuilder = factory.newDoreplacedentBuilder();
                        // The 2nd and 3rd links both relate to cached Exception
                        // instances that retain a link to the TCCL via the
                        // backtrace field. Note that YourKit only shows this
                        // field when using the HPROF format memory snapshots.
                        // https://bz.apache.org/bugzilla/show_bug.cgi?id=58486
                        // These issues are currently present in all current
                        // versions of Java
                        // 2. com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl
                        Doreplacedent doreplacedent = doreplacedentBuilder.newDoreplacedent();
                        doreplacedent.createElement("dummy");
                        DOMImplementationLS implementation = (DOMImplementationLS) doreplacedent.getImplementation();
                        implementation.createLSSerializer().writeToString(doreplacedent);
                        // 3. com.sun.org.apache.xerces.internal.dom.DOMNormalizer
                        doreplacedent.normalize();
                    } catch (ParserConfigurationException e) {
                        log.error(sm.getString("jreLeakListener.xmlParseFail"), e);
                    }
                }
                if (ldapPoolProtection) {
                    try {
                        Clreplaced.forName("com.sun.jndi.ldap.LdapPoolManager");
                    } catch (ClreplacedNotFoundException e) {
                        if (JreVendor.IS_ORACLE_JVM) {
                            log.error(sm.getString("jreLeakListener.ldapPoolManagerFail"), e);
                        } else {
                            log.debug(sm.getString("jreLeakListener.ldapPoolManagerFail"), e);
                        }
                    }
                }
                if (clreplacedesToInitialize != null) {
                    StringTokenizer strTok = new StringTokenizer(clreplacedesToInitialize, ", \r\n\t");
                    while (strTok.hasMoreTokens()) {
                        String clreplacedNameToLoad = strTok.nextToken();
                        try {
                            Clreplaced.forName(clreplacedNameToLoad);
                        } catch (ClreplacedNotFoundException e) {
                            log.error(sm.getString("jreLeakListener.clreplacedToInitializeFail", clreplacedNameToLoad), e);
                        // continue with next clreplaced to load
                        }
                    }
                }
            } finally {
                Thread.currentThread().setContextClreplacedLoader(loader);
            }
        }
    }
}

19 Source : JasperListener.java
with Apache License 2.0
from wangyingjie

/**
 * This listener is designed to initialize Jasper before any web applications are
 * started.
 *
 * @author Remy Maucherat
 * @since 4.1
 */
public clreplaced JasperListener implements LifecycleListener {

    private static final Log log = LogFactory.getLog(JasperListener.clreplaced);

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    // ---------------------------------------------- LifecycleListener Methods
    /**
     * Primary entry point for startup and shutdown events.
     *
     * @param event The event that has occurred
     */
    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
            try {
                // Set JSP factory
                Clreplaced.forName("org.apache.jasper.compiler.JspRuntimeContext", true, this.getClreplaced().getClreplacedLoader());
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                // Should not occur, obviously
                log.warn("Couldn't initialize Jasper", t);
            }
        // Another possibility is to do directly:
        // JspFactory.setDefaultFactory(new JspFactoryImpl());
        }
    }
}

19 Source : ApplicationSessionCookieConfig.java
with Apache License 2.0
from wangyingjie

public clreplaced ApplicationSessionCookieConfig implements SessionCookieConfig {

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    private boolean httpOnly;

    private boolean secure;

    private int maxAge = -1;

    private String comment;

    private String domain;

    private String name;

    private String path;

    private StandardContext context;

    public ApplicationSessionCookieConfig(StandardContext context) {
        this.context = context;
    }

    @Override
    public String getComment() {
        return comment;
    }

    @Override
    public String getDomain() {
        return domain;
    }

    @Override
    public int getMaxAge() {
        return maxAge;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getPath() {
        return path;
    }

    @Override
    public boolean isHttpOnly() {
        return httpOnly;
    }

    @Override
    public boolean isSecure() {
        return secure;
    }

    @Override
    public void setComment(String comment) {
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationSessionCookieConfig.ise", "comment", context.getPath()));
        }
        this.comment = comment;
    }

    @Override
    public void setDomain(String domain) {
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationSessionCookieConfig.ise", "domain name", context.getPath()));
        }
        this.domain = domain;
    }

    @Override
    public void setHttpOnly(boolean httpOnly) {
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationSessionCookieConfig.ise", "HttpOnly", context.getPath()));
        }
        this.httpOnly = httpOnly;
    }

    @Override
    public void setMaxAge(int maxAge) {
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationSessionCookieConfig.ise", "max age", context.getPath()));
        }
        this.maxAge = maxAge;
    }

    @Override
    public void setName(String name) {
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationSessionCookieConfig.ise", "name", context.getPath()));
        }
        this.name = name;
    }

    @Override
    public void setPath(String path) {
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationSessionCookieConfig.ise", "path", context.getPath()));
        }
        this.path = path;
    }

    @Override
    public void setSecure(boolean secure) {
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationSessionCookieConfig.ise", "secure", context.getPath()));
        }
        this.secure = secure;
    }

    /**
     * Creates a new session cookie for the given session ID
     *
     * @param context     The Context for the web application
     * @param sessionId   The ID of the session for which the cookie will be
     *                    created
     * @param secure      Should session cookie be configured as secure
     */
    public static Cookie createSessionCookie(Context context, String sessionId, boolean secure) {
        SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();
        // NOTE: The priority order for session cookie configuration is:
        // 1. Context level configuration
        // 2. Values from SessionCookieConfig
        // 3. Defaults
        Cookie cookie = new Cookie(SessionConfig.getSessionCookieName(context), sessionId);
        // Just apply the defaults.
        cookie.setMaxAge(scc.getMaxAge());
        cookie.setComment(scc.getComment());
        if (context.getSessionCookieDomain() == null) {
            // Avoid possible NPE
            if (scc.getDomain() != null) {
                cookie.setDomain(scc.getDomain());
            }
        } else {
            cookie.setDomain(context.getSessionCookieDomain());
        }
        // Always set secure if the request is secure
        if (scc.isSecure() || secure) {
            cookie.setSecure(true);
        }
        // Always set httpOnly if the context is configured for that
        if (scc.isHttpOnly() || context.getUseHttpOnly()) {
            cookie.setHttpOnly(true);
        }
        String contextPath = context.getSessionCookiePath();
        if (contextPath == null || contextPath.length() == 0) {
            contextPath = scc.getPath();
        }
        if (contextPath == null || contextPath.length() == 0) {
            contextPath = context.getEncodedPath();
        }
        if (context.getSessionCookiePathUsesTrailingSlash()) {
            // Handle special case of ROOT context where cookies require a path of
            // '/' but the servlet spec uses an empty string
            // Also ensure the cookies for a context with a path of /foo don't get
            // sent for requests with a path of /foobar
            if (!contextPath.endsWith("/")) {
                contextPath = contextPath + "/";
            }
        } else {
            // Only handle special case of ROOT context where cookies require a
            // path of '/' but the servlet spec uses an empty string
            if (contextPath.length() == 0) {
                contextPath = "/";
            }
        }
        cookie.setPath(contextPath);
        return cookie;
    }

    /**
     * Determine the name to use for the session cookie for the provided
     * context.
     * @param context
     *
     * @deprecated  Replaced by
     *              {@link SessionConfig#getSessionCookieName(Context)}. This
     *              will be removed in Tomcat 8.0.x.
     */
    @Deprecated
    public static String getSessionCookieName(Context context) {
        return SessionConfig.getSessionCookieName(context);
    }

    /**
     * Determine the name to use for the session cookie for the provided
     * context.
     * @param context
     *
     * @deprecated  Replaced by
     *              {@link SessionConfig#getSessionUriParamName(Context)}. This
     *              will be removed in Tomcat 8.0.x.
     */
    @Deprecated
    public static String getSessionUriParamName(Context context) {
        return SessionConfig.getSessionUriParamName(context);
    }
}

19 Source : ApplicationServletRegistration.java
with Apache License 2.0
from wangyingjie

public clreplaced ApplicationServletRegistration implements ServletRegistration.Dynamic {

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    private Wrapper wrapper;

    private Context context;

    public ApplicationServletRegistration(Wrapper wrapper, Context context) {
        this.wrapper = wrapper;
        this.context = context;
    }

    @Override
    public String getClreplacedName() {
        return wrapper.getServletClreplaced();
    }

    @Override
    public String getInitParameter(String name) {
        return wrapper.findInitParameter(name);
    }

    @Override
    public Map<String, String> getInitParameters() {
        ParameterMap<String, String> result = new ParameterMap<String, String>();
        String[] parameterNames = wrapper.findInitParameters();
        for (String parameterName : parameterNames) {
            result.put(parameterName, wrapper.findInitParameter(parameterName));
        }
        result.setLocked(true);
        return result;
    }

    @Override
    public String getName() {
        return wrapper.getName();
    }

    @Override
    public boolean setInitParameter(String name, String value) {
        if (name == null || value == null) {
            throw new IllegalArgumentException(sm.getString("applicationFilterRegistration.nullInitParam", name, value));
        }
        if (getInitParameter(name) != null) {
            return false;
        }
        wrapper.addInitParameter(name, value);
        return true;
    }

    @Override
    public Set<String> setInitParameters(Map<String, String> initParameters) {
        Set<String> conflicts = new HashSet<String>();
        for (Map.Entry<String, String> entry : initParameters.entrySet()) {
            if (entry.getKey() == null || entry.getValue() == null) {
                throw new IllegalArgumentException(sm.getString("applicationFilterRegistration.nullInitParams", entry.getKey(), entry.getValue()));
            }
            if (getInitParameter(entry.getKey()) != null) {
                conflicts.add(entry.getKey());
            }
        }
        // Have to add in a separate loop since spec requires no updates at all
        // if there is an issue
        if (conflicts.isEmpty()) {
            for (Map.Entry<String, String> entry : initParameters.entrySet()) {
                setInitParameter(entry.getKey(), entry.getValue());
            }
        }
        return conflicts;
    }

    @Override
    public void setAsyncSupported(boolean asyncSupported) {
        wrapper.setAsyncSupported(asyncSupported);
    }

    @Override
    public void setLoadOnStartup(int loadOnStartup) {
        wrapper.setLoadOnStartup(loadOnStartup);
    }

    @Override
    public void setMultipartConfig(MultipartConfigElement multipartConfig) {
        wrapper.setMultipartConfigElement(multipartConfig);
    }

    @Override
    public void setRunAsRole(String roleName) {
        wrapper.setRunAs(roleName);
    }

    @Override
    public Set<String> setServletSecurity(ServletSecurityElement constraint) {
        if (constraint == null) {
            throw new IllegalArgumentException(sm.getString("applicationServletRegistration.setServletSecurity.iae", getName(), context.getName()));
        }
        if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
            throw new IllegalStateException(sm.getString("applicationServletRegistration.setServletSecurity.ise", getName(), context.getName()));
        }
        return context.addServletSecurity(this, constraint);
    }

    @Override
    public Set<String> addMapping(String... urlPatterns) {
        if (urlPatterns == null) {
            return Collections.emptySet();
        }
        Set<String> conflicts = new HashSet<String>();
        for (String urlPattern : urlPatterns) {
            String wrapperName = context.findServletMapping(urlPattern);
            if (wrapperName != null) {
                Wrapper wrapper = (Wrapper) context.findChild(wrapperName);
                if (wrapper.isOverridable()) {
                    // Some Wrappers (from global and host web.xml) may be
                    // overridden rather than generating a conflict
                    context.removeServletMapping(urlPattern);
                } else {
                    conflicts.add(urlPattern);
                }
            }
        }
        if (!conflicts.isEmpty()) {
            return conflicts;
        }
        for (String urlPattern : urlPatterns) {
            context.addServletMapping(urlPattern, wrapper.getName());
        }
        return Collections.emptySet();
    }

    @Override
    public Collection<String> getMappings() {
        Set<String> result = new HashSet<String>();
        String servletName = wrapper.getName();
        String[] urlPatterns = context.findServletMappings();
        for (String urlPattern : urlPatterns) {
            String name = context.findServletMapping(urlPattern);
            if (name.equals(servletName)) {
                result.add(urlPattern);
            }
        }
        return result;
    }

    @Override
    public String getRunAsRole() {
        return wrapper.getRunAs();
    }
}

19 Source : ApplicationFilterChain.java
with Apache License 2.0
from wangyingjie

/**
 * Implementation of <code>javax.servlet.FilterChain</code> used to manage
 * the execution of a set of filters for a particular request.  When the
 * set of defined filters has all been executed, the next call to
 * <code>doFilter()</code> will execute the servlet's <code>service()</code>
 * method itself.
 *
 * @author Craig R. McClanahan
 *
 * 该类会执行到应用中配置的:Filter、Servlet
 */
final clreplaced ApplicationFilterChain implements FilterChain, CometFilterChain {

    // Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
    private static final ThreadLocal<ServletRequest> lastServicedRequest;

    private static final ThreadLocal<ServletResponse> lastServicedResponse;

    static {
        if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
            lastServicedRequest = new ThreadLocal<ServletRequest>();
            lastServicedResponse = new ThreadLocal<ServletResponse>();
        } else {
            lastServicedRequest = null;
            lastServicedResponse = null;
        }
    }

    // -------------------------------------------------------------- Constants
    public static final int INCREMENT = 10;

    // ----------------------------------------------------------- Constructors
    /**
     * Construct a new chain instance with no defined filters.
     */
    public ApplicationFilterChain() {
        super();
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * Filters.
     */
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];

    /**
     * The int which is used to maintain the current position
     * in the filter chain.
     */
    private int pos = 0;

    /**
     * The int which gives the current number of filters in the chain.
     */
    private int n = 0;

    /**
     * The servlet instance to be executed by this chain.
     */
    private Servlet servlet = null;

    /**
     * The string manager for our package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    /**
     * The InstanceSupport instance replacedociated with our Wrapper (used to
     * send "before filter" and "after filter" events.
     */
    private InstanceSupport support = null;

    /**
     * Static clreplaced array used when the SecurityManager is turned on and
     * <code>doFilter</code> is invoked.
     */
    private static Clreplaced<?>[] clreplacedType = new Clreplaced[] { ServletRequest.clreplaced, ServletResponse.clreplaced, FilterChain.clreplaced };

    /**
     * Static clreplaced array used when the SecurityManager is turned on and
     * <code>service</code> is invoked.
     */
    private static Clreplaced<?>[] clreplacedTypeUsedInService = new Clreplaced[] { ServletRequest.clreplaced, ServletResponse.clreplaced };

    /**
     * Static clreplaced array used when the SecurityManager is turned on and
     * <code>doFilterEvent</code> is invoked.
     */
    private static Clreplaced<?>[] cometClreplacedType = new Clreplaced[] { CometEvent.clreplaced, CometFilterChain.clreplaced };

    /**
     * Static clreplaced array used when the SecurityManager is turned on and
     * <code>event</code> is invoked.
     */
    private static Clreplaced<?>[] clreplacedTypeUsedInEvent = new Clreplaced[] { CometEvent.clreplaced };

    // ---------------------------------------------------- FilterChain Methods
    /**
     * Invoke the next filter in this chain, preplaceding the specified request
     * and response.  If there are no more filters in this chain, invoke
     * the <code>service()</code> method of the servlet itself.
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet exception occurs
     *
     * 用来执行过滤器方法以及最后的Servlet
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (Globals.IS_SECURITY_ENABLED) {
            final ServletRequest req = request;
            final ServletResponse res = response;
            try {
                java.security.AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Void>() {

                    @Override
                    public Void run() throws ServletException, IOException {
                        internalDoFilter(req, res);
                        return null;
                    }
                });
            } catch (PrivilegedActionException pe) {
                Exception e = pe.getException();
                if (e instanceof ServletException)
                    throw (ServletException) e;
                else if (e instanceof IOException)
                    throw (IOException) e;
                else if (e instanceof RuntimeException)
                    throw (RuntimeException) e;
                else
                    throw new ServletException(e.getMessage(), e);
            }
        } else {
            internalDoFilter(request, response);
        }
    }

    /**
     * 该方法主要做2件事:
     * (1)、执行过滤器  Filter.doFilter 方法
     * (2)、执行  Servlet.service 方法
     *
     *  源代码写的真烂!!!!!
     *
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        // Call the next filter if there is one
        if (pos < n) {
            ApplicationFilterConfig filterConfig = filters[pos++];
            Filter filter = null;
            // todo 调用 Filter 的 doFilter 方法
            try {
                filter = filterConfig.getFilter();
                support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response);
                if (request.isAsyncSupported() && "false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {
                    request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
                }
                if (Globals.IS_SECURITY_ENABLED) {
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal = ((HttpServletRequest) req).getUserPrincipal();
                    Object[] args = new Object[] { req, res, this };
                    SecurityUtil.doAsPrivilege("doFilter", filter, clreplacedType, args, principal);
                } else {
                    filter.doFilter(request, response, this);
                }
                support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response);
            } catch (IOException e) {
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e);
                throw e;
            } catch (ServletException e) {
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e);
                throw e;
            } catch (RuntimeException e) {
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e);
                throw e;
            } catch (Throwable e) {
                e = ExceptionUtils.unwrapInvocationTargetException(e);
                ExceptionUtils.handleThrowable(e);
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e);
                throw new ServletException(sm.getString("filterChain.filter"), e);
            }
            return;
        }
        // todo 调用 Servlet 的 service 方法
        // We fell off the end of the chain -- call the servlet instance
        try {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(request);
                lastServicedResponse.set(response);
            }
            support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response);
            if (request.isAsyncSupported() && !support.getWrapper().isAsyncSupported()) {
                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
            }
            // todo 会执行 Servlet 的 service 方法
            // Use potentially wrapped request from this point
            if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) {
                if (Globals.IS_SECURITY_ENABLED) {
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal = ((HttpServletRequest) req).getUserPrincipal();
                    Object[] args = new Object[] { req, res };
                    SecurityUtil.doAsPrivilege("service", servlet, clreplacedTypeUsedInService, args, principal);
                } else {
                    servlet.service(request, response);
                }
            } else {
                servlet.service(request, response);
            }
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response);
        } catch (IOException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e);
            throw e;
        } catch (ServletException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e);
            throw e;
        } catch (RuntimeException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e);
            throw e;
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e);
            throw new ServletException(sm.getString("filterChain.servlet"), e);
        } finally {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(null);
                lastServicedResponse.set(null);
            }
        }
    }

    /**
     * Process the event, using the security manager if the option is enabled.
     *
     * @param event the event to process
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet exception occurs
     */
    @Override
    public void doFilterEvent(CometEvent event) throws IOException, ServletException {
        if (Globals.IS_SECURITY_ENABLED) {
            final CometEvent ev = event;
            try {
                java.security.AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Void>() {

                    @Override
                    public Void run() throws ServletException, IOException {
                        internalDoFilterEvent(ev);
                        return null;
                    }
                });
            } catch (PrivilegedActionException pe) {
                Exception e = pe.getException();
                if (e instanceof ServletException)
                    throw (ServletException) e;
                else if (e instanceof IOException)
                    throw (IOException) e;
                else if (e instanceof RuntimeException)
                    throw (RuntimeException) e;
                else
                    throw new ServletException(e.getMessage(), e);
            }
        } else {
            internalDoFilterEvent(event);
        }
    }

    /**
     * The last request preplaceded to a servlet for servicing from the current
     * thread.
     *
     * @return The last request to be serviced.
     */
    public static ServletRequest getLastServicedRequest() {
        return lastServicedRequest.get();
    }

    /**
     * The last response preplaceded to a servlet for servicing from the current
     * thread.
     *
     * @return The last response to be serviced.
     */
    public static ServletResponse getLastServicedResponse() {
        return lastServicedResponse.get();
    }

    private void internalDoFilterEvent(CometEvent event) throws IOException, ServletException {
        // Call the next filter if there is one
        if (pos < n) {
            ApplicationFilterConfig filterConfig = filters[pos++];
            CometFilter filter = null;
            try {
                filter = (CometFilter) filterConfig.getFilter();
                // FIXME: No instance listener processing for events for now
                /*
                support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
                        filter, event);
                        */
                if (Globals.IS_SECURITY_ENABLED) {
                    final CometEvent ev = event;
                    Principal principal = ev.getHttpServletRequest().getUserPrincipal();
                    Object[] args = new Object[] { ev, this };
                    SecurityUtil.doAsPrivilege("doFilterEvent", filter, cometClreplacedType, args, principal);
                } else {
                    filter.doFilterEvent(event, this);
                }
            /*support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                        filter, event);*/
            } catch (IOException e) {
                /*
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                            filter, event, e);
                            */
                throw e;
            } catch (ServletException e) {
                /*
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                            filter, event, e);
                            */
                throw e;
            } catch (RuntimeException e) {
                /*
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                            filter, event, e);
                            */
                throw e;
            } catch (Throwable e) {
                e = ExceptionUtils.unwrapInvocationTargetException(e);
                ExceptionUtils.handleThrowable(e);
                /*if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                            filter, event, e);*/
                throw new ServletException(sm.getString("filterChain.filter"), e);
            }
            return;
        }
        // We fell off the end of the chain -- call the servlet instance
        try {
            /*
            support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
                    servlet, request, response);
                    */
            if (Globals.IS_SECURITY_ENABLED) {
                final CometEvent ev = event;
                Principal principal = ev.getHttpServletRequest().getUserPrincipal();
                Object[] args = new Object[] { ev };
                SecurityUtil.doAsPrivilege("event", servlet, clreplacedTypeUsedInEvent, args, principal);
            } else {
                ((CometProcessor) servlet).event(event);
            }
        /*
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                    servlet, request, response);*/
        } catch (IOException e) {
            /*
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                    servlet, request, response, e);
                    */
            throw e;
        } catch (ServletException e) {
            /*
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                    servlet, request, response, e);
                    */
            throw e;
        } catch (RuntimeException e) {
            /*
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                    servlet, request, response, e);
                    */
            throw e;
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            /*
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                    servlet, request, response, e);
                    */
            throw new ServletException(sm.getString("filterChain.servlet"), e);
        }
    }

    // -------------------------------------------------------- Package Methods
    /**
     * Add a filter to the set of filters that will be executed in this chain.
     *
     * @param filterConfig The FilterConfig for the servlet to be executed
     */
    void addFilter(ApplicationFilterConfig filterConfig) {
        // Prevent the same filter being added multiple times
        for (ApplicationFilterConfig filter : filters) if (filter == filterConfig)
            return;
        if (n == filters.length) {
            ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT];
            System.arraycopy(filters, 0, newFilters, 0, n);
            filters = newFilters;
        }
        filters[n++] = filterConfig;
    }

    /**
     * Release references to the filters and wrapper executed by this chain.
     */
    void release() {
        for (int i = 0; i < n; i++) {
            filters[i] = null;
        }
        n = 0;
        pos = 0;
        servlet = null;
        support = null;
    }

    /**
     * Prepare for reuse of the filters and wrapper executed by this chain.
     */
    void reuse() {
        pos = 0;
    }

    /**
     * Set the servlet that will be executed at the end of this chain.
     *
     * @param servlet The Wrapper for the servlet to be executed
     */
    void setServlet(Servlet servlet) {
        this.servlet = servlet;
    }

    /**
     * Set the InstanceSupport object used for event notifications
     * for this filter chain.
     *
     * @param support The InstanceSupport object for our Wrapper
     */
    void setSupport(InstanceSupport support) {
        this.support = support;
    }
}

19 Source : ApplicationDispatcher.java
with Apache License 2.0
from wangyingjie

/**
 * Standard implementation of <code>RequestDispatcher</code> that allows a
 * request to be forwarded to a different resource to create the ultimate
 * response, or to include the output of another resource in the response
 * from this resource.  This implementation allows application level servlets
 * to wrap the request and/or response objects that are preplaceded on to the
 * called resource, as long as the wrapping clreplacedes extend
 * <code>javax.servlet.ServletRequestWrapper</code> and
 * <code>javax.servlet.ServletResponseWrapper</code>.
 *
 * @author Craig R. McClanahan
 */
final clreplaced ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher {

    static final boolean STRICT_SERVLET_COMPLIANCE;

    static final boolean WRAP_SAME_OBJECT;

    static {
        STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
        String wrapSameObject = System.getProperty("org.apache.catalina.core.ApplicationDispatcher.WRAP_SAME_OBJECT");
        if (wrapSameObject == null) {
            WRAP_SAME_OBJECT = STRICT_SERVLET_COMPLIANCE;
        } else {
            WRAP_SAME_OBJECT = Boolean.parseBoolean(wrapSameObject);
        }
    }

    protected clreplaced PrivilegedForward implements PrivilegedExceptionAction<Void> {

        private ServletRequest request;

        private ServletResponse response;

        PrivilegedForward(ServletRequest request, ServletResponse response) {
            this.request = request;
            this.response = response;
        }

        @Override
        public Void run() throws java.lang.Exception {
            doForward(request, response);
            return null;
        }
    }

    protected clreplaced PrivilegedInclude implements PrivilegedExceptionAction<Void> {

        private ServletRequest request;

        private ServletResponse response;

        PrivilegedInclude(ServletRequest request, ServletResponse response) {
            this.request = request;
            this.response = response;
        }

        @Override
        public Void run() throws ServletException, IOException {
            doInclude(request, response);
            return null;
        }
    }

    protected clreplaced PrivilegedDispatch implements PrivilegedExceptionAction<Void> {

        private final ServletRequest request;

        private final ServletResponse response;

        PrivilegedDispatch(ServletRequest request, ServletResponse response) {
            this.request = request;
            this.response = response;
        }

        @Override
        public Void run() throws ServletException, IOException {
            doDispatch(request, response);
            return null;
        }
    }

    /**
     * Used to preplaced state when the request dispatcher is used. Using instance
     * variables causes threading issues and state is too complex to preplaced and
     * return single ServletRequest or ServletResponse objects.
     */
    private static clreplaced State {

        State(ServletRequest request, ServletResponse response, boolean including) {
            this.outerRequest = request;
            this.outerResponse = response;
            this.including = including;
        }

        /**
         * The outermost request that will be preplaceded on to the invoked servlet.
         */
        ServletRequest outerRequest = null;

        /**
         * The outermost response that will be preplaceded on to the invoked servlet.
         */
        ServletResponse outerResponse = null;

        /**
         * The request wrapper we have created and installed (if any).
         */
        ServletRequest wrapRequest = null;

        /**
         * The response wrapper we have created and installed (if any).
         */
        ServletResponse wrapResponse = null;

        /**
         * Are we performing an include() instead of a forward()?
         */
        boolean including = false;

        /**
         * Outermost HttpServletRequest in the chain
         */
        HttpServletRequest hrequest = null;

        /**
         * Outermost HttpServletResponse in the chain
         */
        HttpServletResponse hresponse = null;
    }

    // ----------------------------------------------------------- Constructors
    /**
     * Construct a new instance of this clreplaced, configured according to the
     * specified parameters.  If both servletPath and pathInfo are
     * <code>null</code>, it will be replacedumed that this RequestDispatcher
     * was acquired by name, rather than by path.
     *
     * @param wrapper The Wrapper replacedociated with the resource that will
     *  be forwarded to or included (required)
     * @param requestURI The request URI to this resource (if any)
     * @param servletPath The revised servlet path to this resource (if any)
     * @param pathInfo The revised extra path information to this resource
     *  (if any)
     * @param queryString Query string parameters included with this request
     *  (if any)
     * @param name Servlet name (if a named dispatcher was created)
     *  else <code>null</code>
     */
    public ApplicationDispatcher(Wrapper wrapper, String requestURI, String servletPath, String pathInfo, String queryString, String name) {
        super();
        // Save all of our configuration parameters
        this.wrapper = wrapper;
        this.context = (Context) wrapper.getParent();
        this.requestURI = requestURI;
        this.servletPath = servletPath;
        this.pathInfo = pathInfo;
        this.queryString = queryString;
        this.name = name;
        if (wrapper instanceof StandardWrapper)
            this.support = ((StandardWrapper) wrapper).getInstanceSupport();
        else
            this.support = new InstanceSupport(wrapper);
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * The Context this RequestDispatcher is replacedociated with.
     */
    private Context context = null;

    /**
     * Descriptive information about this implementation.
     */
    private static final String info = "org.apache.catalina.core.ApplicationDispatcher/1.0";

    /**
     * The servlet name for a named dispatcher.
     */
    private String name = null;

    /**
     * The extra path information for this RequestDispatcher.
     */
    private String pathInfo = null;

    /**
     * The query string parameters for this RequestDispatcher.
     */
    private String queryString = null;

    /**
     * The request URI for this RequestDispatcher.
     */
    private String requestURI = null;

    /**
     * The servlet path for this RequestDispatcher.
     */
    private String servletPath = null;

    /**
     * The StringManager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    /**
     * The InstanceSupport instance replacedociated with our Wrapper (used to
     * send "before dispatch" and "after dispatch" events.
     */
    private InstanceSupport support = null;

    /**
     * The Wrapper replacedociated with the resource that will be forwarded to
     * or included.
     */
    private Wrapper wrapper = null;

    // ------------------------------------------------------------- Properties
    /**
     * Return the descriptive information about this implementation.
     */
    public String getInfo() {
        return (info);
    }

    // --------------------------------------------------------- Public Methods
    /**
     * Forward this request and response to another resource for processing.
     * Any runtime exception, IOException, or ServletException thrown by the
     * called servlet will be propagated to the caller.
     *
     * @param request The servlet request to be forwarded
     * @param response The servlet response to be forwarded
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet exception occurs
     */
    @Override
    public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        if (Globals.IS_SECURITY_ENABLED) {
            try {
                PrivilegedForward dp = new PrivilegedForward(request, response);
                AccessController.doPrivileged(dp);
            } catch (PrivilegedActionException pe) {
                Exception e = pe.getException();
                if (e instanceof ServletException)
                    throw (ServletException) e;
                throw (IOException) e;
            }
        } else {
            doForward(request, response);
        }
    }

    private void doForward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        // Reset any output that has been buffered, but keep headers/cookies
        if (response.isCommitted()) {
            throw new IllegalStateException(sm.getString("applicationDispatcher.forward.ise"));
        }
        try {
            response.resetBuffer();
        } catch (IllegalStateException e) {
            throw e;
        }
        // Set up to handle the specified request and response
        State state = new State(request, response, false);
        if (WRAP_SAME_OBJECT) {
            // Check SRV.8.2 / SRV.14.2.5.1 compliance
            checkSameObjects(request, response);
        }
        wrapResponse(state);
        // Handle an HTTP named dispatcher forward
        if ((servletPath == null) && (pathInfo == null)) {
            ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
            HttpServletRequest hrequest = state.hrequest;
            wrequest.setRequestURI(hrequest.getRequestURI());
            wrequest.setContextPath(hrequest.getContextPath());
            wrequest.setServletPath(hrequest.getServletPath());
            wrequest.setPathInfo(hrequest.getPathInfo());
            wrequest.setQueryString(hrequest.getQueryString());
            processRequest(request, response, state);
        } else // Handle an HTTP path-based forward
        {
            ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
            String contextPath = context.getPath();
            HttpServletRequest hrequest = state.hrequest;
            if (hrequest.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) == null) {
                wrequest.setAttribute(RequestDispatcher.FORWARD_REQUEST_URI, hrequest.getRequestURI());
                wrequest.setAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH, hrequest.getContextPath());
                wrequest.setAttribute(RequestDispatcher.FORWARD_SERVLET_PATH, hrequest.getServletPath());
                wrequest.setAttribute(RequestDispatcher.FORWARD_PATH_INFO, hrequest.getPathInfo());
                wrequest.setAttribute(RequestDispatcher.FORWARD_QUERY_STRING, hrequest.getQueryString());
            }
            wrequest.setContextPath(contextPath);
            wrequest.setRequestURI(requestURI);
            wrequest.setServletPath(servletPath);
            wrequest.setPathInfo(pathInfo);
            if (queryString != null) {
                wrequest.setQueryString(queryString);
                wrequest.setQueryParams(queryString);
            }
            processRequest(request, response, state);
        }
        if (request.isAsyncStarted()) {
            // An async request was started during the forward, don't close the
            // response as it may be written to during the async handling
            return;
        }
        // This is not a real close in order to support error processing
        if (wrapper.getLogger().isDebugEnabled())
            wrapper.getLogger().debug(" Disabling the response for futher output");
        if (response instanceof ResponseFacade) {
            ((ResponseFacade) response).finish();
        } else {
            // Servlet SRV.6.2.2. The Request/Response may have been wrapped
            // and may no longer be instance of RequestFacade
            if (wrapper.getLogger().isDebugEnabled()) {
                wrapper.getLogger().debug(" The Response is vehiculed using a wrapper: " + response.getClreplaced().getName());
            }
            // Close anyway
            try {
                PrintWriter writer = response.getWriter();
                writer.close();
            } catch (IllegalStateException e) {
                try {
                    ServletOutputStream stream = response.getOutputStream();
                    stream.close();
                } catch (IllegalStateException f) {
                // Ignore
                } catch (IOException f) {
                // Ignore
                }
            } catch (IOException e) {
            // Ignore
            }
        }
    }

    /**
     * Prepare the request based on the filter configuration.
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     * @param state The RD state
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    private void processRequest(ServletRequest request, ServletResponse response, State state) throws IOException, ServletException {
        DispatcherType disInt = (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
        if (disInt != null) {
            boolean doInvoke = true;
            if (context.getFireRequestListenersOnForwards() && !context.fireRequestInitEvent(request)) {
                doInvoke = false;
            }
            if (doInvoke) {
                if (disInt != DispatcherType.ERROR) {
                    state.outerRequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, getCombinedPath());
                    state.outerRequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.FORWARD);
                    invoke(state.outerRequest, response, state);
                } else {
                    invoke(state.outerRequest, response, state);
                }
                if (context.getFireRequestListenersOnForwards()) {
                    context.fireRequestDestroyEvent(request);
                }
            }
        }
    }

    /**
     * Combine the servletPath and the pathInfo. If pathInfo is
     * <code>null</code> it is ignored. If servletPath is <code>null</code> then
     * <code>null</code> is returned.
     * @return The combined path with pathInfo appended to servletInfo
     */
    private String getCombinedPath() {
        if (servletPath == null) {
            return null;
        }
        if (pathInfo == null) {
            return servletPath;
        }
        return servletPath + pathInfo;
    }

    /**
     * Include the response from another resource in the current response.
     * Any runtime exception, IOException, or ServletException thrown by the
     * called servlet will be propagated to the caller.
     *
     * @param request The servlet request that is including this one
     * @param response The servlet response to be appended to
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet exception occurs
     */
    @Override
    public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        if (Globals.IS_SECURITY_ENABLED) {
            try {
                PrivilegedInclude dp = new PrivilegedInclude(request, response);
                AccessController.doPrivileged(dp);
            } catch (PrivilegedActionException pe) {
                Exception e = pe.getException();
                if (e instanceof ServletException)
                    throw (ServletException) e;
                throw (IOException) e;
            }
        } else {
            doInclude(request, response);
        }
    }

    private void doInclude(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        // Set up to handle the specified request and response
        State state = new State(request, response, true);
        if (WRAP_SAME_OBJECT) {
            // Check SRV.8.2 / SRV.14.2.5.1 compliance
            checkSameObjects(request, response);
        }
        // Create a wrapped response to use for this request
        wrapResponse(state);
        // Handle an HTTP named dispatcher include
        if (name != null) {
            ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
            wrequest.setAttribute(Globals.NAMED_DISPATCHER_ATTR, name);
            if (servletPath != null)
                wrequest.setServletPath(servletPath);
            wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.INCLUDE);
            wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, getCombinedPath());
            invoke(state.outerRequest, state.outerResponse, state);
        } else // Handle an HTTP path based include
        {
            ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
            String contextPath = context.getPath();
            if (requestURI != null)
                wrequest.setAttribute(RequestDispatcher.INCLUDE_REQUEST_URI, requestURI);
            if (contextPath != null)
                wrequest.setAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH, contextPath);
            if (servletPath != null)
                wrequest.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH, servletPath);
            if (pathInfo != null)
                wrequest.setAttribute(RequestDispatcher.INCLUDE_PATH_INFO, pathInfo);
            if (queryString != null) {
                wrequest.setAttribute(RequestDispatcher.INCLUDE_QUERY_STRING, queryString);
                wrequest.setQueryParams(queryString);
            }
            wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.INCLUDE);
            wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, getCombinedPath());
            invoke(state.outerRequest, state.outerResponse, state);
        }
    }

    @Override
    public void dispatch(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        if (Globals.IS_SECURITY_ENABLED) {
            try {
                PrivilegedDispatch dp = new PrivilegedDispatch(request, response);
                AccessController.doPrivileged(dp);
            } catch (PrivilegedActionException pe) {
                Exception e = pe.getException();
                if (e instanceof ServletException)
                    throw (ServletException) e;
                throw (IOException) e;
            }
        } else {
            doDispatch(request, response);
        }
    }

    private void doDispatch(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        // Set up to handle the specified request and response
        State state = new State(request, response, false);
        // Create a wrapped response to use for this request
        wrapResponse(state);
        ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
        if (queryString != null) {
            wrequest.setQueryParams(queryString);
        }
        wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ASYNC);
        wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, getCombinedPath());
        wrequest.setContextPath(context.getPath());
        wrequest.setRequestURI(requestURI);
        wrequest.setServletPath(servletPath);
        wrequest.setPathInfo(pathInfo);
        if (queryString != null) {
            wrequest.setQueryString(queryString);
            wrequest.setQueryParams(queryString);
        }
        invoke(state.outerRequest, state.outerResponse, state);
    }

    // -------------------------------------------------------- Private Methods
    /**
     * Ask the resource represented by this RequestDispatcher to process
     * the replacedociated request, and create (or append to) the replacedociated
     * response.
     * <p>
     * <strong>IMPLEMENTATION NOTE</strong>: This implementation replacedumes
     * that no filters are applied to a forwarded or included resource,
     * because they were already done for the original request.
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    private void invoke(ServletRequest request, ServletResponse response, State state) throws IOException, ServletException {
        // Checking to see if the context clreplacedloader is the current context
        // clreplacedloader. If it's not, we're saving it, and setting the context
        // clreplacedloader to the Context clreplacedloader
        ClreplacedLoader oldCCL = Thread.currentThread().getContextClreplacedLoader();
        ClreplacedLoader contextClreplacedLoader = context.getLoader().getClreplacedLoader();
        if (oldCCL != contextClreplacedLoader) {
            Thread.currentThread().setContextClreplacedLoader(contextClreplacedLoader);
        } else {
            oldCCL = null;
        }
        // Initialize local variables we may need
        HttpServletResponse hresponse = state.hresponse;
        Servlet servlet = null;
        IOException ioException = null;
        ServletException servletException = null;
        RuntimeException runtimeException = null;
        boolean unavailable = false;
        // Check for the servlet being marked unavailable
        if (wrapper.isUnavailable()) {
            wrapper.getLogger().warn(sm.getString("applicationDispatcher.isUnavailable", wrapper.getName()));
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE))
                hresponse.setDateHeader("Retry-After", available);
            hresponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("applicationDispatcher.isUnavailable", wrapper.getName()));
            unavailable = true;
        }
        // Allocate a servlet instance to process this request
        try {
            if (!unavailable) {
                servlet = wrapper.allocate();
            }
        } catch (ServletException e) {
            wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e));
            servletException = e;
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), e);
            servletException = new ServletException(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), e);
            servlet = null;
        }
        // Get the FilterChain Here
        ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
        ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);
        // Call the service() method for the allocated servlet instance
        try {
            support.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT, servlet, request, response);
            // for includes/forwards
            if ((servlet != null) && (filterChain != null)) {
                filterChain.doFilter(request, response);
            }
            // Servlet Service Method is called by the FilterChain
            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT, servlet, request, response);
        } catch (ClientAbortException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT, servlet, request, response);
            ioException = e;
        } catch (IOException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT, servlet, request, response);
            wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e);
            ioException = e;
        } catch (UnavailableException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT, servlet, request, response);
            wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e);
            servletException = e;
            wrapper.unavailable(e);
        } catch (ServletException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT, servlet, request, response);
            Throwable rootCause = StandardWrapper.getRootCause(e);
            if (!(rootCause instanceof ClientAbortException)) {
                wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), rootCause);
            }
            servletException = e;
        } catch (RuntimeException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT, servlet, request, response);
            wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e);
            runtimeException = e;
        }
        // Release the filter chain (if any) for this request
        try {
            if (filterChain != null)
                filterChain.release();
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            wrapper.getLogger().error(sm.getString("standardWrapper.releaseFilters", wrapper.getName()), e);
        // FIXME: Exception handling needs to be similar to what is in the StandardWrapperValue
        }
        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                wrapper.deallocate(servlet);
            }
        } catch (ServletException e) {
            wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), e);
            servletException = e;
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), e);
            servletException = new ServletException(sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), e);
        }
        // Reset the old context clreplaced loader
        if (oldCCL != null)
            Thread.currentThread().setContextClreplacedLoader(oldCCL);
        // Unwrap request/response if needed
        // See Bugzilla 30949
        unwrapRequest(state);
        unwrapResponse(state);
        // Recycle request if necessary (also BZ 30949)
        recycleRequestWrapper(state);
        // Rethrow an exception if one was thrown by the invoked servlet
        if (ioException != null)
            throw ioException;
        if (servletException != null)
            throw servletException;
        if (runtimeException != null)
            throw runtimeException;
    }

    /**
     * Unwrap the request if we have wrapped it.
     */
    private void unwrapRequest(State state) {
        if (state.wrapRequest == null)
            return;
        if (state.outerRequest.isAsyncStarted()) {
            if (!state.outerRequest.getAsyncContext().hasOriginalRequestAndResponse()) {
                return;
            }
        }
        ServletRequest previous = null;
        ServletRequest current = state.outerRequest;
        while (current != null) {
            // If we run into the container request we are done
            if ((current instanceof Request) || (current instanceof RequestFacade))
                break;
            // Remove the current request if it is our wrapper
            if (current == state.wrapRequest) {
                ServletRequest next = ((ServletRequestWrapper) current).getRequest();
                if (previous == null)
                    state.outerRequest = next;
                else
                    ((ServletRequestWrapper) previous).setRequest(next);
                break;
            }
            // Advance to the next request in the chain
            previous = current;
            current = ((ServletRequestWrapper) current).getRequest();
        }
    }

    /**
     * Unwrap the response if we have wrapped it.
     */
    private void unwrapResponse(State state) {
        if (state.wrapResponse == null)
            return;
        if (state.outerRequest.isAsyncStarted()) {
            if (!state.outerRequest.getAsyncContext().hasOriginalRequestAndResponse()) {
                return;
            }
        }
        ServletResponse previous = null;
        ServletResponse current = state.outerResponse;
        while (current != null) {
            // If we run into the container response we are done
            if ((current instanceof Response) || (current instanceof ResponseFacade))
                break;
            // Remove the current response if it is our wrapper
            if (current == state.wrapResponse) {
                ServletResponse next = ((ServletResponseWrapper) current).getResponse();
                if (previous == null)
                    state.outerResponse = next;
                else
                    ((ServletResponseWrapper) previous).setResponse(next);
                break;
            }
            // Advance to the next response in the chain
            previous = current;
            current = ((ServletResponseWrapper) current).getResponse();
        }
    }

    /**
     * Create and return a request wrapper that has been inserted in the
     * appropriate spot in the request chain.
     */
    private ServletRequest wrapRequest(State state) {
        // Locate the request we should insert in front of
        ServletRequest previous = null;
        ServletRequest current = state.outerRequest;
        while (current != null) {
            if (state.hrequest == null && (current instanceof HttpServletRequest))
                state.hrequest = (HttpServletRequest) current;
            if (!(current instanceof ServletRequestWrapper))
                break;
            if (current instanceof ApplicationHttpRequest)
                break;
            if (current instanceof ApplicationRequest)
                break;
            previous = current;
            current = ((ServletRequestWrapper) current).getRequest();
        }
        // Instantiate a new wrapper at this point and insert it in the chain
        ServletRequest wrapper = null;
        if ((current instanceof ApplicationHttpRequest) || (current instanceof Request) || (current instanceof HttpServletRequest)) {
            // Compute a crossContext flag
            HttpServletRequest hcurrent = (HttpServletRequest) current;
            boolean crossContext = false;
            if ((state.outerRequest instanceof ApplicationHttpRequest) || (state.outerRequest instanceof Request) || (state.outerRequest instanceof HttpServletRequest)) {
                HttpServletRequest houterRequest = (HttpServletRequest) state.outerRequest;
                Object contextPath = houterRequest.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH);
                if (contextPath == null) {
                    // Forward
                    contextPath = houterRequest.getContextPath();
                }
                crossContext = !(context.getPath().equals(contextPath));
            }
            wrapper = new ApplicationHttpRequest(hcurrent, context, crossContext);
        } else {
            wrapper = new ApplicationRequest(current);
        }
        if (previous == null)
            state.outerRequest = wrapper;
        else
            ((ServletRequestWrapper) previous).setRequest(wrapper);
        state.wrapRequest = wrapper;
        return (wrapper);
    }

    /**
     * Create and return a response wrapper that has been inserted in the
     * appropriate spot in the response chain.
     */
    private ServletResponse wrapResponse(State state) {
        // Locate the response we should insert in front of
        ServletResponse previous = null;
        ServletResponse current = state.outerResponse;
        while (current != null) {
            if (state.hresponse == null && (current instanceof HttpServletResponse)) {
                state.hresponse = (HttpServletResponse) current;
                if (// Forward only needs hresponse
                !state.including)
                    return null;
            }
            if (!(current instanceof ServletResponseWrapper))
                break;
            if (current instanceof ApplicationHttpResponse)
                break;
            if (current instanceof ApplicationResponse)
                break;
            previous = current;
            current = ((ServletResponseWrapper) current).getResponse();
        }
        // Instantiate a new wrapper at this point and insert it in the chain
        ServletResponse wrapper = null;
        if ((current instanceof ApplicationHttpResponse) || (current instanceof Response) || (current instanceof HttpServletResponse))
            wrapper = new ApplicationHttpResponse((HttpServletResponse) current, state.including);
        else
            wrapper = new ApplicationResponse(current, state.including);
        if (previous == null)
            state.outerResponse = wrapper;
        else
            ((ServletResponseWrapper) previous).setResponse(wrapper);
        state.wrapResponse = wrapper;
        return (wrapper);
    }

    private void checkSameObjects(ServletRequest appRequest, ServletResponse appResponse) throws ServletException {
        ServletRequest originalRequest = ApplicationFilterChain.getLastServicedRequest();
        ServletResponse originalResponse = ApplicationFilterChain.getLastServicedResponse();
        // Some forwards, eg from valves will not set original values
        if (originalRequest == null || originalResponse == null) {
            return;
        }
        boolean same = false;
        ServletRequest dispatchedRequest = appRequest;
        // find the request that was preplaceded into the service method
        while (originalRequest instanceof ServletRequestWrapper && ((ServletRequestWrapper) originalRequest).getRequest() != null) {
            originalRequest = ((ServletRequestWrapper) originalRequest).getRequest();
        }
        // compare with the dispatched request
        while (!same) {
            if (originalRequest.equals(dispatchedRequest)) {
                same = true;
            }
            if (!same && dispatchedRequest instanceof ServletRequestWrapper) {
                dispatchedRequest = ((ServletRequestWrapper) dispatchedRequest).getRequest();
            } else {
                break;
            }
        }
        if (!same) {
            throw new ServletException(sm.getString("applicationDispatcher.specViolation.request"));
        }
        same = false;
        ServletResponse dispatchedResponse = appResponse;
        // find the response that was preplaceded into the service method
        while (originalResponse instanceof ServletResponseWrapper && ((ServletResponseWrapper) originalResponse).getResponse() != null) {
            originalResponse = ((ServletResponseWrapper) originalResponse).getResponse();
        }
        // compare with the dispatched response
        while (!same) {
            if (originalResponse.equals(dispatchedResponse)) {
                same = true;
            }
            if (!same && dispatchedResponse instanceof ServletResponseWrapper) {
                dispatchedResponse = ((ServletResponseWrapper) dispatchedResponse).getResponse();
            } else {
                break;
            }
        }
        if (!same) {
            throw new ServletException(sm.getString("applicationDispatcher.specViolation.response"));
        }
    }

    private void recycleRequestWrapper(State state) {
        if (state.wrapRequest instanceof ApplicationHttpRequest) {
            ((ApplicationHttpRequest) state.wrapRequest).recycle();
        }
    }
}

19 Source : ResponseFacade.java
with Apache License 2.0
from wangyingjie

/**
 * Facade clreplaced that wraps a Coyote response object.
 * All methods are delegated to the wrapped response.
 *
 * @author Remy Maucherat
 * @author Jean-Francois Arcand
 */
@SuppressWarnings("deprecation")
public clreplaced ResponseFacade implements HttpServletResponse {

    // ----------------------------------------------------------- DoPrivileged
    private final clreplaced SetContentTypePrivilegedAction implements PrivilegedAction<Void> {

        private final String contentType;

        public SetContentTypePrivilegedAction(String contentType) {
            this.contentType = contentType;
        }

        @Override
        public Void run() {
            response.setContentType(contentType);
            return null;
        }
    }

    private final clreplaced DateHeaderPrivilegedAction implements PrivilegedAction<Void> {

        private final String name;

        private final long value;

        private final boolean add;

        DateHeaderPrivilegedAction(String name, long value, boolean add) {
            this.name = name;
            this.value = value;
            this.add = add;
        }

        @Override
        public Void run() {
            if (add) {
                response.addDateHeader(name, value);
            } else {
                response.setDateHeader(name, value);
            }
            return null;
        }
    }

    // ----------------------------------------------------------- Constructors
    /**
     * Construct a wrapper for the specified response.
     *
     * @param response The response to be wrapped
     */
    public ResponseFacade(Response response) {
        this.response = response;
    }

    // ----------------------------------------------- Clreplaced/Instance Variables
    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    /**
     * The wrapped response.
     */
    protected Response response = null;

    // --------------------------------------------------------- Public Methods
    /**
     * Clear facade.
     */
    public void clear() {
        response = null;
    }

    /**
     * Prevent cloning the facade.
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    public void finish() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        response.setSuspended(true);
    }

    public boolean isFinished() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.isSuspended();
    }

    public long getContentWritten() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.getContentWritten();
    }

    // ------------------------------------------------ ServletResponse Methods
    @Override
    public String getCharacterEncoding() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.getCharacterEncoding();
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        // if (isFinished())
        // throw new IllegalStateException
        // (/*sm.getString("responseFacade.finished")*/);
        ServletOutputStream sos = response.getOutputStream();
        if (isFinished()) {
            response.setSuspended(true);
        }
        return (sos);
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        // if (isFinished())
        // throw new IllegalStateException
        // (/*sm.getString("responseFacade.finished")*/);
        PrintWriter writer = response.getWriter();
        if (isFinished()) {
            response.setSuspended(true);
        }
        return (writer);
    }

    @Override
    public void setContentLength(int len) {
        if (isCommitted()) {
            return;
        }
        response.setContentLength(len);
    }

    @Override
    public void setContentType(String type) {
        if (isCommitted()) {
            return;
        }
        if (SecurityUtil.isPackageProtectionEnabled()) {
            AccessController.doPrivileged(new SetContentTypePrivilegedAction(type));
        } else {
            response.setContentType(type);
        }
    }

    @Override
    public void setBufferSize(int size) {
        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.setBufferSize.ise"));
        }
        response.setBufferSize(size);
    }

    @Override
    public int getBufferSize() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.getBufferSize();
    }

    @Override
    public void flushBuffer() throws IOException {
        if (isFinished()) {
            // throw new IllegalStateException
            // (/*sm.getString("responseFacade.finished")*/);
            return;
        }
        if (SecurityUtil.isPackageProtectionEnabled()) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {

                    @Override
                    public Void run() throws IOException {
                        response.setAppCommitted(true);
                        response.flushBuffer();
                        return null;
                    }
                });
            } catch (PrivilegedActionException e) {
                Exception ex = e.getException();
                if (ex instanceof IOException) {
                    throw (IOException) ex;
                }
            }
        } else {
            response.setAppCommitted(true);
            response.flushBuffer();
        }
    }

    @Override
    public void resetBuffer() {
        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.resetBuffer.ise"));
        }
        response.resetBuffer();
    }

    @Override
    public boolean isCommitted() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return (response.isAppCommitted());
    }

    @Override
    public void reset() {
        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.reset.ise"));
        }
        response.reset();
    }

    @Override
    public void setLocale(Locale loc) {
        if (isCommitted()) {
            return;
        }
        response.setLocale(loc);
    }

    @Override
    public Locale getLocale() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.getLocale();
    }

    @Override
    public void addCookie(Cookie cookie) {
        if (isCommitted()) {
            return;
        }
        response.addCookie(cookie);
    }

    @Override
    public boolean containsHeader(String name) {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.containsHeader(name);
    }

    @Override
    public String encodeURL(String url) {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.encodeURL(url);
    }

    @Override
    public String encodeRedirectURL(String url) {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.encodeRedirectURL(url);
    }

    @Override
    public String encodeUrl(String url) {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.encodeURL(url);
    }

    @Override
    public String encodeRedirectUrl(String url) {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.encodeRedirectURL(url);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.sendError.ise"));
        }
        response.setAppCommitted(true);
        response.sendError(sc, msg);
    }

    @Override
    public void sendError(int sc) throws IOException {
        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.sendError.ise"));
        }
        response.setAppCommitted(true);
        response.sendError(sc);
    }

    @Override
    public void sendRedirect(String location) throws IOException {
        if (isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteResponse.sendRedirect.ise"));
        }
        response.setAppCommitted(true);
        response.sendRedirect(location);
    }

    @Override
    public void setDateHeader(String name, long date) {
        if (isCommitted()) {
            return;
        }
        if (Globals.IS_SECURITY_ENABLED) {
            AccessController.doPrivileged(new DateHeaderPrivilegedAction(name, date, false));
        } else {
            response.setDateHeader(name, date);
        }
    }

    @Override
    public void addDateHeader(String name, long date) {
        if (isCommitted()) {
            return;
        }
        if (Globals.IS_SECURITY_ENABLED) {
            AccessController.doPrivileged(new DateHeaderPrivilegedAction(name, date, true));
        } else {
            response.addDateHeader(name, date);
        }
    }

    @Override
    public void setHeader(String name, String value) {
        if (isCommitted()) {
            return;
        }
        response.setHeader(name, value);
    }

    @Override
    public void addHeader(String name, String value) {
        if (isCommitted()) {
            return;
        }
        response.addHeader(name, value);
    }

    @Override
    public void setIntHeader(String name, int value) {
        if (isCommitted()) {
            return;
        }
        response.setIntHeader(name, value);
    }

    @Override
    public void addIntHeader(String name, int value) {
        if (isCommitted()) {
            return;
        }
        response.addIntHeader(name, value);
    }

    @Override
    public void setStatus(int sc) {
        if (isCommitted()) {
            return;
        }
        response.setStatus(sc);
    }

    @Override
    public void setStatus(int sc, String sm) {
        if (isCommitted()) {
            return;
        }
        response.setStatus(sc, sm);
    }

    @Override
    public String getContentType() {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        return response.getContentType();
    }

    @Override
    public void setCharacterEncoding(String arg0) {
        if (response == null) {
            throw new IllegalStateException(sm.getString("responseFacade.nullResponse"));
        }
        response.setCharacterEncoding(arg0);
    }

    @Override
    public int getStatus() {
        return response.getStatus();
    }

    @Override
    public String getHeader(String name) {
        return response.getHeader(name);
    }

    @Override
    public Collection<String> getHeaderNames() {
        return response.getHeaderNames();
    }

    @Override
    public Collection<String> getHeaders(String name) {
        return response.getHeaders(name);
    }
}

19 Source : RequestFacade.java
with Apache License 2.0
from wangyingjie

/**
 * Facade clreplaced that wraps a Coyote request object.
 * All methods are delegated to the wrapped request.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 * @author Jean-Francois Arcand
 */
@SuppressWarnings("deprecation")
public clreplaced RequestFacade implements HttpServletRequest {

    // ----------------------------------------------------------- DoPrivileged
    private final clreplaced GetAttributePrivilegedAction implements PrivilegedAction<Enumeration<String>> {

        @Override
        public Enumeration<String> run() {
            return request.getAttributeNames();
        }
    }

    private final clreplaced GetParameterMapPrivilegedAction implements PrivilegedAction<Map<String, String[]>> {

        @Override
        public Map<String, String[]> run() {
            return request.getParameterMap();
        }
    }

    private final clreplaced GetRequestDispatcherPrivilegedAction implements PrivilegedAction<RequestDispatcher> {

        private final String path;

        public GetRequestDispatcherPrivilegedAction(String path) {
            this.path = path;
        }

        @Override
        public RequestDispatcher run() {
            return request.getRequestDispatcher(path);
        }
    }

    private final clreplaced GetParameterPrivilegedAction implements PrivilegedAction<String> {

        public String name;

        public GetParameterPrivilegedAction(String name) {
            this.name = name;
        }

        @Override
        public String run() {
            return request.getParameter(name);
        }
    }

    private final clreplaced GetParameterNamesPrivilegedAction implements PrivilegedAction<Enumeration<String>> {

        @Override
        public Enumeration<String> run() {
            return request.getParameterNames();
        }
    }

    private final clreplaced GetParameterValuePrivilegedAction implements PrivilegedAction<String[]> {

        public String name;

        public GetParameterValuePrivilegedAction(String name) {
            this.name = name;
        }

        @Override
        public String[] run() {
            return request.getParameterValues(name);
        }
    }

    private final clreplaced GetCookiesPrivilegedAction implements PrivilegedAction<Cookie[]> {

        @Override
        public Cookie[] run() {
            return request.getCookies();
        }
    }

    private final clreplaced GetCharacterEncodingPrivilegedAction implements PrivilegedAction<String> {

        @Override
        public String run() {
            return request.getCharacterEncoding();
        }
    }

    private final clreplaced GetHeadersPrivilegedAction implements PrivilegedAction<Enumeration<String>> {

        private final String name;

        public GetHeadersPrivilegedAction(String name) {
            this.name = name;
        }

        @Override
        public Enumeration<String> run() {
            return request.getHeaders(name);
        }
    }

    private final clreplaced GetHeaderNamesPrivilegedAction implements PrivilegedAction<Enumeration<String>> {

        @Override
        public Enumeration<String> run() {
            return request.getHeaderNames();
        }
    }

    private final clreplaced GetLocalePrivilegedAction implements PrivilegedAction<Locale> {

        @Override
        public Locale run() {
            return request.getLocale();
        }
    }

    private final clreplaced GetLocalesPrivilegedAction implements PrivilegedAction<Enumeration<Locale>> {

        @Override
        public Enumeration<Locale> run() {
            return request.getLocales();
        }
    }

    private final clreplaced GetSessionPrivilegedAction implements PrivilegedAction<HttpSession> {

        private final boolean create;

        public GetSessionPrivilegedAction(boolean create) {
            this.create = create;
        }

        @Override
        public HttpSession run() {
            return request.getSession(create);
        }
    }

    // ----------------------------------------------------------- Constructors
    /**
     * Construct a wrapper for the specified request.
     *
     * @param request The request to be wrapped
     */
    public RequestFacade(Request request) {
        this.request = request;
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * The wrapped request.
     */
    protected Request request = null;

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    // --------------------------------------------------------- Public Methods
    /**
     * Clear facade.
     */
    public void clear() {
        request = null;
    }

    /**
     * Prevent cloning the facade.
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    // ------------------------------------------------- ServletRequest Methods
    @Override
    public Object getAttribute(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getAttribute(name);
    }

    @Override
    public Enumeration<String> getAttributeNames() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetAttributePrivilegedAction());
        } else {
            return request.getAttributeNames();
        }
    }

    @Override
    public String getCharacterEncoding() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetCharacterEncodingPrivilegedAction());
        } else {
            return request.getCharacterEncoding();
        }
    }

    @Override
    public void setCharacterEncoding(String env) throws java.io.UnsupportedEncodingException {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        request.setCharacterEncoding(env);
    }

    @Override
    public int getContentLength() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getContentLength();
    }

    @Override
    public String getContentType() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getContentType();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getInputStream();
    }

    @Override
    public String getParameter(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetParameterPrivilegedAction(name));
        } else {
            return request.getParameter(name);
        }
    }

    @Override
    public Enumeration<String> getParameterNames() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetParameterNamesPrivilegedAction());
        } else {
            return request.getParameterNames();
        }
    }

    @Override
    public String[] getParameterValues(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        String[] ret = null;
        /*
         * Clone the returned array only if there is a security manager
         * in place, so that performance won't suffer in the non-secure case
         */
        if (SecurityUtil.isPackageProtectionEnabled()) {
            ret = AccessController.doPrivileged(new GetParameterValuePrivilegedAction(name));
            if (ret != null) {
                ret = ret.clone();
            }
        } else {
            ret = request.getParameterValues(name);
        }
        return ret;
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetParameterMapPrivilegedAction());
        } else {
            return request.getParameterMap();
        }
    }

    @Override
    public String getProtocol() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getProtocol();
    }

    @Override
    public String getScheme() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getScheme();
    }

    @Override
    public String getServerName() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getServerName();
    }

    @Override
    public int getServerPort() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getServerPort();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getReader();
    }

    @Override
    public String getRemoteAddr() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRemoteAddr();
    }

    @Override
    public String getRemoteHost() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRemoteHost();
    }

    @Override
    public void setAttribute(String name, Object o) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        request.setAttribute(name, o);
    }

    @Override
    public void removeAttribute(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        request.removeAttribute(name);
    }

    @Override
    public Locale getLocale() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetLocalePrivilegedAction());
        } else {
            return request.getLocale();
        }
    }

    @Override
    public Enumeration<Locale> getLocales() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetLocalesPrivilegedAction());
        } else {
            return request.getLocales();
        }
    }

    @Override
    public boolean isSecure() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.isSecure();
    }

    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetRequestDispatcherPrivilegedAction(path));
        } else {
            return request.getRequestDispatcher(path);
        }
    }

    @Override
    public String getRealPath(String path) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRealPath(path);
    }

    @Override
    public String getAuthType() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getAuthType();
    }

    @Override
    public Cookie[] getCookies() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        Cookie[] ret = null;
        /*
         * Clone the returned array only if there is a security manager
         * in place, so that performance won't suffer in the non-secure case
         */
        if (SecurityUtil.isPackageProtectionEnabled()) {
            ret = AccessController.doPrivileged(new GetCookiesPrivilegedAction());
            if (ret != null) {
                ret = ret.clone();
            }
        } else {
            ret = request.getCookies();
        }
        return ret;
    }

    @Override
    public long getDateHeader(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getDateHeader(name);
    }

    @Override
    public String getHeader(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getHeader(name);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetHeadersPrivilegedAction(name));
        } else {
            return request.getHeaders(name);
        }
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (Globals.IS_SECURITY_ENABLED) {
            return AccessController.doPrivileged(new GetHeaderNamesPrivilegedAction());
        } else {
            return request.getHeaderNames();
        }
    }

    @Override
    public int getIntHeader(String name) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getIntHeader(name);
    }

    @Override
    public String getMethod() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getMethod();
    }

    @Override
    public String getPathInfo() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getPathInfo();
    }

    @Override
    public String getPathTranslated() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getPathTranslated();
    }

    @Override
    public String getContextPath() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getContextPath();
    }

    @Override
    public String getQueryString() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getQueryString();
    }

    @Override
    public String getRemoteUser() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRemoteUser();
    }

    @Override
    public boolean isUserInRole(String role) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.isUserInRole(role);
    }

    @Override
    public java.security.Principal getUserPrincipal() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getUserPrincipal();
    }

    @Override
    public String getRequestedSessionId() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRequestedSessionId();
    }

    @Override
    public String getRequestURI() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRequestURI();
    }

    @Override
    public StringBuffer getRequestURL() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRequestURL();
    }

    @Override
    public String getServletPath() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getServletPath();
    }

    @Override
    public HttpSession getSession(boolean create) {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        if (SecurityUtil.isPackageProtectionEnabled()) {
            return AccessController.doPrivileged(new GetSessionPrivilegedAction(create));
        } else {
            return request.getSession(create);
        }
    }

    @Override
    public HttpSession getSession() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return getSession(true);
    }

    @Override
    public boolean isRequestedSessionIdValid() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.isRequestedSessionIdValid();
    }

    @Override
    public boolean isRequestedSessionIdFromCookie() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.isRequestedSessionIdFromCookie();
    }

    @Override
    public boolean isRequestedSessionIdFromURL() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.isRequestedSessionIdFromURL();
    }

    @Override
    public boolean isRequestedSessionIdFromUrl() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.isRequestedSessionIdFromURL();
    }

    @Override
    public String getLocalAddr() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getLocalAddr();
    }

    @Override
    public String getLocalName() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getLocalName();
    }

    @Override
    public int getLocalPort() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getLocalPort();
    }

    @Override
    public int getRemotePort() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getRemotePort();
    }

    @Override
    public ServletContext getServletContext() {
        if (request == null) {
            throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));
        }
        return request.getServletContext();
    }

    @Override
    public AsyncContext startAsync() throws IllegalStateException {
        return request.startAsync();
    }

    @Override
    public AsyncContext startAsync(ServletRequest request, ServletResponse response) throws IllegalStateException {
        return this.request.startAsync(request, response);
    }

    @Override
    public boolean isAsyncStarted() {
        return request.isAsyncStarted();
    }

    @Override
    public boolean isAsyncSupported() {
        return request.isAsyncSupported();
    }

    @Override
    public AsyncContext getAsyncContext() {
        return request.getAsyncContext();
    }

    @Override
    public DispatcherType getDispatcherType() {
        return request.getDispatcherType();
    }

    @Override
    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
        return request.authenticate(response);
    }

    @Override
    public void login(String username, String preplacedword) throws ServletException {
        request.login(username, preplacedword);
    }

    @Override
    public void logout() throws ServletException {
        request.logout();
    }

    @Override
    public Collection<Part> getParts() throws IllegalStateException, IOException, ServletException {
        return request.getParts();
    }

    @Override
    public Part getPart(String name) throws IllegalStateException, IOException, ServletException {
        return request.getPart(name);
    }

    public boolean getAllowTrace() {
        return request.getConnector().getAllowTrace();
    }

    /**
     * Sets the response status to {@link
     * HttpServletResponse#SC_SWITCHING_PROTOCOLS} and flushes the response.
     * Protocol specific headers must have already been set before this method
     * is called.
     *
     * @param inbound   The handler for all further incoming data on the current
     *                  connection.
     *
     * @throws IOException  If the upgrade fails (e.g. if the response has
     *                      already been committed.
     */
    public void doUpgrade(UpgradeInbound inbound) throws IOException {
        request.doUpgrade(inbound);
    }

    public <T extends HttpUpgradeHandler> T upgrade(Clreplaced<T> httpUpgradeHandlerClreplaced) throws ServletException {
        return request.upgrade(httpUpgradeHandlerClreplaced);
    }
}

19 Source : MapperListener.java
with Apache License 2.0
from wangyingjie

/**
 * Mapper listener.
 *
 * @author Remy Maucherat
 * @author Costin Manolache
 */
public clreplaced MapperListener extends LifecycleMBeanBase implements ContainerListener, LifecycleListener {

    private static final Log log = LogFactory.getLog(MapperListener.clreplaced);

    // ----------------------------------------------------- Instance Variables
    /**
     * replacedociated mapper.
     */
    private Mapper mapper = null;

    /**
     * replacedociated connector
     */
    private Connector connector = null;

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    /**
     * The domain (effectively the engine) this mapper is replacedociated with
     */
    private final String domain = null;

    // ----------------------------------------------------------- Constructors
    /**
     * Create mapper listener.
     */
    public MapperListener(Mapper mapper, Connector connector) {
        this.mapper = mapper;
        this.connector = connector;
    }

    // --------------------------------------------------------- Public Methods
    @Deprecated
    public String getConnectorName() {
        return this.connector.toString();
    }

    // ------------------------------------------------------- Lifecycle Methods
    @Override
    public void startInternal() throws LifecycleException {
        setState(LifecycleState.STARTING);
        // Find any components that have already been initialized since the
        // MBean listener won't be notified as those components will have
        // already registered their MBeans
        findDefaultHost();
        Engine engine = (Engine) connector.getService().getContainer();
        addListeners(engine);
        Container[] conHosts = engine.findChildren();
        for (Container conHost : conHosts) {
            Host host = (Host) conHost;
            if (!LifecycleState.NEW.equals(host.getState())) {
                // Registering the host will register the context and wrappers
                registerHost(host);
            }
        }
    }

    @Override
    public void stopInternal() throws LifecycleException {
        setState(LifecycleState.STOPPING);
        Engine engine = (Engine) connector.getService().getContainer();
        removeListeners(engine);
    }

    @Override
    protected String getDomainInternal() {
        // Should be the same as the connector
        return connector.getDomainInternal();
    }

    @Override
    protected String getObjectNameKeyProperties() {
        // Same as connector but Mapper rather than Connector
        return connector.createObjectNameKeyProperties("Mapper");
    }

    // --------------------------------------------- Container Listener methods
    @Override
    public void containerEvent(ContainerEvent event) {
        if (Container.ADD_CHILD_EVENT.equals(event.getType())) {
            Container child = (Container) event.getData();
            addListeners(child);
            // If child is started then it is too late for life-cycle listener
            // to register the child so register it here
            if (child.getState().isAvailable()) {
                if (child instanceof Host) {
                    registerHost((Host) child);
                } else if (child instanceof Context) {
                    registerContext((Context) child);
                } else if (child instanceof Wrapper) {
                    // Only if the Context has started. If it has not, then it
                    // will have its own "after_start" life-cycle event later.
                    if (child.getParent().getState().isAvailable()) {
                        registerWrapper((Wrapper) child);
                    }
                }
            }
        } else if (Container.REMOVE_CHILD_EVENT.equals(event.getType())) {
            Container child = (Container) event.getData();
            removeListeners(child);
        // No need to unregister - life-cycle listener will handle this when
        // the child stops
        } else if (Host.ADD_ALIAS_EVENT.equals(event.getType())) {
            // Handle dynamically adding host aliases
            mapper.addHostAlias(((Host) event.getSource()).getName(), event.getData().toString());
        } else if (Host.REMOVE_ALIAS_EVENT.equals(event.getType())) {
            // Handle dynamically removing host aliases
            mapper.removeHostAlias(event.getData().toString());
        } else if (Wrapper.ADD_MAPPING_EVENT.equals(event.getType())) {
            // Handle dynamically adding wrappers
            Wrapper wrapper = (Wrapper) event.getSource();
            Context context = (Context) wrapper.getParent();
            String contextPath = context.getPath();
            if ("/".equals(contextPath)) {
                contextPath = "";
            }
            String version = context.getWebappVersion();
            String hostName = context.getParent().getName();
            String wrapperName = wrapper.getName();
            String mapping = (String) event.getData();
            boolean jspWildCard = ("jsp".equals(wrapperName) && mapping.endsWith("/*"));
            mapper.addWrapper(hostName, contextPath, version, mapping, wrapper, jspWildCard, context.isResourceOnlyServlet(wrapperName));
        } else if (Wrapper.REMOVE_MAPPING_EVENT.equals(event.getType())) {
            // Handle dynamically removing wrappers
            Wrapper wrapper = (Wrapper) event.getSource();
            Context context = (Context) wrapper.getParent();
            String contextPath = context.getPath();
            if ("/".equals(contextPath)) {
                contextPath = "";
            }
            String version = context.getWebappVersion();
            String hostName = context.getParent().getName();
            String mapping = (String) event.getData();
            mapper.removeWrapper(hostName, contextPath, version, mapping);
        } else if (Context.ADD_WELCOME_FILE_EVENT.equals(event.getType())) {
            // Handle dynamically adding welcome files
            Context context = (Context) event.getSource();
            String hostName = context.getParent().getName();
            String contextPath = context.getPath();
            if ("/".equals(contextPath)) {
                contextPath = "";
            }
            String welcomeFile = (String) event.getData();
            mapper.addWelcomeFile(hostName, contextPath, context.getWebappVersion(), welcomeFile);
        } else if (Context.REMOVE_WELCOME_FILE_EVENT.equals(event.getType())) {
            // Handle dynamically removing welcome files
            Context context = (Context) event.getSource();
            String hostName = context.getParent().getName();
            String contextPath = context.getPath();
            if ("/".equals(contextPath)) {
                contextPath = "";
            }
            String welcomeFile = (String) event.getData();
            mapper.removeWelcomeFile(hostName, contextPath, context.getWebappVersion(), welcomeFile);
        } else if (Context.CLEAR_WELCOME_FILES_EVENT.equals(event.getType())) {
            // Handle dynamically clearing welcome files
            Context context = (Context) event.getSource();
            String hostName = context.getParent().getName();
            String contextPath = context.getPath();
            if ("/".equals(contextPath)) {
                contextPath = "";
            }
            mapper.clearWelcomeFiles(hostName, contextPath, context.getWebappVersion());
        }
    }

    // ------------------------------------------------------ Protected Methods
    private void findDefaultHost() {
        Engine engine = (Engine) connector.getService().getContainer();
        String defaultHost = engine.getDefaultHost();
        boolean found = false;
        if (defaultHost != null && defaultHost.length() > 0) {
            Container[] containers = engine.findChildren();
            for (Container container : containers) {
                Host host = (Host) container;
                if (defaultHost.equalsIgnoreCase(host.getName())) {
                    found = true;
                    break;
                }
                String[] aliases = host.findAliases();
                for (String alias : aliases) {
                    if (defaultHost.equalsIgnoreCase(alias)) {
                        found = true;
                        break;
                    }
                }
            }
        }
        if (found) {
            mapper.setDefaultHostName(defaultHost);
        } else {
            log.warn(sm.getString("mapperListener.unknownDefaultHost", defaultHost, connector));
        }
    }

    /**
     * Register host.
     */
    private void registerHost(Host host) {
        String[] aliases = host.findAliases();
        mapper.addHost(host.getName(), aliases, host);
        for (Container container : host.findChildren()) {
            if (container.getState().isAvailable()) {
                registerContext((Context) container);
            }
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("mapperListener.registerHost", host.getName(), domain, connector));
        }
    }

    /**
     * Unregister host.
     */
    private void unregisterHost(Host host) {
        String hostname = host.getName();
        mapper.removeHost(hostname);
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("mapperListener.unregisterHost", hostname, domain, connector));
        }
    }

    /**
     * Unregister wrapper.
     */
    private void unregisterWrapper(Wrapper wrapper) {
        Context context = (Context) wrapper.getParent();
        String contextPath = context.getPath();
        String wrapperName = wrapper.getName();
        if ("/".equals(contextPath)) {
            contextPath = "";
        }
        String version = context.getWebappVersion();
        String hostName = context.getParent().getName();
        String[] mappings = wrapper.findMappings();
        for (String mapping : mappings) {
            mapper.removeWrapper(hostName, contextPath, version, mapping);
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("mapperListener.unregisterWrapper", wrapperName, contextPath, connector));
        }
    }

    /**
     * Register context.
     */
    private void registerContext(Context context) {
        String contextPath = context.getPath();
        if ("/".equals(contextPath)) {
            contextPath = "";
        }
        Container host = context.getParent();
        javax.naming.Context resources = context.getResources();
        String[] welcomeFiles = context.findWelcomeFiles();
        List<WrapperMappingInfo> wrappers = new ArrayList<WrapperMappingInfo>();
        for (Container container : context.findChildren()) {
            prepareWrapperMappingInfo(context, (Wrapper) container, wrappers);
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("mapperListener.registerWrapper", container.getName(), contextPath, connector));
            }
        }
        mapper.addContextVersion(host.getName(), host, contextPath, context.getWebappVersion(), context, welcomeFiles, resources, wrappers, context.getMapperContextRootRedirectEnabled(), context.getMapperDirectoryRedirectEnabled());
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("mapperListener.registerContext", contextPath, connector));
        }
    }

    /**
     * Unregister context.
     */
    private void unregisterContext(Context context) {
        String contextPath = context.getPath();
        if ("/".equals(contextPath)) {
            contextPath = "";
        }
        String hostName = context.getParent().getName();
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("mapperListener.unregisterContext", contextPath, connector));
        }
        if (context.getPaused()) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("mapperListener.pauseContext", contextPath, connector));
            }
            mapper.pauseContextVersion(context, hostName, contextPath, context.getWebappVersion());
        } else {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("mapperListener.unregisterContext", contextPath, connector));
            }
            mapper.removeContextVersion(hostName, contextPath, context.getWebappVersion());
        }
    }

    /**
     * Register wrapper.
     */
    private void registerWrapper(Wrapper wrapper) {
        Context context = (Context) wrapper.getParent();
        String contextPath = context.getPath();
        if ("/".equals(contextPath)) {
            contextPath = "";
        }
        String version = context.getWebappVersion();
        String hostName = context.getParent().getName();
        List<WrapperMappingInfo> wrappers = new ArrayList<WrapperMappingInfo>();
        prepareWrapperMappingInfo(context, wrapper, wrappers);
        mapper.addWrappers(hostName, contextPath, version, wrappers);
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("mapperListener.registerWrapper", wrapper.getName(), contextPath, connector));
        }
    }

    /**
     * Populate <code>wrappers</code> list with information for registration of
     * mappings for this wrapper in this context.
     *
     * @param context
     * @param wrapper
     * @param list
     */
    private void prepareWrapperMappingInfo(Context context, Wrapper wrapper, List<WrapperMappingInfo> wrappers) {
        String wrapperName = wrapper.getName();
        boolean resourceOnly = context.isResourceOnlyServlet(wrapperName);
        String[] mappings = wrapper.findMappings();
        for (String mapping : mappings) {
            boolean jspWildCard = (wrapperName.equals("jsp") && mapping.endsWith("/*"));
            wrappers.add(new WrapperMappingInfo(mapping, wrapper, jspWildCard, resourceOnly));
        }
    }

    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
            Object obj = event.getSource();
            if (obj instanceof Wrapper) {
                Wrapper w = (Wrapper) obj;
                // Only if the Context has started. If it has not, then it will
                // have its own "after_start" event later.
                if (w.getParent().getState().isAvailable()) {
                    registerWrapper(w);
                }
            } else if (obj instanceof Context) {
                Context c = (Context) obj;
                // Only if the Host has started. If it has not, then it will
                // have its own "after_start" event later.
                if (c.getParent().getState().isAvailable()) {
                    registerContext(c);
                }
            } else if (obj instanceof Host) {
                registerHost((Host) obj);
            }
        } else if (event.getType().equals(Lifecycle.BEFORE_STOP_EVENT)) {
            Object obj = event.getSource();
            if (obj instanceof Wrapper) {
                unregisterWrapper((Wrapper) obj);
            } else if (obj instanceof Context) {
                unregisterContext((Context) obj);
            } else if (obj instanceof Host) {
                unregisterHost((Host) obj);
            }
        }
    }

    /**
     * Add this mapper to the container and all child containers
     *
     * @param container
     */
    private void addListeners(Container container) {
        container.addContainerListener(this);
        container.addLifecycleListener(this);
        for (Container child : container.findChildren()) {
            addListeners(child);
        }
    }

    /**
     * Remove this mapper from the container and all child containers
     *
     * @param container
     */
    private void removeListeners(Container container) {
        container.removeContainerListener(this);
        container.removeLifecycleListener(this);
        for (Container child : container.findChildren()) {
            removeListeners(child);
        }
    }
}

19 Source : CometEventImpl.java
with Apache License 2.0
from wangyingjie

public clreplaced CometEventImpl implements CometEvent {

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    public CometEventImpl(Request request, Response response) {
        this.request = request;
        this.response = response;
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * replacedociated request.
     */
    protected Request request = null;

    /**
     * replacedociated response.
     */
    protected Response response = null;

    /**
     * Event type.
     */
    protected EventType eventType = EventType.BEGIN;

    /**
     * Event sub type.
     */
    protected EventSubType eventSubType = null;

    // --------------------------------------------------------- Public Methods
    /**
     * Clear the event.
     */
    public void clear() {
        request = null;
        response = null;
    }

    public void setEventType(EventType eventType) {
        this.eventType = eventType;
    }

    public void setEventSubType(EventSubType eventSubType) {
        this.eventSubType = eventSubType;
    }

    @Override
    public void close() throws IOException {
        if (request == null) {
            throw new IllegalStateException(sm.getString("cometEvent.nullRequest"));
        }
        request.finishRequest();
        response.finishResponse();
        if (request.isComet()) {
            request.cometClose();
        }
    }

    @Override
    public EventSubType getEventSubType() {
        return eventSubType;
    }

    @Override
    public EventType getEventType() {
        return eventType;
    }

    @Override
    public HttpServletRequest getHttpServletRequest() {
        return request.getRequest();
    }

    @Override
    public HttpServletResponse getHttpServletResponse() {
        return response.getResponse();
    }

    @Override
    public void setTimeout(int timeout) throws IOException, ServletException, UnsupportedOperationException {
        if (Boolean.TRUE.equals(request.getAttribute(Globals.COMET_TIMEOUT_SUPPORTED_ATTR))) {
            request.setAttribute(Globals.COMET_TIMEOUT_ATTR, Integer.valueOf(timeout));
            if (request.isComet()) {
                request.setCometTimeout(timeout);
            }
        } else {
            throw new UnsupportedOperationException();
        }
    }

    @Override
    public String toString() {
        StringBuilder buf = new StringBuilder();
        buf.append(super.toString());
        buf.append("[EventType:");
        buf.append(eventType);
        buf.append(", EventSubType:");
        buf.append(eventSubType);
        buf.append("]");
        return buf.toString();
    }
}

19 Source : JSSESocketFactory.java
with Apache License 2.0
from tryandcatch

/**
 * SSL server socket factory. It <b>requires</b> a valid RSA key and
 * JSSE.<br/>
 * keytool -genkey -alias tomcat -keyalg RSA</br>
 * Use "changeit" as preplacedword (this is the default we use).
 *
 * @author Harish Prabandham
 * @author Costin Manolache
 * @author Stefan Freyr Stefansson
 * @author EKR -- renamed to JSSESocketFactory
 * @author Jan Luehe
 * @author Bill Barker
 */
public clreplaced JSSESocketFactory implements ServerSocketFactory, Sreplacedil {

    private static final org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.clreplaced);

    private static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.net.jsse.res");

    // Defaults - made public where re-used
    private static final String defaultProtocol = Constants.SSL_PROTO_TLS;

    private static final String defaultKeystoreType = "JKS";

    private static final String defaultKeystoreFile = System.getProperty("user.home") + "/.keystore";

    private static final int defaultSessionCacheSize = 0;

    private static final int defaultSessionTimeout = 86400;

    private static final String ALLOW_ALL_SUPPORTED_CIPHERS = "ALL";

    public static final String DEFAULT_KEY_Preplaced = "changeit";

    private AbstractEndpoint<?> endpoint;

    private final boolean rfc5746Supported;

    private final String[] defaultServerProtocols;

    private final String[] defaultServerCipherSuites;

    protected SSLServerSocketFactory sslProxy = null;

    protected String[] enabledCiphers;

    protected String[] enabledProtocols;

    protected boolean allowUnsafeLegacyRenegotiation = false;

    /**
     * Flag to state that we require client authentication.
     */
    protected boolean requireClientAuth = false;

    /**
     * Flag to state that we would like client authentication.
     */
    protected boolean wantClientAuth = false;

    public JSSESocketFactory(AbstractEndpoint<?> endpoint) {
        this.endpoint = endpoint;
        String sslProtocol = endpoint.getSslProtocol();
        if (sslProtocol == null) {
            sslProtocol = defaultProtocol;
        }
        SSLContext context;
        try {
            context = SSLContext.getInstance(sslProtocol);
            context.init(null, null, null);
        } catch (NoSuchAlgorithmException e) {
            // This is fatal for the connector so throw an exception to prevent
            // it from starting
            throw new IllegalArgumentException(e);
        } catch (KeyManagementException e) {
            // This is fatal for the connector so throw an exception to prevent
            // it from starting
            throw new IllegalArgumentException(e);
        }
        // Supported cipher suites aren't accessible directly from the
        // SSLContext so use the SSL server socket factory
        SSLServerSocketFactory ssf = context.getServerSocketFactory();
        String[] supportedCiphers = ssf.getSupportedCipherSuites();
        boolean found = false;
        for (String cipher : supportedCiphers) {
            if ("TLS_EMPTY_RENEGOTIATION_INFO_SCSV".equals(cipher)) {
                found = true;
                break;
            }
        }
        rfc5746Supported = found;
        // There is no standard way to determine the default protocols and
        // cipher suites so create a server socket to see what the defaults are
        SSLServerSocket socket;
        try {
            socket = (SSLServerSocket) ssf.createServerSocket();
        } catch (IOException e) {
            // This is very likely to be fatal but there is a slim chance that
            // the JSSE implementation just doesn't like creating unbound
            // sockets so allow the code to proceed.
            defaultServerCipherSuites = new String[0];
            defaultServerProtocols = new String[0];
            log.warn(sm.getString("jsse.noDefaultCiphers", endpoint.getName()));
            log.warn(sm.getString("jsse.noDefaultProtocols", endpoint.getName()));
            return;
        }
        try {
            defaultServerCipherSuites = socket.getEnabledCipherSuites();
            if (defaultServerCipherSuites.length == 0) {
                log.warn(sm.getString("jsse.noDefaultCiphers", endpoint.getName()));
            }
            // Filter out all the SSL protocols (SSLv2 and SSLv3) from the defaults
            // since they are no longer considered secure
            List<String> filteredProtocols = new ArrayList<String>();
            for (String protocol : socket.getEnabledProtocols()) {
                if (protocol.toUpperCase(Locale.ENGLISH).contains("SSL")) {
                    log.debug(sm.getString("jsse.excludeDefaultProtocol", protocol));
                    continue;
                }
                filteredProtocols.add(protocol);
            }
            defaultServerProtocols = filteredProtocols.toArray(new String[filteredProtocols.size()]);
            if (defaultServerProtocols.length == 0) {
                log.warn(sm.getString("jsse.noDefaultProtocols", endpoint.getName()));
            }
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                log.warn(sm.getString("jsse.exceptionOnClose"), e);
            }
        }
    }

    @Override
    public ServerSocket createSocket(int port) throws IOException {
        init();
        ServerSocket socket = sslProxy.createServerSocket(port);
        initServerSocket(socket);
        return socket;
    }

    @Override
    public ServerSocket createSocket(int port, int backlog) throws IOException {
        init();
        ServerSocket socket = sslProxy.createServerSocket(port, backlog);
        initServerSocket(socket);
        return socket;
    }

    @Override
    public ServerSocket createSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
        init();
        ServerSocket socket = sslProxy.createServerSocket(port, backlog, ifAddress);
        initServerSocket(socket);
        return socket;
    }

    @Override
    public Socket acceptSocket(ServerSocket socket) throws IOException {
        SSLSocket asock = null;
        try {
            asock = (SSLSocket) socket.accept();
        } catch (SSLException e) {
            throw new SocketException("SSL handshake error" + e.toString());
        }
        return asock;
    }

    @Override
    public void handshake(Socket sock) throws IOException {
        // We do getSession instead of startHandshake() so we can call this multiple times
        SSLSession session = ((SSLSocket) sock).getSession();
        if (session.getCipherSuite().equals("SSL_NULL_WITH_NULL_NULL"))
            throw new IOException("SSL handshake failed. Ciper suite in SSL Session is SSL_NULL_WITH_NULL_NULL");
        if (!allowUnsafeLegacyRenegotiation && !rfc5746Supported) {
            // Prevent further handshakes by removing all cipher suites
            ((SSLSocket) sock).setEnabledCipherSuites(new String[0]);
        }
    }

    @Override
    public String[] getEnableableCiphers(SSLContext context) {
        String requestedCiphersStr = endpoint.getCiphers();
        if (ALLOW_ALL_SUPPORTED_CIPHERS.equals(requestedCiphersStr)) {
            return context.getSupportedSSLParameters().getCipherSuites();
        }
        if ((requestedCiphersStr == null) || (requestedCiphersStr.trim().length() == 0)) {
            return defaultServerCipherSuites;
        }
        List<String> requestedCiphers = new ArrayList<String>();
        for (String rc : requestedCiphersStr.split(",")) {
            final String cipher = rc.trim();
            if (cipher.length() > 0) {
                requestedCiphers.add(cipher);
            }
        }
        if (requestedCiphers.isEmpty()) {
            return defaultServerCipherSuites;
        }
        List<String> ciphers = new ArrayList<String>(requestedCiphers);
        String[] supportedCipherSuiteArray = context.getSupportedSSLParameters().getCipherSuites();
        // The IBM JRE will accept cipher suites names SSL_xxx or TLS_xxx but
        // only returns the SSL_xxx form for supported cipher suites. Therefore
        // need to filter the requested cipher suites using both forms with an
        // IBM JRE.
        List<String> supportedCipherSuiteList;
        if (JreVendor.IS_IBM_JVM) {
            supportedCipherSuiteList = new ArrayList<String>(supportedCipherSuiteArray.length * 2);
            for (String name : supportedCipherSuiteArray) {
                supportedCipherSuiteList.add(name);
                if (name.startsWith("SSL")) {
                    supportedCipherSuiteList.add("TLS" + name.substring(3));
                }
            }
        } else {
            supportedCipherSuiteList = Arrays.asList(supportedCipherSuiteArray);
        }
        ciphers.retainAll(supportedCipherSuiteList);
        if (ciphers.isEmpty()) {
            log.warn(sm.getString("jsse.requested_ciphers_not_supported", requestedCiphersStr));
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("jsse.enableable_ciphers", ciphers));
            if (ciphers.size() != requestedCiphers.size()) {
                List<String> skipped = new ArrayList<String>(requestedCiphers);
                skipped.removeAll(ciphers);
                log.debug(sm.getString("jsse.unsupported_ciphers", skipped));
            }
        }
        return ciphers.toArray(new String[ciphers.size()]);
    }

    /*
     * Gets the SSL server's keystore preplacedword.
     */
    protected String getKeystorePreplacedword() {
        String keystorePreplaced = endpoint.getKeystorePreplaced();
        if (keystorePreplaced == null) {
            keystorePreplaced = endpoint.getKeyPreplaced();
        }
        if (keystorePreplaced == null) {
            keystorePreplaced = DEFAULT_KEY_Preplaced;
        }
        return keystorePreplaced;
    }

    /*
     * Gets the SSL server's keystore.
     */
    protected KeyStore getKeystore(String type, String provider, String preplaced) throws IOException {
        String keystoreFile = endpoint.getKeystoreFile();
        if (keystoreFile == null)
            keystoreFile = defaultKeystoreFile;
        return getStore(type, provider, keystoreFile, preplaced);
    }

    /*
     * Gets the SSL server's truststore.
     */
    protected KeyStore getTrustStore(String keystoreType, String keystoreProvider) throws IOException {
        KeyStore trustStore = null;
        String truststoreFile = endpoint.getTruststoreFile();
        if (truststoreFile == null) {
            truststoreFile = System.getProperty("javax.net.ssl.trustStore");
        }
        if (log.isDebugEnabled()) {
            log.debug("Truststore = " + truststoreFile);
        }
        String truststorePreplacedword = endpoint.getTruststorePreplaced();
        if (truststorePreplacedword == null) {
            truststorePreplacedword = System.getProperty("javax.net.ssl.trustStorePreplacedword");
        }
        if (log.isDebugEnabled()) {
            log.debug("TrustPreplaced = " + truststorePreplacedword);
        }
        String truststoreType = endpoint.getTruststoreType();
        if (truststoreType == null) {
            truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
        }
        if (truststoreType == null) {
            truststoreType = keystoreType;
        }
        if (log.isDebugEnabled()) {
            log.debug("trustType = " + truststoreType);
        }
        String truststoreProvider = endpoint.getTruststoreProvider();
        if (truststoreProvider == null) {
            truststoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider");
        }
        if (truststoreProvider == null) {
            truststoreProvider = keystoreProvider;
        }
        if (log.isDebugEnabled()) {
            log.debug("trustProvider = " + truststoreProvider);
        }
        if (truststoreFile != null) {
            try {
                trustStore = getStore(truststoreType, truststoreProvider, truststoreFile, truststorePreplacedword);
            } catch (IOException ioe) {
                Throwable cause = ioe.getCause();
                if (cause instanceof UnrecoverableKeyException) {
                    // Log a warning we had a preplacedword issue
                    log.warn(sm.getString("jsse.invalid_truststore_preplacedword"), cause);
                    // Re-try
                    trustStore = getStore(truststoreType, truststoreProvider, truststoreFile, null);
                } else {
                    // Something else went wrong - re-throw
                    throw ioe;
                }
            }
        }
        return trustStore;
    }

    /*
     * Gets the key- or truststore with the specified type, path, and preplacedword.
     */
    private KeyStore getStore(String type, String provider, String path, String preplaced) throws IOException {
        KeyStore ks = null;
        InputStream istream = null;
        try {
            if (provider == null) {
                ks = KeyStore.getInstance(type);
            } else {
                ks = KeyStore.getInstance(type, provider);
            }
            if (!("PKCS11".equalsIgnoreCase(type) || "".equalsIgnoreCase(path))) {
                istream = ConfigFileLoader.getInputStream(path);
            }
            char[] storePreplaced = null;
            if (preplaced != null && !"".equals(preplaced)) {
                storePreplaced = preplaced.toCharArray();
            }
            ks.load(istream, storePreplaced);
        } catch (FileNotFoundException fnfe) {
            log.error(sm.getString("jsse.keystore_load_failed", type, path, fnfe.getMessage()), fnfe);
            throw fnfe;
        } catch (IOException ioe) {
            // May be expected when working with a trust store
            // Re-throw. Caller will catch and log as required
            throw ioe;
        } catch (Exception ex) {
            String msg = sm.getString("jsse.keystore_load_failed", type, path, ex.getMessage());
            log.error(msg, ex);
            throw new IOException(msg);
        } finally {
            if (istream != null) {
                try {
                    istream.close();
                } catch (IOException ioe) {
                // Do nothing
                }
            }
        }
        return ks;
    }

    /**
     * Reads the keystore and initializes the SSL socket factory.
     */
    void init() throws IOException {
        try {
            String clientAuthStr = endpoint.getClientAuth();
            if ("true".equalsIgnoreCase(clientAuthStr) || "yes".equalsIgnoreCase(clientAuthStr)) {
                requireClientAuth = true;
            } else if ("want".equalsIgnoreCase(clientAuthStr)) {
                wantClientAuth = true;
            }
            SSLContext context = createSSLContext();
            context.init(getKeyManagers(), getTrustManagers(), null);
            // Configure SSL session cache
            SSLSessionContext sessionContext = context.getServerSessionContext();
            if (sessionContext != null) {
                configureSessionContext(sessionContext);
            }
            // create proxy
            sslProxy = context.getServerSocketFactory();
            // Determine which cipher suites to enable
            enabledCiphers = getEnableableCiphers(context);
            enabledProtocols = getEnableableProtocols(context);
            allowUnsafeLegacyRenegotiation = "true".equals(endpoint.getAllowUnsafeLegacyRenegotiation());
            // Check the SSL config is OK
            checkConfig();
        } catch (Exception e) {
            if (e instanceof IOException)
                throw (IOException) e;
            throw new IOException(e.getMessage(), e);
        }
    }

    @Override
    public SSLContext createSSLContext() throws Exception {
        // SSL protocol variant (e.g., TLS, SSL v3, etc.)
        String protocol = endpoint.getSslProtocol();
        if (protocol == null) {
            protocol = defaultProtocol;
        }
        SSLContext context = SSLContext.getInstance(protocol);
        return context;
    }

    @Override
    public KeyManager[] getKeyManagers() throws Exception {
        String keystoreType = endpoint.getKeystoreType();
        if (keystoreType == null) {
            keystoreType = defaultKeystoreType;
        }
        String algorithm = endpoint.getAlgorithm();
        if (algorithm == null) {
            algorithm = KeyManagerFactory.getDefaultAlgorithm();
        }
        return getKeyManagers(keystoreType, endpoint.getKeystoreProvider(), algorithm, endpoint.getKeyAlias());
    }

    @Override
    public TrustManager[] getTrustManagers() throws Exception {
        String truststoreType = endpoint.getTruststoreType();
        if (truststoreType == null) {
            truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
        }
        if (truststoreType == null) {
            truststoreType = endpoint.getKeystoreType();
        }
        if (truststoreType == null) {
            truststoreType = defaultKeystoreType;
        }
        String algorithm = endpoint.getTruststoreAlgorithm();
        if (algorithm == null) {
            algorithm = TrustManagerFactory.getDefaultAlgorithm();
        }
        return getTrustManagers(truststoreType, endpoint.getKeystoreProvider(), algorithm);
    }

    @Override
    public void configureSessionContext(SSLSessionContext sslSessionContext) {
        int sessionCacheSize;
        if (endpoint.getSessionCacheSize() != null) {
            sessionCacheSize = Integer.parseInt(endpoint.getSessionCacheSize());
        } else {
            sessionCacheSize = defaultSessionCacheSize;
        }
        int sessionTimeout;
        if (endpoint.getSessionTimeout() != null) {
            sessionTimeout = Integer.parseInt(endpoint.getSessionTimeout());
        } else {
            sessionTimeout = defaultSessionTimeout;
        }
        sslSessionContext.setSessionCacheSize(sessionCacheSize);
        sslSessionContext.setSessionTimeout(sessionTimeout);
    }

    /**
     * Gets the initialized key managers.
     */
    protected KeyManager[] getKeyManagers(String keystoreType, String keystoreProvider, String algorithm, String keyAlias) throws Exception {
        KeyManager[] kms = null;
        String keystorePreplaced = getKeystorePreplacedword();
        KeyStore ks = getKeystore(keystoreType, keystoreProvider, keystorePreplaced);
        if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
            throw new IOException(sm.getString("jsse.alias_no_key_entry", keyAlias));
        }
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
        String keyPreplaced = endpoint.getKeyPreplaced();
        if (keyPreplaced == null) {
            keyPreplaced = keystorePreplaced;
        }
        kmf.init(ks, keyPreplaced.toCharArray());
        kms = kmf.getKeyManagers();
        if (keyAlias != null) {
            String alias = keyAlias;
            if (JSSESocketFactory.defaultKeystoreType.equals(keystoreType)) {
                alias = alias.toLowerCase(Locale.ENGLISH);
            }
            for (int i = 0; i < kms.length; i++) {
                kms[i] = new JSSEKeyManager((X509KeyManager) kms[i], alias);
            }
        }
        return kms;
    }

    /**
     * Gets the initialized trust managers.
     */
    protected TrustManager[] getTrustManagers(String keystoreType, String keystoreProvider, String algorithm) throws Exception {
        String crlf = endpoint.getCrlFile();
        String clreplacedName = endpoint.getTrustManagerClreplacedName();
        if (clreplacedName != null && clreplacedName.length() > 0) {
            ClreplacedLoader clreplacedLoader = getClreplaced().getClreplacedLoader();
            Clreplaced<?> clazz = clreplacedLoader.loadClreplaced(clreplacedName);
            if (!(TrustManager.clreplaced.isreplacedignableFrom(clazz))) {
                throw new InstantiationException(sm.getString("jsse.invalidTrustManagerClreplacedName", clreplacedName));
            }
            Object trustManagerObject = clazz.newInstance();
            TrustManager trustManager = (TrustManager) trustManagerObject;
            return new TrustManager[] { trustManager };
        }
        TrustManager[] tms = null;
        KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider);
        if (trustStore != null || endpoint.getTrustManagerClreplacedName() != null) {
            if (crlf == null) {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
                tmf.init(trustStore);
                tms = tmf.getTrustManagers();
            } else {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
                CertPathParameters params = getParameters(algorithm, crlf, trustStore);
                ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params);
                tmf.init(mfp);
                tms = tmf.getTrustManagers();
            }
        }
        return tms;
    }

    /**
     * Return the initialization parameters for the TrustManager.
     * Currently, only the default <code>PKIX</code> is supported.
     *
     * @param algorithm The algorithm to get parameters for.
     * @param crlf The path to the CRL file.
     * @param trustStore The configured TrustStore.
     * @return The parameters including the CRLs and TrustStore.
     */
    protected CertPathParameters getParameters(String algorithm, String crlf, KeyStore trustStore) throws Exception {
        CertPathParameters params = null;
        if ("PKIX".equalsIgnoreCase(algorithm)) {
            PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore, new X509CertSelector());
            Collection<? extends CRL> crls = getCRLs(crlf);
            CertStoreParameters csp = new CollectionCertStoreParameters(crls);
            CertStore store = CertStore.getInstance("Collection", csp);
            xparams.addCertStore(store);
            xparams.setRevocationEnabled(true);
            String trustLength = endpoint.getTrustMaxCertLength();
            if (trustLength != null) {
                try {
                    xparams.setMaxPathLength(Integer.parseInt(trustLength));
                } catch (Exception ex) {
                    log.warn("Bad maxCertLength: " + trustLength);
                }
            }
            params = xparams;
        } else {
            throw new CRLException("CRLs not supported for type: " + algorithm);
        }
        return params;
    }

    /**
     * Load the collection of CRLs.
     */
    protected Collection<? extends CRL> getCRLs(String crlf) throws IOException, CRLException, CertificateException {
        Collection<? extends CRL> crls = null;
        InputStream is = null;
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            is = ConfigFileLoader.getInputStream(crlf);
            crls = cf.generateCRLs(is);
        } catch (IOException iex) {
            throw iex;
        } catch (CRLException crle) {
            throw crle;
        } catch (CertificateException ce) {
            throw ce;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception ex) {
                // Ignore
                }
            }
        }
        return crls;
    }

    @Override
    public String[] getEnableableProtocols(SSLContext context) {
        String[] requestedProtocols = endpoint.getSslEnabledProtocolsArray();
        if ((requestedProtocols == null) || (requestedProtocols.length == 0)) {
            return defaultServerProtocols;
        }
        List<String> protocols = new ArrayList<String>(Arrays.asList(requestedProtocols));
        protocols.retainAll(Arrays.asList(context.getSupportedSSLParameters().getProtocols()));
        if (protocols.isEmpty()) {
            log.warn(sm.getString("jsse.requested_protocols_not_supported", Arrays.asList(requestedProtocols)));
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("jsse.enableable_protocols", protocols));
            if (protocols.size() != requestedProtocols.length) {
                List<String> skipped = new ArrayList<String>(Arrays.asList(requestedProtocols));
                skipped.removeAll(protocols);
                log.debug(sm.getString("jsse.unsupported_protocols", skipped));
            }
        }
        return protocols.toArray(new String[protocols.size()]);
    }

    /**
     * Configure Client authentication for this version of JSSE.  The
     * JSSE included in Java 1.4 supports the 'want' value.  Prior
     * versions of JSSE will treat 'want' as 'false'.
     * @param socket the SSLServerSocket
     */
    protected void configureClientAuth(SSLServerSocket socket) {
        if (wantClientAuth) {
            socket.setWantClientAuth(wantClientAuth);
        } else {
            socket.setNeedClientAuth(requireClientAuth);
        }
    }

    /**
     * Configures SSLEngine to honor cipher suites ordering based upon
     * endpoint configuration.
     *
     * @throws InvalidAlgorithmParameterException If the runtime JVM doesn't
     *         support this setting.
     */
    protected void configureUseServerCipherSuitesOrder(SSLServerSocket socket) {
        String useServerCipherSuitesOrderStr = endpoint.getUseServerCipherSuitesOrder().trim();
        // Only use this feature if the user explicitly requested its use.
        if (!"".equals(useServerCipherSuitesOrderStr)) {
            boolean useServerCipherSuitesOrder = ("true".equalsIgnoreCase(useServerCipherSuitesOrderStr) || "yes".equalsIgnoreCase(useServerCipherSuitesOrderStr));
            JreCompat jreCompat = JreCompat.getInstance();
            jreCompat.setUseServerCipherSuitesOrder(socket, useServerCipherSuitesOrder);
        }
    }

    /**
     * Configures the given SSL server socket with the requested cipher suites,
     * protocol versions, and need for client authentication
     */
    private void initServerSocket(ServerSocket ssocket) {
        SSLServerSocket socket = (SSLServerSocket) ssocket;
        socket.setEnabledCipherSuites(enabledCiphers);
        socket.setEnabledProtocols(enabledProtocols);
        // we don't know if client auth is needed -
        // after parsing the request we may re-handshake
        configureClientAuth(socket);
        configureUseServerCipherSuitesOrder(socket);
    }

    /**
     * Checks that the certificate is compatible with the enabled cipher suites.
     * If we don't check now, the JIoEndpoint can enter a nasty logging loop.
     * See bug 45528.
     */
    private void checkConfig() throws IOException {
        // Create an unbound server socket
        ServerSocket socket = sslProxy.createServerSocket();
        initServerSocket(socket);
        try {
            // Set the timeout to 1ms as all we care about is if it throws an
            // SSLException on accept.
            socket.setSoTimeout(1);
            socket.accept();
        // Will never get here - no client can connect to an unbound port
        } catch (SSLException ssle) {
            // SSL configuration is invalid. Possibly cert doesn't match ciphers
            IOException ioe = new IOException(sm.getString("jsse.invalid_ssl_conf", ssle.getMessage()));
            ioe.initCause(ssle);
            throw ioe;
        } catch (Exception e) {
        /*
             * Possible ways of getting here
             * socket.accept() throws a SecurityException
             * socket.setSoTimeout() throws a SocketException
             * socket.accept() throws some other exception (after a JDK change)
             *      In these cases the test won't work so carry on - essentially
             *      the behaviour before this patch
             * socket.accept() throws a SocketTimeoutException
             *      In this case all is well so carry on
             */
        } finally {
            // Should be open here but just in case
            if (!socket.isClosed()) {
                socket.close();
            }
        }
    }
}

19 Source : JreCompat.java
with Apache License 2.0
from tryandcatch

/**
 * This is the base implementation clreplaced for JRE compatibility and provides an
 * implementation based on Java 6. Sub-clreplacedes may extend this clreplaced and provide
 * alternative implementations for later JRE versions
 */
public clreplaced JreCompat {

    private static final JreCompat instance;

    private static StringManager sm = StringManager.getManager(JreCompat.clreplaced.getPackage().getName());

    private static final boolean jre7Available;

    private static final boolean jre8Available;

    static {
        // This is Tomcat 7 with a minimum Java version of Java 6. The latest
        // Java version the optional features require is Java 8.
        // Look for the highest supported JVM first
        if (Jre8Compat.isSupported()) {
            instance = new Jre8Compat();
            jre7Available = true;
            jre8Available = true;
        } else if (Jre7Compat.isSupported()) {
            instance = new Jre7Compat();
            jre7Available = true;
            jre8Available = false;
        } else {
            instance = new JreCompat();
            jre7Available = false;
            jre8Available = false;
        }
    }

    public static JreCompat getInstance() {
        return instance;
    }

    // Java 6 implementation of Java 7 methods
    public static boolean isJre7Available() {
        return jre7Available;
    }

    public Locale forLanguageTag(String languageTag) {
        // Extract the language and country for this entry
        String language = null;
        String country = null;
        String variant = null;
        int dash = languageTag.indexOf('-');
        if (dash < 0) {
            language = languageTag;
            country = "";
            variant = "";
        } else {
            language = languageTag.substring(0, dash);
            country = languageTag.substring(dash + 1);
            int vDash = country.indexOf('-');
            if (vDash > 0) {
                String cTemp = country.substring(0, vDash);
                variant = country.substring(vDash + 1);
                country = cTemp;
            } else {
                variant = "";
            }
        }
        if (!isAlpha(language) || !isAlpha(country) || !isAlpha(variant)) {
            return null;
        }
        return new Locale(language, country, variant);
    }

    private static final boolean isAlpha(String value) {
        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);
            if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
                return false;
            }
        }
        return true;
    }

    // Java 6 implementation of Java 8 methods
    public static boolean isJre8Available() {
        return jre8Available;
    }

    @SuppressWarnings("unused")
    public void setUseServerCipherSuitesOrder(SSLServerSocket socket, boolean useCipherSuitesOrder) {
        throw new UnsupportedOperationException(sm.getString("jreCompat.noServerCipherSuiteOrder"));
    }

    @SuppressWarnings("unused")
    public void setUseServerCipherSuitesOrder(SSLEngine engine, boolean useCipherSuitesOrder) {
        throw new UnsupportedOperationException(sm.getString("jreCompat.noServerCipherSuiteOrder"));
    }
}

19 Source : AsyncStateMachine.java
with Apache License 2.0
from tryandcatch

/**
 * Manages the state transitions for async requests.
 *
 * <pre>
 * The internal states that are used are:
 * DISPATCHED    - Standard request. Not in Async mode.
 * STARTING      - ServletRequest.startAsync() has been called but the
 *                 request in which that call was made has not finished
 *                 processing.
 * STARTED       - ServletRequest.startAsync() has been called and the
 *                 request in which that call was made has finished
 *                 processing.
 * MUST_COMPLETE - complete() has been called before the request in which
 *                 ServletRequest.startAsync() has finished. As soon as that
 *                 request finishes, the complete() will be processed.
 * COMPLETING    - The call to complete() was made once the request was in
 *                 the STARTED state. May or may not be triggered by a
 *                 container thread - depends if start(Runnable) was used
 * TIMING_OUT    - The async request has timed out and is waiting for a call
 *                 to complete(). If that isn't made, the error state will
 *                 entered.
 * MUST_DISPATCH - dispatch() has been called from a container thread. The
 *                 dispatch will be processed once processing control returns to
 *                 the container.
 * DISPATCHING   - dispatch() has been called from a non-container thread. The
 *                 dispatch will be processed as soon as a container thread is
 *                 available.
 * ERROR         - Something went wrong.
 *
 * |----------------->--------------|
 * |                               \|/
 * |   |----------<---------------ERROR
 * |   |      complete()         /|\ | \
 * |   |                          |  |  \---------------|
 * |   |                          |  |                  |dispatch()
 * |   |                          |  |postProcess()    \|/
 * |   |                   error()|  |                  |
 * |   |                          |  |  |--|timeout()   |
 * |   |           postProcess()  | \|/ | \|/           |         auto
 * |   |         |--------------->DISPATCHED<---------- | --------------COMPLETING<-----|
 * |   |         |               /|\  |                 |                 | /|\         |
 * |   |         |    |--->-------|   |                 |                 |--|          |
 * |   |         ^    |               |startAsync()     |               timeout()       |
 * |   |         |    |               |                 |                               |
 * |  \|/        |    |  complete()  \|/  postProcess() |                               |
 * | MUST_COMPLETE-<- | ----<------STARTING-->--------- | ------------|                 ^
 * |         /|\      |               |                 |             |      complete() |
 * |          |       |               |                 |             |     /-----------|
 * |          |       ^               |dispatch()       |             |    /
 * |          |       |               |                 |             |   /
 * |          |       |              \|/                |            \|/ /
 * |          |       |----<----MUST_DISPATCH----<------|          STARTED
 * |          |       |   auto              \                      /|
 * |          |       |                      \                    / |
 * ^          ^       ^                       \        dispatch()/  |
 * |          |       |                        \                /   |
 * |          |       |               |-------- \ -------------/    |auto
 * |          |       |               |          \                  |
 * |          |       |               |           \                 |
 * |          |       | auto         \|/           \               \|/
 * |          |       |---<------DISPATCHING        \---------TIMING_OUT
 * |          |                                   dispatch()    |   |
 * |          |                                                 |   |
 * |          |-------<----------------------------------<------|   |
 * |                              complete()                        |
 * |                                                                |
 * |<--------<-------------------<-------------------------------<--|
 *                                 error()
 * </pre>
 */
public clreplaced AsyncStateMachine<S> {

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    private static enum AsyncState {

        DISPATCHED(false, false, false, false, false),
        STARTING(true, true, false, false, true),
        STARTED(true, true, false, false, false),
        MUST_COMPLETE(true, true, true, false, false),
        COMPLETING(true, false, true, false, false),
        TIMING_OUT(true, false, false, false, false),
        MUST_DISPATCH(true, true, false, true, true),
        DISPATCHING(true, false, false, true, false),
        ERROR(true, false, false, false, false);

        private final boolean isAsync;

        private final boolean isStarted;

        private final boolean isCompleting;

        private final boolean isDispatching;

        private final boolean pauseNonContainerThread;

        private AsyncState(boolean isAsync, boolean isStarted, boolean isCompleting, boolean isDispatching, boolean pauseNonContainerThread) {
            this.isAsync = isAsync;
            this.isStarted = isStarted;
            this.isCompleting = isCompleting;
            this.isDispatching = isDispatching;
            this.pauseNonContainerThread = pauseNonContainerThread;
        }

        public boolean isAsync() {
            return isAsync;
        }

        public boolean isStarted() {
            return isStarted;
        }

        public boolean isDispatching() {
            return isDispatching;
        }

        public boolean isCompleting() {
            return isCompleting;
        }

        public boolean getPauseNonContainerThread() {
            return pauseNonContainerThread;
        }
    }

    private volatile AsyncState state = AsyncState.DISPATCHED;

    // Need this to fire listener on complete
    private AsyncContextCallback asyncCtxt = null;

    private Processor<S> processor;

    public AsyncStateMachine(Processor<S> processor) {
        this.processor = processor;
    }

    public boolean isAsync() {
        return state.isAsync();
    }

    public boolean isAsyncDispatching() {
        return state.isDispatching();
    }

    public boolean isAsyncStarted() {
        return state.isStarted();
    }

    public boolean isAsyncTimingOut() {
        return state == AsyncState.TIMING_OUT;
    }

    public boolean isAsyncError() {
        return state == AsyncState.ERROR;
    }

    public boolean isCompleting() {
        return state.isCompleting();
    }

    public synchronized void asyncStart(AsyncContextCallback asyncCtxt) {
        if (state == AsyncState.DISPATCHED) {
            state = AsyncState.STARTING;
            this.asyncCtxt = asyncCtxt;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncStart()", state));
        }
    }

    /*
     * Async has been processed. Whether or not to enter a long poll depends on
     * current state. For example, as per SRV.2.3.3.3 can now process calls to
     * complete() or dispatch().
     */
    public synchronized SocketState asyncPostProcess() {
        // Unpause any non-container threads that may be waiting for this
        // container thread to complete this method. Note because of the syncs
        // those non-container threads won't start back up until until this
        // method exits.
        notifyAll();
        if (state == AsyncState.STARTING) {
            state = AsyncState.STARTED;
            return SocketState.LONG;
        } else if (state == AsyncState.MUST_COMPLETE) {
            asyncCtxt.fireOnComplete();
            state = AsyncState.DISPATCHED;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.COMPLETING) {
            asyncCtxt.fireOnComplete();
            state = AsyncState.DISPATCHED;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.MUST_DISPATCH) {
            state = AsyncState.DISPATCHING;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.DISPATCHING) {
            state = AsyncState.DISPATCHED;
            return SocketState.ASYNC_END;
        } else if (state == AsyncState.STARTED) {
            // This can occur if an async listener does a dispatch to an async
            // servlet during onTimeout
            return SocketState.LONG;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncPostProcess()", state));
        }
    }

    public synchronized boolean asyncComplete() {
        pauseNonContainerThread();
        boolean doComplete = false;
        if (state == AsyncState.STARTING) {
            state = AsyncState.MUST_COMPLETE;
        } else if (state == AsyncState.STARTED) {
            state = AsyncState.COMPLETING;
            doComplete = true;
        } else if (state == AsyncState.TIMING_OUT || state == AsyncState.ERROR) {
            state = AsyncState.MUST_COMPLETE;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncComplete()", state));
        }
        return doComplete;
    }

    public synchronized boolean asyncTimeout() {
        if (state == AsyncState.STARTED) {
            state = AsyncState.TIMING_OUT;
            return true;
        } else if (state == AsyncState.COMPLETING || state == AsyncState.DISPATCHING || state == AsyncState.DISPATCHED) {
            // NOOP - App called complete() or dispatch() between the the
            // timeout firing and execution reaching this point
            return false;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncTimeout()", state));
        }
    }

    public synchronized boolean asyncDispatch() {
        pauseNonContainerThread();
        boolean doDispatch = false;
        if (state == AsyncState.STARTING || state == AsyncState.TIMING_OUT || state == AsyncState.ERROR) {
            // In these three cases processing is on a container thread so no
            // need to transfer processing to a new container thread
            state = AsyncState.MUST_DISPATCH;
        } else if (state == AsyncState.STARTED) {
            // A dispatch is always required.
            // If on a non-container thread, need to get back onto a container
            // thread to complete the processing.
            // If on a container thread the current request/response are not the
            // request/response replacedociated with the AsyncContext so need a new
            // container thread to process the different request/response.
            state = AsyncState.DISPATCHING;
            doDispatch = true;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncDispatch()", state));
        }
        return doDispatch;
    }

    public synchronized void asyncDispatched() {
        if (state == AsyncState.DISPATCHING || state == AsyncState.MUST_DISPATCH) {
            state = AsyncState.DISPATCHED;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncDispatched()", state));
        }
    }

    public synchronized boolean asyncError() {
        boolean doDispatch = false;
        if (state == AsyncState.DISPATCHED || state == AsyncState.TIMING_OUT) {
            state = AsyncState.ERROR;
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncError()", state));
        }
        return doDispatch;
    }

    public synchronized void asyncRun(Runnable runnable) {
        if (state == AsyncState.STARTING || state == AsyncState.STARTED) {
            // Execute the runnable using a container thread from the
            // Connector's thread pool. Use a wrapper to prevent a memory leak
            ClreplacedLoader oldCL;
            if (Constants.IS_SECURITY_ENABLED) {
                PrivilegedAction<ClreplacedLoader> pa = new PrivilegedGetTccl();
                oldCL = AccessController.doPrivileged(pa);
            } else {
                oldCL = Thread.currentThread().getContextClreplacedLoader();
            }
            try {
                if (Constants.IS_SECURITY_ENABLED) {
                    PrivilegedAction<Void> pa = new PrivilegedSetTccl(this.getClreplaced().getClreplacedLoader());
                    AccessController.doPrivileged(pa);
                } else {
                    Thread.currentThread().setContextClreplacedLoader(this.getClreplaced().getClreplacedLoader());
                }
                processor.getExecutor().execute(runnable);
            } finally {
                if (Constants.IS_SECURITY_ENABLED) {
                    PrivilegedAction<Void> pa = new PrivilegedSetTccl(oldCL);
                    AccessController.doPrivileged(pa);
                } else {
                    Thread.currentThread().setContextClreplacedLoader(oldCL);
                }
            }
        } else {
            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState", "asyncRun()", state));
        }
    }

    public synchronized void recycle() {
        // Ensure in case of error that any non-container threads that have been
        // paused are unpaused.
        notifyAll();
        asyncCtxt = null;
        state = AsyncState.DISPATCHED;
    }

    /*
     * startAsync() has been called but the container thread where this was
     * called has not completed processing. To avoid various race conditions -
     * including several related to error page handling - pause this
     * non-container thread until the container thread has finished processing.
     * The non-container thread will be paused until the container thread
     * completes asyncPostProcess().
     */
    private synchronized void pauseNonContainerThread() {
        while (!ContainerThreadMarker.isContainerThread() && state.getPauseNonContainerThread()) {
            try {
                wait();
            } catch (InterruptedException e) {
            // TODO Log this?
            }
        }
    }
}

19 Source : AbstractAjpProtocol.java
with Apache License 2.0
from tryandcatch

public abstract clreplaced AbstractAjpProtocol<S> extends AbstractProtocol<S> {

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    @Override
    protected String getProtocolName() {
        return "Ajp";
    }

    // ------------------------------------------------- AJP specific properties
    // ------------------------------------------ managed in the ProtocolHandler
    /**
     * Should authentication be done in the native web server layer,
     * or in the Servlet container ?
     */
    protected boolean tomcatAuthentication = true;

    public boolean getTomcatAuthentication() {
        return tomcatAuthentication;
    }

    public void setTomcatAuthentication(boolean tomcatAuthentication) {
        this.tomcatAuthentication = tomcatAuthentication;
    }

    /**
     * Should authentication be done in the native web server layer and
     * authorization in the Servlet container?
     */
    private boolean tomcatAuthorization = false;

    public boolean getTomcatAuthorization() {
        return tomcatAuthorization;
    }

    public void setTomcatAuthorization(boolean tomcatAuthorization) {
        this.tomcatAuthorization = tomcatAuthorization;
    }

    /**
     * Required secret.
     */
    protected String requiredSecret = null;

    public void setRequiredSecret(String requiredSecret) {
        this.requiredSecret = requiredSecret;
    }

    /**
     * AJP packet size.
     */
    protected int packetSize = Constants.MAX_PACKET_SIZE;

    public int getPacketSize() {
        return packetSize;
    }

    public void setPacketSize(int packetSize) {
        if (packetSize < Constants.MAX_PACKET_SIZE) {
            this.packetSize = Constants.MAX_PACKET_SIZE;
        } else {
            this.packetSize = packetSize;
        }
    }

    protected abstract static clreplaced AbstractAjpConnectionHandler<S, P extends AbstractAjpProcessor<S>> extends AbstractConnectionHandler<S, P> {

        @Override
        protected void initSsl(SocketWrapper<S> socket, Processor<S> processor) {
        // NOOP for AJP
        }

        @Override
        protected void longPoll(SocketWrapper<S> socket, Processor<S> processor) {
            // Same requirements for all AJP connectors
            socket.setAsync(true);
        }

        /**
         * @deprecated  Will be removed in Tomcat 8.0.x.
         */
        @Deprecated
        @Override
        protected P createUpgradeProcessor(SocketWrapper<S> socket, org.apache.coyote.http11.upgrade.UpgradeInbound inbound) {
            // TODO should fail - throw IOE
            return null;
        }

        @Override
        protected P createUpgradeProcessor(SocketWrapper<S> socket, HttpUpgradeHandler httpUpgradeHandler) {
            // TODO should fail - throw IOE
            return null;
        }
    }
}

19 Source : AbstractProcessor.java
with Apache License 2.0
from tryandcatch

/**
 * Provides functionality and attributes common to all supported protocols
 * (currently HTTP and AJP).
 */
public abstract clreplaced AbstractProcessor<S> implements ActionHook, Processor<S> {

    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    protected Adapter adapter;

    protected AsyncStateMachine<S> asyncStateMachine;

    protected AbstractEndpoint<S> endpoint;

    protected Request request;

    protected Response response;

    protected SocketWrapper<S> socketWrapper = null;

    /**
     * Error state for the request/response currently being processed.
     */
    private ErrorState errorState = ErrorState.NONE;

    /**
     * Intended for use by the Upgrade sub-clreplacedes that have no need to
     * initialise the request, response, etc.
     */
    protected AbstractProcessor() {
    // NOOP
    }

    public AbstractProcessor(AbstractEndpoint<S> endpoint) {
        this.endpoint = endpoint;
        asyncStateMachine = new AsyncStateMachine<S>(this);
        request = new Request();
        response = new Response();
        response.setHook(this);
        request.setResponse(response);
    }

    /**
     * Update the current error state to the new error state if the new error
     * state is more severe than the current error state.
     */
    protected void setErrorState(ErrorState errorState, Throwable t) {
        boolean blockIo = this.errorState.isIoAllowed() && !errorState.isIoAllowed();
        this.errorState = this.errorState.getMostSevere(errorState);
        if (blockIo && !ContainerThreadMarker.isContainerThread() && isAsync()) {
            // The error occurred on a non-container thread during async
            // processing which means not all of the necessary clean-up will
            // have been completed. Dispatch to a container thread to do the
            // clean-up. Need to do it this way to ensure that all the necessary
            // clean-up is performed.
            if (response.getStatus() < 400) {
                response.setStatus(500);
            }
            getLog().info(sm.getString("abstractProcessor.nonContainerThreadError"), t);
            getEndpoint().processSocketAsync(socketWrapper, SocketStatus.CLOSE_NOW);
        }
    }

    protected void resetErrorState() {
        errorState = ErrorState.NONE;
    }

    protected ErrorState getErrorState() {
        return errorState;
    }

    /**
     * The endpoint receiving connections that are handled by this processor.
     */
    protected AbstractEndpoint<S> getEndpoint() {
        return endpoint;
    }

    /**
     * The request replacedociated with this processor.
     */
    @Override
    public Request getRequest() {
        return request;
    }

    /**
     * Set the replacedociated adapter.
     *
     * @param adapter the new adapter
     */
    public void setAdapter(Adapter adapter) {
        this.adapter = adapter;
    }

    /**
     * Get the replacedociated adapter.
     *
     * @return the replacedociated adapter
     */
    public Adapter getAdapter() {
        return adapter;
    }

    /**
     * Set the socket wrapper being used.
     */
    protected final void setSocketWrapper(SocketWrapper<S> socketWrapper) {
        this.socketWrapper = socketWrapper;
    }

    /**
     * Get the socket wrapper being used.
     */
    protected final SocketWrapper<S> getSocketWrapper() {
        return socketWrapper;
    }

    /**
     * Obtain the Executor used by the underlying endpoint.
     */
    @Override
    public Executor getExecutor() {
        return endpoint.getExecutor();
    }

    @Override
    public boolean isAsync() {
        return (asyncStateMachine != null && asyncStateMachine.isAsync());
    }

    @Override
    public SocketState asyncPostProcess() {
        return asyncStateMachine.asyncPostProcess();
    }

    @Override
    public void errorDispatch() {
        getAdapter().errorDispatch(request, response);
    }

    @Override
    public abstract boolean isComet();

    @Override
    public abstract boolean isUpgrade();

    /**
     * Process HTTP requests. All requests are treated as HTTP requests to start
     * with although they may change type during processing.
     */
    @Override
    public abstract SocketState process(SocketWrapper<S> socket) throws IOException;

    /**
     * Process in-progress Comet requests. These will start as HTTP requests.
     */
    @Override
    public abstract SocketState event(SocketStatus status) throws IOException;

    /**
     * Process in-progress Servlet 3.0 Async requests. These will start as HTTP
     * requests.
     */
    @Override
    public abstract SocketState asyncDispatch(SocketStatus status);

    /**
     * Processes data received on a connection that has been through an HTTP
     * upgrade.
     */
    @Override
    public abstract SocketState upgradeDispatch() throws IOException;

    /**
     * @deprecated  Will be removed in Tomcat 8.0.x.
     */
    @Deprecated
    @Override
    public abstract org.apache.coyote.http11.upgrade.UpgradeInbound getUpgradeInbound();

    protected abstract Log getLog();
}

19 Source : JmxRemoteLifecycleListener.java
with Apache License 2.0
from tryandcatch

/**
 * This listener fixes the port used by JMX/RMI Server making things much
 * simpler if you need to connect jconsole or similar to a remote Tomcat
 * instance that is running behind a firewall. Only the ports are configured via
 * the listener. The remainder of the configuration is via the standard system
 * properties for configuring JMX.
 */
public clreplaced JmxRemoteLifecycleListener implements LifecycleListener {

    private static final Log log = LogFactory.getLog(JmxRemoteLifecycleListener.clreplaced);

    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    protected String rmiBindAddress = null;

    protected int rmiRegistryPortPlatform = -1;

    protected int rmiServerPortPlatform = -1;

    protected boolean rmiRegistrySSL = true;

    protected boolean rmiServerSSL = true;

    protected String[] ciphers = null;

    protected String[] protocols = null;

    protected boolean clientAuth = true;

    protected boolean authenticate = true;

    protected String preplacedwordFile = null;

    protected String loginModuleName = null;

    protected String accessFile = null;

    protected boolean useLocalPorts = false;

    protected JMXConnectorServer csPlatform = null;

    /**
     * Get the inet address on which the Platform RMI server is exported.
     * @return The textual representation of inet address
     */
    public String getRmiBindAddress() {
        return rmiBindAddress;
    }

    /**
     * Set the inet address on which the Platform RMI server is exported.
     * @param theRmiBindAddress The textual representation of inet address
     */
    public void setRmiBindAddress(String theRmiBindAddress) {
        rmiBindAddress = theRmiBindAddress;
    }

    /**
     * Get the port on which the Platform RMI server is exported. This is the
     * port that is normally chosen by the RMI stack.
     * @return The port number
     */
    public int getRmiServerPortPlatform() {
        return rmiServerPortPlatform;
    }

    /**
     * Set the port on which the Platform RMI server is exported. This is the
     * port that is normally chosen by the RMI stack.
     * @param theRmiServerPortPlatform The port number
     */
    public void setRmiServerPortPlatform(int theRmiServerPortPlatform) {
        rmiServerPortPlatform = theRmiServerPortPlatform;
    }

    /**
     * Get the port on which the Platform RMI registry is exported.
     * @return The port number
     */
    public int getRmiRegistryPortPlatform() {
        return rmiRegistryPortPlatform;
    }

    /**
     * Set the port on which the Platform RMI registry is exported.
     * @param theRmiRegistryPortPlatform The port number
     */
    public void setRmiRegistryPortPlatform(int theRmiRegistryPortPlatform) {
        rmiRegistryPortPlatform = theRmiRegistryPortPlatform;
    }

    /**
     * Get the flag that indicates that local ports should be used for all
     * connections. If using SSH tunnels, or similar, this should be set to
     * true to ensure the RMI client uses the tunnel.
     * @return <code>true</code> if local ports should be used
     */
    public boolean getUseLocalPorts() {
        return useLocalPorts;
    }

    /**
     * Set the flag that indicates that local ports should be used for all
     * connections. If using SSH tunnels, or similar, this should be set to
     * true to ensure the RMI client uses the tunnel.
     * @param useLocalPorts Set to <code>true</code> if local ports should be
     *                      used
     */
    public void setUseLocalPorts(boolean useLocalPorts) {
        this.useLocalPorts = useLocalPorts;
    }

    private void init() {
        // Get all the other parameters required from the standard system
        // properties. Only need to get the parameters that affect the creation
        // of the server port.
        String rmiRegistrySSLValue = System.getProperty("com.sun.management.jmxremote.registry.ssl", "false");
        rmiRegistrySSL = Boolean.parseBoolean(rmiRegistrySSLValue);
        String rmiServerSSLValue = System.getProperty("com.sun.management.jmxremote.ssl", "true");
        rmiServerSSL = Boolean.parseBoolean(rmiServerSSLValue);
        String protocolsValue = System.getProperty("com.sun.management.jmxremote.ssl.enabled.protocols");
        if (protocolsValue != null) {
            protocols = protocolsValue.split(",");
        }
        String ciphersValue = System.getProperty("com.sun.management.jmxremote.ssl.enabled.cipher.suites");
        if (ciphersValue != null) {
            ciphers = ciphersValue.split(",");
        }
        String clientAuthValue = System.getProperty("com.sun.management.jmxremote.ssl.need.client.auth", "true");
        clientAuth = Boolean.parseBoolean(clientAuthValue);
        String authenticateValue = System.getProperty("com.sun.management.jmxremote.authenticate", "true");
        authenticate = Boolean.parseBoolean(authenticateValue);
        preplacedwordFile = System.getProperty("com.sun.management.jmxremote.preplacedword.file", "jmxremote.preplacedword");
        accessFile = System.getProperty("com.sun.management.jmxremote.access.file", "jmxremote.access");
        loginModuleName = System.getProperty("com.sun.management.jmxremote.login.config");
    }

    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        // When the server starts, configure JMX/RMI
        if (Lifecycle.START_EVENT == event.getType()) {
            // Configure using standard jmx system properties
            init();
            // Prevent an attacker guessing the RMI object ID
            System.setProperty("java.rmi.server.randomIDs", "true");
            // Create the environment
            HashMap<String, Object> env = new HashMap<String, Object>();
            RMIClientSocketFactory registryCsf = null;
            RMIServerSocketFactory registrySsf = null;
            RMIClientSocketFactory serverCsf = null;
            RMIServerSocketFactory serverSsf = null;
            // Configure registry socket factories
            if (rmiRegistrySSL) {
                registryCsf = new SslRMIClientSocketFactory();
                if (rmiBindAddress == null) {
                    registrySsf = new SslRMIServerSocketFactory(ciphers, protocols, clientAuth);
                } else {
                    registrySsf = new SslRmiServerBindSocketFactory(ciphers, protocols, clientAuth, rmiBindAddress);
                }
            } else {
                if (rmiBindAddress != null) {
                    registrySsf = new RmiServerBindSocketFactory(rmiBindAddress);
                }
            }
            // Configure server socket factories
            if (rmiServerSSL) {
                serverCsf = new SslRMIClientSocketFactory();
                if (rmiBindAddress == null) {
                    serverSsf = new SslRMIServerSocketFactory(ciphers, protocols, clientAuth);
                } else {
                    serverSsf = new SslRmiServerBindSocketFactory(ciphers, protocols, clientAuth, rmiBindAddress);
                }
            } else {
                if (rmiBindAddress != null) {
                    serverSsf = new RmiServerBindSocketFactory(rmiBindAddress);
                }
            }
            // By default, the registry will pick an address to listen on.
            // Setting this property overrides that and ensures it listens on
            // the configured address.
            if (rmiBindAddress != null) {
                System.setProperty("java.rmi.server.hostname", rmiBindAddress);
            }
            // Force the use of local ports if required
            if (useLocalPorts) {
                registryCsf = new RmiClientLocalhostSocketFactory(registryCsf);
                serverCsf = new RmiClientLocalhostSocketFactory(serverCsf);
            }
            // Populate the env properties used to create the server
            if (serverCsf != null) {
                env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, serverCsf);
                env.put("com.sun.jndi.rmi.factory.socket", registryCsf);
            }
            if (serverSsf != null) {
                env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverSsf);
            }
            // Configure authentication
            if (authenticate) {
                env.put("jmx.remote.x.preplacedword.file", preplacedwordFile);
                env.put("jmx.remote.x.access.file", accessFile);
                env.put("jmx.remote.x.login.config", loginModuleName);
            }
            // Create the Platform server
            csPlatform = createServer("Platform", rmiBindAddress, rmiRegistryPortPlatform, rmiServerPortPlatform, env, registryCsf, registrySsf, serverCsf, serverSsf);
        } else if (Lifecycle.STOP_EVENT == event.getType()) {
            destroyServer("Platform", csPlatform);
        }
    }

    private JMXConnectorServer createServer(String serverName, String bindAddress, int theRmiRegistryPort, int theRmiServerPort, HashMap<String, Object> theEnv, RMIClientSocketFactory registryCsf, RMIServerSocketFactory registrySsf, RMIClientSocketFactory serverCsf, RMIServerSocketFactory serverSsf) {
        // Create the RMI registry
        Registry registry;
        try {
            registry = LocateRegistry.createRegistry(theRmiRegistryPort, registryCsf, registrySsf);
        } catch (RemoteException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.createRegistryFailed", serverName, Integer.toString(theRmiRegistryPort)), e);
            return null;
        }
        if (bindAddress == null) {
            bindAddress = "localhost";
        }
        String url = "service:jmx:rmi://" + bindAddress;
        JMXServiceURL serviceUrl;
        try {
            serviceUrl = new JMXServiceURL(url.toString());
        } catch (MalformedURLException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.invalidURL", serverName, url), e);
            return null;
        }
        RMIConnectorServer cs = null;
        try {
            RMIJRMPServerImpl server = new RMIJRMPServerImpl(rmiServerPortPlatform, serverCsf, serverSsf, theEnv);
            cs = new RMIConnectorServer(serviceUrl, theEnv, server, ManagementFactory.getPlatformMBeanServer());
            cs.start();
            registry.bind("jmxrmi", server);
            log.info(sm.getString("jmxRemoteLifecycleListener.start", Integer.toString(theRmiRegistryPort), Integer.toString(theRmiServerPort), serverName));
        } catch (IOException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.createServerFailed", serverName), e);
        } catch (AlreadyBoundException e) {
            log.error(sm.getString("jmxRemoteLifecycleListener.createServerFailed", serverName), e);
        }
        return cs;
    }

    private void destroyServer(String serverName, JMXConnectorServer theConnectorServer) {
        if (theConnectorServer != null) {
            try {
                theConnectorServer.stop();
            } catch (IOException e) {
                log.error(sm.getString("jmxRemoteLifecycleListener.destroyServerFailed", serverName), e);
            }
        }
    }

    public static clreplaced RmiClientLocalhostSocketFactory implements RMIClientSocketFactory, Serializable {

        private static final long serialVersionUID = 1L;

        private static final String FORCED_HOST = "localhost";

        private RMIClientSocketFactory factory = null;

        public RmiClientLocalhostSocketFactory(RMIClientSocketFactory theFactory) {
            factory = theFactory;
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException {
            if (factory == null) {
                return new Socket(FORCED_HOST, port);
            } else {
                return factory.createSocket(FORCED_HOST, port);
            }
        }
    }

    public static clreplaced RmiServerBindSocketFactory implements RMIServerSocketFactory {

        private final InetAddress bindAddress;

        public RmiServerBindSocketFactory(String address) {
            InetAddress bindAddress = null;
            try {
                bindAddress = InetAddress.getByName(address);
            } catch (UnknownHostException e) {
                log.error(sm.getString("jmxRemoteLifecycleListener.invalidRmiBindAddress", address), e);
            // bind address will be null which means any/all local addresses
            // which should be safe
            }
            this.bindAddress = bindAddress;
        }

        @Override
        public ServerSocket createServerSocket(int port) throws IOException {
            return new ServerSocket(port, 0, bindAddress);
        }
    }

    public static clreplaced SslRmiServerBindSocketFactory extends SslRMIServerSocketFactory {

        private static final SSLServerSocketFactory sslServerSocketFactory;

        private static final String[] defaultProtocols;

        static {
            SSLContext sslContext;
            try {
                sslContext = SSLContext.getDefault();
            } catch (NoSuchAlgorithmException e) {
                // Can't continue. Force a failure.
                throw new IllegalStateException(e);
            }
            sslServerSocketFactory = sslContext.getServerSocketFactory();
            String[] protocols = sslContext.getDefaultSSLParameters().getProtocols();
            List<String> filteredProtocols = new ArrayList<String>(protocols.length);
            for (String protocol : protocols) {
                if (protocol.toUpperCase(Locale.ENGLISH).contains("SSL")) {
                    continue;
                }
                filteredProtocols.add(protocol);
            }
            defaultProtocols = filteredProtocols.toArray(new String[filteredProtocols.size()]);
        }

        private final InetAddress bindAddress;

        public SslRmiServerBindSocketFactory(String[] enabledCipherSuites, String[] enabledProtocols, boolean needClientAuth, String address) {
            super(enabledCipherSuites, enabledProtocols, needClientAuth);
            InetAddress bindAddress = null;
            try {
                bindAddress = InetAddress.getByName(address);
            } catch (UnknownHostException e) {
                log.error(sm.getString("jmxRemoteLifecycleListener.invalidRmiBindAddress", address), e);
            // bind address will be null which means any/all local addresses
            // which should be safe
            }
            this.bindAddress = bindAddress;
        }

        @Override
        public ServerSocket createServerSocket(int port) throws IOException {
            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port, 0, bindAddress);
            if (getEnabledCipherSuites() != null) {
                sslServerSocket.setEnabledCipherSuites(getEnabledCipherSuites());
            }
            if (getEnabledProtocols() == null) {
                sslServerSocket.setEnabledProtocols(defaultProtocols);
            } else {
                sslServerSocket.setEnabledProtocols(getEnabledProtocols());
            }
            sslServerSocket.setNeedClientAuth(getNeedClientAuth());
            return sslServerSocket;
        }
    }
}

19 Source : StandardWrapperValve.java
with Apache License 2.0
from tryandcatch

/**
 * Valve that implements the default basic behavior for the
 * <code>StandardWrapper</code> container implementation.
 *
 * @author Craig R. McClanahan
 */
final clreplaced StandardWrapperValve extends ValveBase {

    // ------------------------------------------------------ Constructor
    public StandardWrapperValve() {
        super(true);
    }

    // ----------------------------------------------------- Instance Variables
    // Some JMX statistics. This valve is replacedociated with a StandardWrapper.
    // We expose the StandardWrapper as JMX ( j2eeType=Servlet ). The fields
    // are here for performance.
    private volatile long processingTime;

    private volatile long maxTime;

    private volatile long minTime = Long.MAX_VALUE;

    private volatile int requestCount;

    private volatile int errorCount;

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    // --------------------------------------------------------- Public Methods
    /**
     * Invoke the servlet we are managing, respecting the rules regarding
     * servlet lifecycle and SingleThreadModel support.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void invoke(Request request, Response response) throws IOException, ServletException {
        // Initialize local variables we may need
        boolean unavailable = false;
        Throwable throwable = null;
        // This should be a Request attribute...
        long t1 = System.currentTimeMillis();
        requestCount++;
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        Servlet servlet = null;
        Context context = (Context) wrapper.getParent();
        // Check for the application being marked unavailable
        if (!context.getState().isAvailable()) {
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardContext.isUnavailable"));
            unavailable = true;
        }
        // Check for the servlet being marked unavailable
        if (!unavailable && wrapper.isUnavailable()) {
            container.getLogger().info(sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE)) {
                response.setDateHeader("Retry-After", available);
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            } else if (available == Long.MAX_VALUE) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
            }
            unavailable = true;
        }
        // Allocate a servlet instance to process this request
        try {
            if (!unavailable) {
                servlet = wrapper.allocate();
            }
        } catch (UnavailableException e) {
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE)) {
                response.setDateHeader("Retry-After", available);
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            } else if (available == Long.MAX_VALUE) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
            }
        } catch (ServletException e) {
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e));
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
            servlet = null;
        }
        // Identify if the request is Comet related now that the servlet has been allocated
        boolean comet = false;
        if (servlet instanceof CometProcessor && Boolean.TRUE.equals(request.getAttribute(Globals.COMET_SUPPORTED_ATTR))) {
            comet = true;
            request.setComet(true);
        }
        MessageBytes requestPathMB = request.getRequestPathMB();
        DispatcherType dispatcherType = DispatcherType.REQUEST;
        if (request.getDispatcherType() == DispatcherType.ASYNC)
            dispatcherType = DispatcherType.ASYNC;
        request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, dispatcherType);
        request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
        // Create the filter chain for this request
        ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
        ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);
        // Reset comet flag value after creating the filter chain
        request.setComet(false);
        // Call the filter chain for this request
        // NOTE: This also calls the servlet's service() method
        try {
            if ((servlet != null) && (filterChain != null)) {
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        if (request.isAsyncDispatching()) {
                            // TODO SERVLET3 - async
                            ((AsyncContextImpl) request.getAsyncContext()).doInternalDispatch();
                        } else if (comet) {
                            filterChain.doFilterEvent(request.getEvent());
                            request.setComet(true);
                        } else {
                            filterChain.doFilter(request.getRequest(), response.getResponse());
                        }
                    } finally {
                        String log = SystemLogHandler.stopCapture();
                        if (log != null && log.length() > 0) {
                            context.getLogger().info(log);
                        }
                    }
                } else {
                    if (request.isAsyncDispatching()) {
                        // TODO SERVLET3 - async
                        ((AsyncContextImpl) request.getAsyncContext()).doInternalDispatch();
                    } else if (comet) {
                        request.setComet(true);
                        filterChain.doFilterEvent(request.getEvent());
                    } else {
                        filterChain.doFilter(request.getRequest(), response.getResponse());
                    }
                }
            }
        } catch (ClientAbortException e) {
            throwable = e;
            exception(request, response, e);
        } catch (IOException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        } catch (UnavailableException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            // throwable = e;
            // exception(request, response, e);
            wrapper.unavailable(e);
            long available = wrapper.getAvailable();
            if ((available > 0L) && (available < Long.MAX_VALUE)) {
                response.setDateHeader("Retry-After", available);
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
            } else if (available == Long.MAX_VALUE) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
            }
        // Do not save exception in 'throwable', because we
        // do not want to do exception(request, response, e) processing
        } catch (ServletException e) {
            Throwable rootCause = StandardWrapper.getRootCause(e);
            if (!(rootCause instanceof ClientAbortException)) {
                container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(), context.getName(), e.getMessage()), rootCause);
            }
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        }
        // Release the filter chain (if any) for this request
        if (filterChain != null) {
            if (request.isComet()) {
                // If this is a Comet request, then the same chain will be used for the
                // processing of all subsequent events.
                filterChain.reuse();
            } else {
                filterChain.release();
            }
        }
        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                wrapper.deallocate(servlet);
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        // If this servlet has been marked permanently unavailable,
        // unload it and release this instance
        try {
            if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {
                wrapper.unload();
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        long t2 = System.currentTimeMillis();
        long time = t2 - t1;
        processingTime += time;
        if (time > maxTime)
            maxTime = time;
        if (time < minTime)
            minTime = time;
    }

    /**
     * Process a Comet event. The main differences here are to not use sendError
     * (the response is committed), to avoid creating a new filter chain
     * (which would work but be pointless), and a few very minor tweaks.
     *
     * @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
     */
    @Override
    public void event(Request request, Response response, CometEvent event) throws IOException, ServletException {
        // Initialize local variables we may need
        Throwable throwable = null;
        // This should be a Request attribute...
        long t1 = System.currentTimeMillis();
        // FIXME: Add a flag to count the total amount of events processed ? requestCount++;
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        if (wrapper == null) {
            // Context has been shutdown. Nothing to do here.
            return;
        }
        Servlet servlet = null;
        Context context = (Context) wrapper.getParent();
        // Check for the application being marked unavailable
        boolean unavailable = !context.getState().isAvailable() || wrapper.isUnavailable();
        // Allocate a servlet instance to process this request
        try {
            if (!unavailable) {
                servlet = wrapper.allocate();
            }
        } catch (UnavailableException e) {
        // The response is already committed, so it's not possible to do anything
        } catch (ServletException e) {
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e));
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
            throwable = e;
            exception(request, response, e);
            servlet = null;
        }
        MessageBytes requestPathMB = request.getRequestPathMB();
        request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.REQUEST);
        request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
        // Get the current (unchanged) filter chain for this request
        ApplicationFilterChain filterChain = (ApplicationFilterChain) request.getFilterChain();
        // Call the filter chain for this request
        // NOTE: This also calls the servlet's event() method
        try {
            if ((servlet != null) && (filterChain != null)) {
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        filterChain.doFilterEvent(request.getEvent());
                    } finally {
                        String log = SystemLogHandler.stopCapture();
                        if (log != null && log.length() > 0) {
                            context.getLogger().info(log);
                        }
                    }
                } else {
                    filterChain.doFilterEvent(request.getEvent());
                }
            }
        } catch (ClientAbortException e) {
            throwable = e;
            exception(request, response, e);
        } catch (IOException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        } catch (UnavailableException e) {
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        // Do not save exception in 'throwable', because we
        // do not want to do exception(request, response, e) processing
        } catch (ServletException e) {
            Throwable rootCause = StandardWrapper.getRootCause(e);
            if (!(rootCause instanceof ClientAbortException)) {
                container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(), context.getName(), e.getMessage()), rootCause);
            }
            throwable = e;
            exception(request, response, e);
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
            throwable = e;
            exception(request, response, e);
        }
        // Release the filter chain (if any) for this request
        if (filterChain != null) {
            filterChain.reuse();
        }
        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                wrapper.deallocate(servlet);
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        // If this servlet has been marked permanently unavailable,
        // unload it and release this instance
        try {
            if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {
                wrapper.unload();
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        long t2 = System.currentTimeMillis();
        long time = t2 - t1;
        processingTime += time;
        if (time > maxTime)
            maxTime = time;
        if (time < minTime)
            minTime = time;
    }

    // -------------------------------------------------------- Private Methods
    /**
     * Handle the specified ServletException encountered while processing
     * the specified Request to produce the specified Response.  Any
     * exceptions that occur during generation of the exception report are
     * logged and swallowed.
     *
     * @param request The request being processed
     * @param response The response being generated
     * @param exception The exception that occurred (which possibly wraps
     *  a root cause exception
     */
    private void exception(Request request, Response response, Throwable exception) {
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, exception);
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        response.setError();
    }

    public long getProcessingTime() {
        return processingTime;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setProcessingTime(long processingTime) {
        this.processingTime = processingTime;
    }

    public long getMaxTime() {
        return maxTime;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setMaxTime(long maxTime) {
        this.maxTime = maxTime;
    }

    public long getMinTime() {
        return minTime;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setMinTime(long minTime) {
        this.minTime = minTime;
    }

    public int getRequestCount() {
        return requestCount;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setRequestCount(int requestCount) {
        this.requestCount = requestCount;
    }

    public int getErrorCount() {
        return errorCount;
    }

    public void incrementErrorCount() {
        errorCount++;
    }

    /**
     * Deprecated   unused
     */
    @Deprecated
    public void setErrorCount(int errorCount) {
        this.errorCount = errorCount;
    }

    @Override
    protected void initInternal() throws LifecycleException {
    // NOOP - Don't register this Valve in JMX
    }
}

19 Source : StandardHostValve.java
with Apache License 2.0
from tryandcatch

/**
 * Valve that implements the default basic behavior for the
 * <code>StandardHost</code> container implementation.
 * <p>
 * <b>USAGE CONSTRAINT</b>:  This implementation is likely to be useful only
 * when processing HTTP requests.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 */
final clreplaced StandardHostValve extends ValveBase {

    private static final Log log = LogFactory.getLog(StandardHostValve.clreplaced);

    protected static final boolean STRICT_SERVLET_COMPLIANCE;

    protected static final boolean ACCESS_SESSION;

    static {
        STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
        String accessSession = System.getProperty("org.apache.catalina.core.StandardHostValve.ACCESS_SESSION");
        if (accessSession == null) {
            ACCESS_SESSION = STRICT_SERVLET_COMPLIANCE;
        } else {
            ACCESS_SESSION = Boolean.parseBoolean(accessSession);
        }
    }

    // ------------------------------------------------------ Constructor
    public StandardHostValve() {
        super(true);
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * The descriptive information related to this implementation.
     */
    private static final String info = "org.apache.catalina.core.StandardHostValve/1.0";

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager.getManager(Constants.Package);

    // ------------------------------------------------------------- Properties
    /**
     * Return descriptive information about this Valve implementation.
     */
    @Override
    public String getInfo() {
        return (info);
    }

    // --------------------------------------------------------- Public Methods
    /**
     * Select the appropriate child Context to process this request,
     * based on the specified request URI.  If no matching Context can
     * be found, return an appropriate HTTP error.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void invoke(Request request, Response response) throws IOException, ServletException {
        // Select the Context to be used for this Request
        Context context = request.getContext();
        if (context == null) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getString("standardHost.noContext"));
            return;
        }
        // Bind the context CL to the current thread
        if (context.getLoader() != null) {
            // Not started - it should check for availability first
            // This should eventually move to Engine, it's generic.
            if (Globals.IS_SECURITY_ENABLED) {
                PrivilegedAction<Void> pa = new PrivilegedSetTccl(context.getLoader().getClreplacedLoader());
                AccessController.doPrivileged(pa);
            } else {
                Thread.currentThread().setContextClreplacedLoader(context.getLoader().getClreplacedLoader());
            }
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(context.getPipeline().isAsyncSupported());
        }
        boolean asyncAtStart = request.isAsync();
        boolean asyncDispatching = request.isAsyncDispatching();
        if (asyncAtStart || context.fireRequestInitEvent(request)) {
            // Ask this Context to process this request. Requests that are in
            // async mode and are not being dispatched to this resource must be
            // in error and have been routed here to check for application
            // defined error pages.
            try {
                if (!asyncAtStart || asyncDispatching) {
                    context.getPipeline().getFirst().invoke(request, response);
                } else {
                    // Make sure this request/response is here because an error
                    // report is required.
                    if (!response.isErrorReportRequired()) {
                        throw new IllegalStateException(sm.getString("standardHost.asyncStateError"));
                    }
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                // If a new error occurred while trying to report a previous
                // error simply log the new error and allow the original error
                // to be reported.
                if (response.isErrorReportRequired()) {
                    container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
                } else {
                    request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
                    throwable(request, response, t);
                }
            }
            // Now that the request/response pair is back under container
            // control lift the suspension so that the error handling can
            // complete and/or the container can flush any remaining data
            response.setSuspended(false);
            Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
            // Protect against NPEs if the context was destroyed during a
            // long running request.
            if (!context.getState().isAvailable()) {
                return;
            }
            // Look for (and render if found) an application level error page
            if (response.isErrorReportRequired()) {
                if (t != null) {
                    throwable(request, response, t);
                } else {
                    status(request, response);
                }
            }
            if (!request.isAsync() && (!asyncAtStart || !response.isErrorReportRequired())) {
                context.fireRequestDestroyEvent(request);
            }
        }
        // Access a session (if present) to update last accessed time, based on a
        // strict interpretation of the specification
        if (ACCESS_SESSION) {
            request.getSession(false);
        }
        // Restore the context clreplacedloader
        if (Globals.IS_SECURITY_ENABLED) {
            PrivilegedAction<Void> pa = new PrivilegedSetTccl(StandardHostValve.clreplaced.getClreplacedLoader());
            AccessController.doPrivileged(pa);
        } else {
            Thread.currentThread().setContextClreplacedLoader(StandardHostValve.clreplaced.getClreplacedLoader());
        }
    }

    /**
     * Process Comet event.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     * @param event the event
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void event(Request request, Response response, CometEvent event) throws IOException, ServletException {
        // Select the Context to be used for this Request
        Context context = request.getContext();
        // Bind the context CL to the current thread
        if (context.getLoader() != null) {
            // Not started - it should check for availability first
            // This should eventually move to Engine, it's generic.
            Thread.currentThread().setContextClreplacedLoader(context.getLoader().getClreplacedLoader());
        }
        // Ask this Context to process this request
        context.getPipeline().getFirst().event(request, response, event);
        // Error page processing
        response.setSuspended(false);
        Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
        if (t != null) {
            throwable(request, response, t);
        } else {
            status(request, response);
        }
        // Access a session (if present) to update last accessed time, based on a
        // strict interpretation of the specification
        if (ACCESS_SESSION) {
            request.getSession(false);
        }
        // Restore the context clreplacedloader
        Thread.currentThread().setContextClreplacedLoader(StandardHostValve.clreplaced.getClreplacedLoader());
    }

    // -------------------------------------------------------- Private Methods
    /**
     * Handle the HTTP status code (and corresponding message) generated
     * while processing the specified Request to produce the specified
     * Response.  Any exceptions that occur during generation of the error
     * report are logged and swallowed.
     *
     * @param request The request being processed
     * @param response The response being generated
     */
    private void status(Request request, Response response) {
        int statusCode = response.getStatus();
        // Handle a custom error page for this status code
        Context context = request.getContext();
        if (context == null)
            return;
        /* Only look for error pages when isError() is set.
         * isError() is set when response.sendError() is invoked. This
         * allows custom error pages without relying on default from
         * web.xml.
         */
        if (!response.isError())
            return;
        ErrorPage errorPage = context.findErrorPage(statusCode);
        if (errorPage == null) {
            // Look for a default error page
            errorPage = context.findErrorPage(0);
        }
        if (errorPage != null && response.isErrorReportRequired()) {
            response.setAppCommitted(false);
            request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, Integer.valueOf(statusCode));
            String message = response.getMessage();
            if (message == null)
                message = "";
            request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
            request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
            request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);
            Wrapper wrapper = request.getWrapper();
            if (wrapper != null)
                request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
            request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
            if (custom(request, response, errorPage)) {
                response.setErrorReported();
                try {
                    response.finishResponse();
                } catch (ClientAbortException e) {
                // Ignore
                } catch (IOException e) {
                    container.getLogger().warn("Exception Processing " + errorPage, e);
                }
            }
        }
    }

    /**
     * Handle the specified Throwable encountered while processing
     * the specified Request to produce the specified Response.  Any
     * exceptions that occur during generation of the exception report are
     * logged and swallowed.
     *
     * @param request The request being processed
     * @param response The response being generated
     * @param throwable The exception that occurred (which possibly wraps
     *  a root cause exception
     */
    protected void throwable(Request request, Response response, Throwable throwable) {
        Context context = request.getContext();
        if (context == null)
            return;
        Throwable realError = throwable;
        if (realError instanceof ServletException) {
            realError = ((ServletException) realError).getRootCause();
            if (realError == null) {
                realError = throwable;
            }
        }
        // If this is an aborted request from a client just log it and return
        if (realError instanceof ClientAbortException) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("standardHost.clientAbort", realError.getCause().getMessage()));
            }
            return;
        }
        ErrorPage errorPage = findErrorPage(context, throwable);
        if ((errorPage == null) && (realError != throwable)) {
            errorPage = findErrorPage(context, realError);
        }
        if (errorPage != null) {
            if (response.setErrorReported()) {
                response.setAppCommitted(false);
                request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
                request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);
                request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, Integer.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
                request.setAttribute(RequestDispatcher.ERROR_MESSAGE, throwable.getMessage());
                request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, realError);
                Wrapper wrapper = request.getWrapper();
                if (wrapper != null)
                    request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
                request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
                request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, realError.getClreplaced());
                if (custom(request, response, errorPage)) {
                    try {
                        response.finishResponse();
                    } catch (IOException e) {
                        container.getLogger().warn("Exception Processing " + errorPage, e);
                    }
                }
            }
        } else {
            // A custom error-page has not been defined for the exception
            // that was thrown during request processing. Check if an
            // error-page for error code 500 was specified and if so,
            // send that page back as the response.
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            // The response is an error
            response.setError();
            status(request, response);
        }
    }

    /**
     * Handle an HTTP status code or Java exception by forwarding control
     * to the location included in the specified errorPage object.  It is
     * replacedumed that the caller has already recorded any request attributes
     * that are to be forwarded to this page.  Return <code>true</code> if
     * we successfully utilized the specified error page location, or
     * <code>false</code> if the default error report should be rendered.
     *
     * @param request The request being processed
     * @param response The response being generated
     * @param errorPage The errorPage directive we are obeying
     */
    private boolean custom(Request request, Response response, ErrorPage errorPage) {
        if (container.getLogger().isDebugEnabled())
            container.getLogger().debug("Processing " + errorPage);
        try {
            // Forward control to the specified location
            ServletContext servletContext = request.getContext().getServletContext();
            RequestDispatcher rd = servletContext.getRequestDispatcher(errorPage.getLocation());
            if (rd == null) {
                container.getLogger().error(sm.getString("standardHostValue.customStatusFailed", errorPage.getLocation()));
                return false;
            }
            if (response.isCommitted()) {
                // Response is committed - including the error page is the
                // best we can do
                rd.include(request.getRequest(), response.getResponse());
            } else {
                // Reset the response (keeping the real error code and message)
                response.resetBuffer(true);
                response.setContentLength(-1);
                rd.forward(request.getRequest(), response.getResponse());
                // If we forward, the response is suspended again
                response.setSuspended(false);
            }
            // Indicate that we have successfully processed this custom page
            return (true);
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            // Report our failure to process this custom page
            container.getLogger().error("Exception Processing " + errorPage, t);
            return (false);
        }
    }

    /**
     * Find and return the ErrorPage instance for the specified exception's
     * clreplaced, or an ErrorPage instance for the closest superclreplaced for which
     * there is such a definition.  If no replacedociated ErrorPage instance is
     * found, return <code>null</code>.
     *
     * @param context The Context in which to search
     * @param exception The exception for which to find an ErrorPage
     */
    private static ErrorPage findErrorPage(Context context, Throwable exception) {
        if (exception == null)
            return (null);
        Clreplaced<?> clazz = exception.getClreplaced();
        String name = clazz.getName();
        while (!Object.clreplaced.equals(clazz)) {
            ErrorPage errorPage = context.findErrorPage(name);
            if (errorPage != null)
                return (errorPage);
            clazz = clazz.getSuperclreplaced();
            if (clazz == null)
                break;
            name = clazz.getName();
        }
        return (null);
    }
}

See More Examples