001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.rest.rrpc; 018 019import static org.apache.juneau.common.utils.StringUtils.*; 020 021import java.io.*; 022import java.lang.reflect.*; 023 024import org.apache.juneau.http.remote.*; 025import org.apache.juneau.http.response.*; 026import org.apache.juneau.parser.*; 027import org.apache.juneau.rest.*; 028 029/** 030 * A session for a single HTTP request against an RRPC Java method. 031 * 032 * <h5 class='section'>Notes:</h5><ul> 033 * <li class='warn'>This class is not thread safe. 034 * </ul> 035 * 036 * <h5 class='section'>See Also:</h5><ul> 037 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a> 038 * </ul> 039 */ 040public class RrpcRestOpSession extends RestOpSession { 041 042 //----------------------------------------------------------------------------------------------------------------- 043 // Static 044 //----------------------------------------------------------------------------------------------------------------- 045 046 /** 047 * Static creator. 048 * 049 * @param ctx The context of the RRPC Java Method. 050 * @param session The REST session creating this session. 051 * @return A new builder. 052 */ 053 public static Builder create(RrpcRestOpContext ctx, RestSession session) { 054 return new Builder(ctx, session); 055 056 } 057 058 //----------------------------------------------------------------------------------------------------------------- 059 // Builder 060 //----------------------------------------------------------------------------------------------------------------- 061 062 /** 063 * Builder class. 064 */ 065 public static class Builder extends RestOpSession.Builder { 066 067 RrpcRestOpContext ctx; 068 069 /** 070 * Constructor. 071 * 072 * @param ctx The context object of the RRPC Java method. 073 * @param session The REST session. 074 */ 075 public Builder(RrpcRestOpContext ctx, RestSession session) { 076 super(ctx, session); 077 this.ctx = ctx; 078 } 079 080 @Override 081 public RrpcRestOpSession build() { 082 return new RrpcRestOpSession(this); 083 } 084 085 } 086 087 //----------------------------------------------------------------------------------------------------------------- 088 // Instance 089 //----------------------------------------------------------------------------------------------------------------- 090 091 private final RrpcRestOpContext ctx; 092 093 /** 094 * Constructor. 095 * 096 * @param builder The builder for this object. 097 */ 098 protected RrpcRestOpSession(Builder builder) { 099 super(builder); 100 ctx = builder.ctx; 101 } 102 103 @Override 104 public void run() throws Throwable { 105 106 super.run(); 107 108 RestRequest req = getRequest(); 109 RestResponse res = getResponse(); 110 RestSession session = getRestSession(); 111 112 final Object o = res.hasContent() ? res.getContent(Object.class) : null; 113 114 if ("GET".equals(session.getMethod())) { 115 res.setContent(ctx.getMeta().getMethodsByPath().keySet()); 116 return; 117 118 } else if ("POST".equals(session.getMethod())) { 119 String pip = session.getUrlPath().getPath(); 120 if (pip.indexOf('/') != -1) 121 pip = pip.substring(pip.lastIndexOf('/')+1); 122 pip = urlDecode(pip); 123 RrpcInterfaceMethodMeta rmm = ctx.getMeta().getMethodMetaByPath(pip); 124 if (rmm != null) { 125 Method m = rmm.getJavaMethod(); 126 try { 127 // Parse the args and invoke the method. 128 Parser p = req.getContent().getParserMatch().get().getParser(); 129 Object[] args = null; 130 if (m.getGenericParameterTypes().length == 0) 131 args = new Object[0]; 132 else { 133 try (Closeable in = p.isReaderParser() ? req.getReader() : req.getInputStream()) { 134 args = p.parseArgs(in, m.getGenericParameterTypes()); 135 } 136 } 137 res.setContent(m.invoke(o, args)); 138 return; 139 } catch (BasicHttpException e) { 140 throw e; 141 } catch (Exception e) { 142 throw new InternalServerError(e); 143 } 144 } 145 } 146 throw new NotFound(); 147 } 148}