001package ca.uhn.fhir.jpa.provider;
002
003import ca.uhn.fhir.i18n.Msg;
004import ca.uhn.fhir.context.FhirContext;
005import ca.uhn.fhir.jpa.api.config.DaoConfig;
006import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
007import ca.uhn.fhir.jpa.api.model.ExpungeOutcome;
008import ca.uhn.fhir.jpa.model.util.JpaConstants;
009import ca.uhn.fhir.rest.param.DateRangeParam;
010import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
011import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
012import ca.uhn.fhir.util.ParametersUtil;
013import org.apache.commons.lang3.StringUtils;
014import org.hl7.fhir.instance.model.api.IBaseParameters;
015import org.hl7.fhir.instance.model.api.IPrimitiveType;
016import org.jboss.logging.MDC;
017import org.springframework.beans.factory.annotation.Autowired;
018
019import javax.servlet.http.HttpServletRequest;
020import java.util.Date;
021import java.util.Enumeration;
022import java.util.Set;
023import java.util.TreeSet;
024
025/*
026 * #%L
027 * HAPI FHIR Storage api
028 * %%
029 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
030 * %%
031 * Licensed under the Apache License, Version 2.0 (the "License");
032 * you may not use this file except in compliance with the License.
033 * You may obtain a copy of the License at
034 *
035 *      http://www.apache.org/licenses/LICENSE-2.0
036 *
037 * Unless required by applicable law or agreed to in writing, software
038 * distributed under the License is distributed on an "AS IS" BASIS,
039 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
040 * See the License for the specific language governing permissions and
041 * limitations under the License.
042 * #L%
043 */
044
045public class BaseJpaProvider {
046        public static final String REMOTE_ADDR = "req.remoteAddr";
047        public static final String REMOTE_UA = "req.userAgent";
048        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaProvider.class);
049        @Autowired
050        protected DaoConfig myDaoConfig;
051        @Autowired
052        private FhirContext myContext;
053
054        public BaseJpaProvider() {
055                super();
056        }
057
058        public void setDaoConfigForUnitTest(DaoConfig theDaoConfig) {
059                myDaoConfig = theDaoConfig;
060        }
061
062        protected ExpungeOptions createExpungeOptions(IPrimitiveType<? extends Integer> theLimit, IPrimitiveType<? extends Boolean> theExpungeDeletedResources, IPrimitiveType<? extends Boolean> theExpungeOldVersions, IPrimitiveType<? extends Boolean> theExpungeEverything) {
063                ExpungeOptions options = new ExpungeOptions();
064                if (theLimit != null && theLimit.getValue() != null) {
065                        options.setLimit(theLimit.getValue());
066                }
067
068                if (theExpungeOldVersions != null && theExpungeOldVersions.getValue() != null) {
069                        options.setExpungeOldVersions(theExpungeOldVersions.getValue());
070                }
071
072                if (theExpungeDeletedResources != null && theExpungeDeletedResources.getValue() != null) {
073                        options.setExpungeDeletedResources(theExpungeDeletedResources.getValue());
074                }
075
076                if (theExpungeEverything != null && theExpungeEverything.getValue() != null) {
077                        options.setExpungeEverything(theExpungeEverything.getValue());
078                }
079                return options;
080        }
081
082        protected IBaseParameters createExpungeResponse(ExpungeOutcome theOutcome) {
083                IBaseParameters parameters = ParametersUtil.newInstance(getContext());
084                String value = Integer.toString(theOutcome.getDeletedCount());
085                ParametersUtil.addParameterToParameters(getContext(), parameters, JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, "integer", value);
086                return parameters;
087        }
088
089        /**
090         * @param theRequest The servlet request
091         */
092        public void endRequest(HttpServletRequest theRequest) {
093                MDC.remove(REMOTE_ADDR);
094                MDC.remove(REMOTE_UA);
095        }
096
097        public void endRequest(ServletRequestDetails theRequest) {
098                endRequest(theRequest.getServletRequest());
099        }
100
101        public FhirContext getContext() {
102                return myContext;
103        }
104
105        public void setContext(FhirContext theContext) {
106                myContext = theContext;
107        }
108
109        protected DateRangeParam processSinceOrAt(Date theSince, DateRangeParam theAt) {
110                boolean haveAt = theAt != null && (theAt.getLowerBoundAsInstant() != null || theAt.getUpperBoundAsInstant() != null);
111                if (haveAt && theSince != null) {
112                        String msg = getContext().getLocalizer().getMessage(BaseJpaProvider.class, "cantCombintAtAndSince");
113                        throw new InvalidRequestException(Msg.code(553) + msg);
114                }
115
116                if (haveAt) {
117                        return theAt;
118                }
119
120                return new DateRangeParam(theSince, null);
121        }
122
123        public void startRequest(HttpServletRequest theRequest) {
124                if (theRequest == null) {
125                        return;
126                }
127
128                Set<String> headerNames = new TreeSet<String>();
129                for (Enumeration<String> enums = theRequest.getHeaderNames(); enums.hasMoreElements(); ) {
130                        headerNames.add(enums.nextElement());
131                }
132                ourLog.debug("Request headers: {}", headerNames);
133
134                Enumeration<String> forwardedFors = theRequest.getHeaders("x-forwarded-for");
135                StringBuilder b = new StringBuilder();
136                for (Enumeration<String> enums = forwardedFors; enums != null && enums.hasMoreElements(); ) {
137                        if (b.length() > 0) {
138                                b.append(" / ");
139                        }
140                        b.append(enums.nextElement());
141                }
142
143                String forwardedFor = b.toString();
144                String ip = theRequest.getRemoteAddr();
145                if (StringUtils.isBlank(forwardedFor)) {
146                        org.slf4j.MDC.put(REMOTE_ADDR, ip);
147                        ourLog.debug("Request is from address: {}", ip);
148                } else {
149                        org.slf4j.MDC.put(REMOTE_ADDR, forwardedFor);
150                        ourLog.debug("Request is from forwarded address: {}", forwardedFor);
151                }
152
153                String userAgent = StringUtils.defaultString(theRequest.getHeader("user-agent"));
154                org.slf4j.MDC.put(REMOTE_UA, userAgent);
155
156        }
157
158        public void startRequest(ServletRequestDetails theRequest) {
159                startRequest(theRequest.getServletRequest());
160        }
161
162
163}